[Satellite] Use satellite data mode for UX visibility

- Use SatelliteManager#getSatelliteDataSupportMode() to check data
   restricted or not.

Flag: EXEMPT bug fix
Bug: b/401043401
Test: atest pass
Test: Manual test
Change-Id: I6f3e25610717eca0f6e871a9e1158422659058ea
This commit is contained in:
tom hsu
2025-03-19 08:53:27 +00:00
parent 339367886d
commit dc788ed9d1
4 changed files with 215 additions and 59 deletions

View File

@@ -202,9 +202,6 @@ open class SatelliteRepository(
* e.g. "com.android.settings"
*/
open fun getSatelliteDataOptimizedApps(): List<String> {
if (!Flags.satellite25q4Apis()) {
return emptyList()
}
val satelliteManager: SatelliteManager? =
context.getSystemService(SatelliteManager::class.java)
if (satelliteManager == null) {

View File

@@ -16,10 +16,17 @@
package com.android.settings.network.telephony.satellite;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.PersistableBundle;
import android.telephony.satellite.SatelliteManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -27,20 +34,23 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.internal.telephony.flags.Flags;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.SatelliteRepository;
import com.android.settings.network.telephony.TelephonyBasePreferenceController;
import com.android.settingslib.Utils;
import java.util.List;
import java.util.Set;
/** A controller to show some of apps info which supported on Satellite service. */
public class SatelliteAppListCategoryController extends BasePreferenceController {
public class SatelliteAppListCategoryController extends TelephonyBasePreferenceController {
private static final String TAG = "SatelliteAppListCategoryController";
@VisibleForTesting
static final int MAXIMUM_OF_PREFERENCE_AMOUNT = 3;
private List<String> mPackageNameList;
private boolean mIsSmsAvailable;
private boolean mIsDataAvailable;
private boolean mIsSatelliteEligible;
private PersistableBundle mConfigBundle = new PersistableBundle();
public SatelliteAppListCategoryController(
@NonNull Context context,
@@ -49,14 +59,14 @@ public class SatelliteAppListCategoryController extends BasePreferenceController
}
/** Initialize the necessary applications' data*/
public void init() {
SatelliteRepository satelliteRepository = new SatelliteRepository(mContext);
init(satelliteRepository);
}
@VisibleForTesting
void init(@NonNull SatelliteRepository satelliteRepository) {
mPackageNameList = satelliteRepository.getSatelliteDataOptimizedApps();
public void init(int subId, @NonNull PersistableBundle configBundle, boolean isSmsAvailable,
boolean isDataAvailable) {
mSubId = subId;
mConfigBundle = configBundle;
mIsSmsAvailable = isSmsAvailable;
mIsDataAvailable = isDataAvailable;
mPackageNameList = getSatelliteDataOptimizedApps();
mIsSatelliteEligible = isSatelliteEligible();
}
@Override
@@ -78,13 +88,53 @@ public class SatelliteAppListCategoryController extends BasePreferenceController
}
@Override
public int getAvailabilityStatus() {
if (!Flags.satellite25q4Apis()) {
public int getAvailabilityStatus(int subId) {
// Only when carrier support entitlement check, it shall check account eligible or not.
if (mConfigBundle.getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL)
&& !mIsSatelliteEligible) {
return CONDITIONALLY_UNAVAILABLE;
}
return mPackageNameList.isEmpty()
? CONDITIONALLY_UNAVAILABLE
: AVAILABLE;
Log.d(TAG, "Supported apps have " + mPackageNameList.size());
return mIsDataAvailable && !mPackageNameList.isEmpty()
? AVAILABLE_UNSEARCHABLE
: CONDITIONALLY_UNAVAILABLE;
}
@VisibleForTesting
protected List<String> getSatelliteDataOptimizedApps() {
SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
if (satelliteManager == null) {
return List.of();
}
try {
return satelliteManager.getSatelliteDataOptimizedApps();
} catch (IllegalStateException e) {
Log.d(TAG, "getSatelliteDataOptimizedApps failed due to " + e);
}
return List.of();
}
@VisibleForTesting
protected boolean isSatelliteEligible() {
if (mConfigBundle.getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT)
== CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
return mIsSmsAvailable;
}
SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
if (satelliteManager == null) {
Log.d(TAG, "SatelliteManager is null.");
return false;
}
try {
Set<Integer> restrictionReason =
satelliteManager.getAttachRestrictionReasonsForCarrier(mSubId);
return !restrictionReason.contains(
SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT);
} catch (SecurityException | IllegalStateException | IllegalArgumentException ex) {
Log.d(TAG, "Error to getAttachRestrictionReasonsForCarrier : " + ex);
return false;
}
}
static ApplicationInfo getApplicationInfo(Context context, String packageName) {

View File

@@ -23,6 +23,7 @@ import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUP
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING;
import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
import android.app.Activity;
import android.app.settings.SettingsEnums;
@@ -78,35 +79,30 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
public void onAttach(Context context) {
super.onAttach(context);
mActivity = getActivity();
mSubId = mActivity.getIntent().getIntExtra(SUB_ID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mConfigBundle = fetchCarrierConfigData(mSubId);
mIsServiceDataType = getIntent().getBooleanExtra(EXTRA_IS_SERVICE_DATA_TYPE, false);
mIsSmsAvailableForManualType = getIntent().getBooleanExtra(
EXTRA_IS_SMS_AVAILABLE_FOR_MANUAL_TYPE, false);
use(SatelliteAppListCategoryController.class).init();
use(SatelliteSettingAboutContentController.class).init(mSubId);
use(SatelliteSettingAccountInfoController.class).init(mSubId, mConfigBundle,
mIsSmsAvailableForManualType, mIsServiceDataType);
use(SatelliteSettingFooterController.class).init(mSubId, mConfigBundle);
}
@Override
public void onCreate(@NonNull Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSatelliteManager = mActivity.getSystemService(SatelliteManager.class);
if (mSatelliteManager == null) {
Log.d(TAG, "SatelliteManager is null, do nothing.");
finish();
return;
}
if (!isSatelliteAttachSupported(mSubId)) {
mSubId = mActivity.getIntent().getIntExtra(SUB_ID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mConfigBundle = fetchCarrierConfigData(mSubId);
if (!isSatelliteAttachSupported()) {
Log.d(TAG, "SatelliteSettings: KEY_SATELLITE_ATTACH_SUPPORTED_BOOL is false, "
+ "do nothing.");
finish();
}
mIsServiceDataType = getIntent().getBooleanExtra(EXTRA_IS_SERVICE_DATA_TYPE, false);
mIsSmsAvailableForManualType = getIntent().getBooleanExtra(
EXTRA_IS_SMS_AVAILABLE_FOR_MANUAL_TYPE, false);
boolean isDataAvailableAndNotRestricted = isDataAvailableAndNotRestricted();
use(SatelliteAppListCategoryController.class).init(mSubId, mConfigBundle,
mIsSmsAvailableForManualType, isDataAvailableAndNotRestricted);
use(SatelliteSettingAboutContentController.class).init(mSubId);
use(SatelliteSettingAccountInfoController.class).init(mSubId, mConfigBundle,
mIsSmsAvailableForManualType, isDataAvailableAndNotRestricted);
use(SatelliteSettingFooterController.class).init(mSubId, mConfigBundle);
}
@Override
@@ -152,6 +148,7 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
try {
Set<Integer> restrictionReason =
mSatelliteManager.getAttachRestrictionReasonsForCarrier(mSubId);
Log.d(TAG, "Restriction reason : " + restrictionReason);
return !restrictionReason.contains(
SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT);
} catch (SecurityException | IllegalStateException | IllegalArgumentException ex) {
@@ -186,10 +183,26 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC);
}
private boolean isSatelliteAttachSupported(int subId) {
private boolean isSatelliteAttachSupported() {
return mConfigBundle.getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
}
private boolean isDataAvailableAndNotRestricted() {
return getIntent().getBooleanExtra(EXTRA_IS_SERVICE_DATA_TYPE, false)
&& !isDataRestricted();
}
private boolean isDataRestricted() {
int dataMode = SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
try {
dataMode = mSatelliteManager.getSatelliteDataSupportMode(mSubId);
Log.d(TAG, "Data mode : " + dataMode);
} catch (IllegalStateException e) {
Log.d(TAG, "Failed to get data mode : " + e);
}
return dataMode <= SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
}
private static void loge(String message) {
Log.e(TAG, message);
}

View File

@@ -16,7 +16,11 @@
package com.android.settings.network.telephony.satellite;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.android.settings.network.telephony.satellite.SatelliteAppListCategoryController.MAXIMUM_OF_PREFERENCE_AMOUNT;
@@ -31,6 +35,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Looper;
import android.os.PersistableBundle;
import android.platform.test.annotations.EnableFlags;
import androidx.preference.PreferenceCategory;
@@ -39,7 +44,6 @@ import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.telephony.flags.Flags;
import com.android.settings.network.SatelliteRepository;
import org.junit.Before;
import org.junit.Rule;
@@ -48,25 +52,23 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.util.Collections;
import java.util.List;
public class SatelliteAppListCategoryControllerTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private static final int TEST_SUB_ID = 0;
private static final List<String> PACKAGE_NAMES = List.of("com.android.settings",
"com.android.apps.messaging", "com.android.dialer", "com.android.systemui");
private static final String KEY = "SatelliteAppListCategoryControllerTest";
@Mock
private PackageManager mPackageManager;
@Mock
private SatelliteRepository mRepository;
private Context mContext;
private SatelliteAppListCategoryController mController;
private PersistableBundle mPersistableBundle = new PersistableBundle();
@Before
public void setUp() {
@@ -75,16 +77,28 @@ public class SatelliteAppListCategoryControllerTest {
}
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getPackageManager()).thenReturn(mPackageManager);
mPersistableBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
CARRIER_ROAMING_NTN_CONNECT_MANUAL);
mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false);
}
@Test
@EnableFlags(Flags.FLAG_SATELLITE_25Q4_APIS)
public void displayPreference_has4SatSupportedApps_showMaxPreference() throws Exception {
when(mRepository.getSatelliteDataOptimizedApps()).thenReturn(PACKAGE_NAMES);
when(mPackageManager.getApplicationInfoAsUser(any(), anyInt(), anyInt())).thenReturn(
new ApplicationInfo());
mController = new SatelliteAppListCategoryController(mContext, KEY);
mController.init(mRepository);
mController = new SatelliteAppListCategoryController(mContext, KEY) {
@Override
protected boolean isSatelliteEligible() {
return true;
}
@Override
protected List<String> getSatelliteDataOptimizedApps() {
return PACKAGE_NAMES;
}
};
mController.init(TEST_SUB_ID, mPersistableBundle, true, true);
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext);
PreferenceCategory category = new PreferenceCategory(mContext);
@@ -100,25 +114,107 @@ public class SatelliteAppListCategoryControllerTest {
@Test
@EnableFlags(Flags.FLAG_SATELLITE_25Q4_APIS)
public void getAvailabilityStatus_hasSatSupportedApps_returnAvailable() {
when(mRepository.getSatelliteDataOptimizedApps()).thenReturn(PACKAGE_NAMES);
mController = new SatelliteAppListCategoryController(mContext, KEY);
mController.init(mRepository);
mController = new SatelliteAppListCategoryController(mContext, KEY) {
@Override
protected boolean isSatelliteEligible() {
return true;
}
int result = mController.getAvailabilityStatus();
@Override
protected List<String> getSatelliteDataOptimizedApps() {
return PACKAGE_NAMES;
}
};
mController.init(TEST_SUB_ID, mPersistableBundle, true, true);
assertThat(result).isEqualTo(AVAILABLE);
int result = mController.getAvailabilityStatus(TEST_SUB_ID);
assertThat(result).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
@EnableFlags(Flags.FLAG_SATELLITE_25Q4_APIS)
public void getAvailabilityStatus_noSatSupportedApps_returnUnavailable() {
List<String> packageNames = Collections.emptyList();
when(mRepository.getSatelliteDataOptimizedApps()).thenReturn(packageNames);
mController = new SatelliteAppListCategoryController(mContext, KEY);
mController.init(mRepository);
mController = new SatelliteAppListCategoryController(mContext, KEY) {
@Override
protected boolean isSatelliteEligible() {
return true;
}
int result = mController.getAvailabilityStatus();
@Override
protected List<String> getSatelliteDataOptimizedApps() {
return List.of();
}
};
mController.init(TEST_SUB_ID, mPersistableBundle, true, true);
int result = mController.getAvailabilityStatus(TEST_SUB_ID);
assertThat(result).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
@EnableFlags(Flags.FLAG_SATELLITE_25Q4_APIS)
public void getAvailabilityStatus_dataUnavailable_returnUnavailable() {
mController = new SatelliteAppListCategoryController(mContext, KEY) {
@Override
protected boolean isSatelliteEligible() {
return true;
}
@Override
protected List<String> getSatelliteDataOptimizedApps() {
return PACKAGE_NAMES;
}
};
mController.init(TEST_SUB_ID, mPersistableBundle, true, false);
int result = mController.getAvailabilityStatus(TEST_SUB_ID);
assertThat(result).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
@EnableFlags(Flags.FLAG_SATELLITE_25Q4_APIS)
public void getAvailabilityStatus_entitlementSupportedButAccountIneligible_returnUnavailable() {
mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
mController = new SatelliteAppListCategoryController(mContext, KEY) {
@Override
protected boolean isSatelliteEligible() {
return false;
}
@Override
protected List<String> getSatelliteDataOptimizedApps() {
return PACKAGE_NAMES;
}
};
mController.init(TEST_SUB_ID, mPersistableBundle, true, true);
int result = mController.getAvailabilityStatus(TEST_SUB_ID);
assertThat(result).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
@EnableFlags(Flags.FLAG_SATELLITE_25Q4_APIS)
public void getAvailabilityStatus_entitlementSupportedAndAccountEligible_returnAvailable() {
mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
mController = new SatelliteAppListCategoryController(mContext, KEY) {
@Override
protected boolean isSatelliteEligible() {
return true;
}
@Override
protected List<String> getSatelliteDataOptimizedApps() {
return PACKAGE_NAMES;
}
};
mController.init(TEST_SUB_ID, mPersistableBundle, true, true);
int result = mController.getAvailabilityStatus(TEST_SUB_ID);
assertThat(result).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
}