Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc788ed9 authored by tom hsu's avatar tom hsu
Browse files

[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
parent 33936788
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -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) {
+67 −17
Original line number Diff line number Diff line
@@ -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) {
+33 −20
Original line number Diff line number Diff line
@@ -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);
    }
+116 −20
Original line number Diff line number Diff line
@@ -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;
            }

            @Override
            protected List<String> getSatelliteDataOptimizedApps() {
                return PACKAGE_NAMES;
            }
        };
        mController.init(TEST_SUB_ID, mPersistableBundle, true, true);

        int result = mController.getAvailabilityStatus();
        int result = mController.getAvailabilityStatus(TEST_SUB_ID);

        assertThat(result).isEqualTo(AVAILABLE);
        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);
    }
}