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

Commit 808dc46b authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Disabled Settings preference in case Satellite's conditions." into main

parents c3dac341 9ca87091
Loading
Loading
Loading
Loading
+83 −12
Original line number Diff line number Diff line
@@ -16,9 +16,6 @@

package com.android.settings.network.telephony;

import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;

import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.getNetworkModePreferenceType;
import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.setAllowedNetworkTypes;
import static com.android.settings.network.telephony.mode.NetworkModes.addNrToLteNetworkMode;
@@ -33,15 +30,17 @@ import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteModemStateCallback;
import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.ListPreference;
import androidx.preference.ListPreferenceDialogFragmentCompat;
import androidx.preference.Preference;
@@ -67,7 +66,7 @@ import java.util.stream.Stream;
 */
public class EnabledNetworkModePreferenceController extends
        BasePreferenceController implements
        ListPreference.OnPreferenceChangeListener, LifecycleObserver,
        ListPreference.OnPreferenceChangeListener, DefaultLifecycleObserver,
        SubscriptionsChangeListener.SubscriptionsChangeListenerClient {

    private static final String LOG_TAG = "EnabledNetworkMode";
@@ -83,6 +82,43 @@ public class EnabledNetworkModePreferenceController extends
    private PhoneCallStateTelephonyCallback mTelephonyCallback;
    private FragmentManager mFragmentManager;
    private LifecycleOwner mViewLifecycleOwner;
    private SatelliteManager mSatelliteManager;
    private boolean mIsSatelliteSessionStarted = false;
    private boolean mIsCurrentSubscriptionForSatellite = false;

    @VisibleForTesting
    final SelectedNbIotSatelliteSubscriptionCallback mSelectedNbIotSatelliteSubscriptionCallback =
            new SelectedNbIotSatelliteSubscriptionCallback() {
                @Override
                public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
                    mIsCurrentSubscriptionForSatellite = selectedSubId == mSubId;
                    updatePreference();
                }
            };

    @VisibleForTesting
    final SatelliteModemStateCallback mSatelliteModemStateCallback =
            new SatelliteModemStateCallback() {
                @Override
                public void onSatelliteModemStateChanged(int state) {
                    switch (state) {
                        case SatelliteManager.SATELLITE_MODEM_STATE_OFF:
                        case SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE:
                        case SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN:
                            if (mIsSatelliteSessionStarted) {
                                mIsSatelliteSessionStarted = false;
                                updatePreference();
                            }
                            break;
                        default:
                            if (!mIsSatelliteSessionStarted) {
                                mIsSatelliteSessionStarted = true;
                                updatePreference();
                            }
                            break;
                    }
                }
            };

    public EnabledNetworkModePreferenceController(Context context, String key) {
        super(context, key);
@@ -90,6 +126,7 @@ public class EnabledNetworkModePreferenceController extends
        if (mTelephonyCallback == null) {
            mTelephonyCallback = new PhoneCallStateTelephonyCallback();
        }
        mSatelliteManager = context.getSystemService(SatelliteManager.class);
    }

    @Override
@@ -103,8 +140,22 @@ public class EnabledNetworkModePreferenceController extends
        return mCallState == TelephonyManager.CALL_STATE_IDLE;
    }

    @OnLifecycleEvent(ON_START)
    public void onStart() {
    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
            if (mSatelliteManager != null) {
                try {
                    mSatelliteManager.registerForModemStateChanged(
                            mContext.getMainExecutor(), mSatelliteModemStateCallback);
                    mSatelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
                            mContext.getMainExecutor(),
                            mSelectedNbIotSatelliteSubscriptionCallback);
                } catch (IllegalStateException e) {
                    Log.w(LOG_TAG, "IllegalStateException : " + e);
                }
            }
        }

        mSubscriptionsListener.start();
        if (mAllowedNetworkTypesListener == null || mTelephonyCallback == null) {
            return;
@@ -113,9 +164,21 @@ public class EnabledNetworkModePreferenceController extends
        mTelephonyCallback.register(mTelephonyManager, mSubId);
    }

    @OnLifecycleEvent(ON_STOP)
    public void onStop() {
    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        mSubscriptionsListener.stop();
        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
            if (mSatelliteManager != null) {
                try {
                    mSatelliteManager.unregisterForModemStateChanged(mSatelliteModemStateCallback);
                    mSatelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
                            mSelectedNbIotSatelliteSubscriptionCallback);
                } catch (IllegalStateException e) {
                    Log.w(LOG_TAG, "IllegalStateException : " + e);
                }
            }
        }

        if (mAllowedNetworkTypesListener == null || mTelephonyCallback == null) {
            return;
        }
@@ -147,7 +210,7 @@ public class EnabledNetworkModePreferenceController extends
        listPreference.setEntryValues(mBuilder.getEntryValues());
        listPreference.setValue(Integer.toString(mBuilder.getSelectedEntryValue()));
        listPreference.setSummary(mBuilder.getSummary());
        boolean listPreferenceEnabled = isCallStateIdle();
        boolean listPreferenceEnabled = isPreferenceShallEnabled();
        listPreference.setEnabled(listPreferenceEnabled);
        if (!listPreferenceEnabled) {
            // If dialog is already opened when ListPreference disabled, dismiss them.
@@ -203,6 +266,14 @@ public class EnabledNetworkModePreferenceController extends
        }
    }

    private boolean isPreferenceShallEnabled() {
        Log.d(LOG_TAG, "isPreferenceShallEnabled, mIsSatelliteSessionStarted : "
                + mIsSatelliteSessionStarted + " / mIsCurrentSubscriptionForSatellite : "
                + mIsCurrentSubscriptionForSatellite);
        return isCallStateIdle()
                && !(mIsSatelliteSessionStarted && mIsCurrentSubscriptionForSatellite);
    }

    private final class PreferenceEntriesBuilder {
        private CarrierConfigCache mCarrierConfigCache;
        private Context mContext;
+93 −4
Original line number Diff line number Diff line
@@ -24,10 +24,18 @@ import android.telephony.CarrierConfigManager;
import android.telephony.RadioAccessFamily;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteModemStateCallback;
import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
@@ -38,17 +46,56 @@ import com.android.settings.network.telephony.mode.NetworkModes;
 * Preference controller for "Preferred network mode"
 */
public class PreferredNetworkModePreferenceController extends BasePreferenceController
        implements ListPreference.OnPreferenceChangeListener {
        implements ListPreference.OnPreferenceChangeListener, DefaultLifecycleObserver {
    private static final String TAG = "PrefNetworkModeCtrl";

    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private CarrierConfigCache mCarrierConfigCache;
    private TelephonyManager mTelephonyManager;
    private boolean mIsGlobalCdma;
    private SatelliteManager mSatelliteManager;
    private Preference mPreference;
    private boolean mIsSatelliteSessionStarted = false;
    private boolean mIsCurrentSubscriptionForSatellite = false;

    @VisibleForTesting
    final SelectedNbIotSatelliteSubscriptionCallback mSelectedNbIotSatelliteSubscriptionCallback =
            new SelectedNbIotSatelliteSubscriptionCallback() {
                @Override
                public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
                    mIsCurrentSubscriptionForSatellite = selectedSubId == mSubId;
                    updateState(mPreference);
                }
            };

    @VisibleForTesting
    final SatelliteModemStateCallback mSatelliteModemStateCallback =
            new SatelliteModemStateCallback() {
                @Override
                public void onSatelliteModemStateChanged(int state) {
                    switch (state) {
                        case SatelliteManager.SATELLITE_MODEM_STATE_OFF:
                        case SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE:
                        case SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN:
                            if (mIsSatelliteSessionStarted) {
                                mIsSatelliteSessionStarted = false;
                                updateState(mPreference);
                            }
                            break;
                        default:
                            if (!mIsSatelliteSessionStarted) {
                                mIsSatelliteSessionStarted = true;
                                updateState(mPreference);
                            }
                            break;
                    }
                }
            };

    public PreferredNetworkModePreferenceController(Context context, String key) {
        super(context, key);
        mCarrierConfigCache = CarrierConfigCache.getInstance(context);
        mSatelliteManager = context.getSystemService(SatelliteManager.class);
    }

    @Override
@@ -58,9 +105,19 @@ public class PreferredNetworkModePreferenceController extends BasePreferenceCont
                ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(getPreferenceKey());
    }

    @Override
    public void updateState(Preference preference) {
        if (preference == null) {
            return;
        }
        super.updateState(preference);
        preference.setEnabled(!(mIsCurrentSubscriptionForSatellite && mIsSatelliteSessionStarted));
        final ListPreference listPreference = (ListPreference) preference;
        final int networkMode = getPreferredNetworkMode();
        listPreference.setValue(Integer.toString(networkMode));
@@ -90,6 +147,38 @@ public class PreferredNetworkModePreferenceController extends BasePreferenceCont
                && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL);
    }

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
            if (mSatelliteManager != null) {
                try {
                    mSatelliteManager.registerForModemStateChanged(
                            mContext.getMainExecutor(), mSatelliteModemStateCallback);
                    mSatelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
                            mContext.getMainExecutor(),
                            mSelectedNbIotSatelliteSubscriptionCallback);
                } catch (IllegalStateException e) {
                    Log.w(TAG, "IllegalStateException : " + e);
                }
            }
        }
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
            if (mSatelliteManager != null) {
                try {
                    mSatelliteManager.unregisterForModemStateChanged(mSatelliteModemStateCallback);
                    mSatelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
                            mSelectedNbIotSatelliteSubscriptionCallback);
                } catch (IllegalStateException e) {
                    Log.w(TAG, "IllegalStateException : " + e);
                }
            }
        }
    }

    private int getPreferredNetworkMode() {
        if (mTelephonyManager == null) {
            Log.w(TAG, "TelephonyManager is null");
+66 −7
Original line number Diff line number Diff line
@@ -25,18 +25,22 @@ import android.telephony.CarrierConfigManager
import android.telephony.ServiceState
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.satellite.SatelliteManager
import android.telephony.satellite.SatelliteModemStateCallback
import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback
import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.Settings.NetworkSelectActivity
import com.android.settings.flags.Flags
import com.android.settings.network.CarrierConfigCache
import com.android.settings.network.telephony.MobileNetworkUtils
import com.android.settings.network.telephony.allowedNetworkTypesFlow
@@ -46,8 +50,6 @@ import com.android.settingslib.spa.framework.compose.OverridableFlow
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import kotlin.properties.Delegates.notNull
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
@@ -59,6 +61,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.time.Duration.Companion.seconds

/**
 * Preference controller for "Auto Select Network"
@@ -73,9 +76,13 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
    private val getConfigForSubId: (subId: Int) -> PersistableBundle = { subId ->
        CarrierConfigCache.getInstance(context).getConfigForSubId(subId)
    },
) : ComposePreferenceController(context, key) {
) : ComposePreferenceController(context, key), DefaultLifecycleObserver {

    private var isSatelliteSessionStarted = false
    private var isSelectedSubIdForSatellite = false

    private lateinit var telephonyManager: TelephonyManager
    private lateinit var satelliteManager: SatelliteManager
    private val listeners = mutableListOf<OnNetworkSelectModeListener>()

    @VisibleForTesting
@@ -83,6 +90,21 @@ class AutoSelectPreferenceController @JvmOverloads constructor(

    private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID

    val satelliteModemStateCallback = SatelliteModemStateCallback { state ->
        isSatelliteSessionStarted = when (state) {
            SatelliteManager.SATELLITE_MODEM_STATE_OFF,
            SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE,
            SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN -> false

            else -> true
        }
    }

    val selectedNbIotSatelliteSubscriptionCallback =
        SelectedNbIotSatelliteSubscriptionCallback { selectedSubId ->
            isSelectedSubIdForSatellite = selectedSubId == subId
        }

    /**
     * Initialization based on given subscription id.
     */
@@ -90,7 +112,7 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
        this.subId = subId
        telephonyManager = mContext.getSystemService(TelephonyManager::class.java)!!
            .createForSubscriptionId(subId)

        satelliteManager = mContext.getSystemService(SatelliteManager::class.java)!!
        return this
    }

@@ -117,7 +139,10 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
        SwitchPreference(object : SwitchPreferenceModel {
            override val title = stringResource(R.string.select_automatically)
            override val summary = { disallowedSummary }
            override val changeable = { disallowedSummary.isEmpty() }
            override val changeable = {
                disallowedSummary.isEmpty()
                        && !(isSatelliteSessionStarted && isSelectedSubIdForSatellite)
            }
            override val checked = { isAuto }
            override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
                if (newChecked) {
@@ -132,6 +157,38 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
        })
    }

    override fun onStart(owner: LifecycleOwner) {
        if (Flags.satelliteOemSettingsUxMigration()) {
            if (satelliteManager != null) {
                try {
                    satelliteManager.registerForModemStateChanged(
                        mContext.mainExecutor, satelliteModemStateCallback
                    )
                    satelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
                        mContext.mainExecutor, selectedNbIotSatelliteSubscriptionCallback
                    )
                } catch (e: IllegalStateException) {
                    Log.w(TAG, "IllegalStateException $e")
                }
            }
        }
    }

    override fun onStop(owner: LifecycleOwner) {
        if (Flags.satelliteOemSettingsUxMigration()) {
            if (satelliteManager != null) {
                try {
                    satelliteManager.unregisterForModemStateChanged(satelliteModemStateCallback)
                    satelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
                        selectedNbIotSatelliteSubscriptionCallback
                    )
                } catch (e: IllegalStateException) {
                    Log.w(TAG, "IllegalStateException $e")
                }
            }
        }
    }

    private suspend fun getDisallowedSummary(serviceState: ServiceState): String =
        withContext(Dispatchers.Default) {
            if (!serviceState.roaming && onlyAutoSelectInHome()) {
@@ -213,6 +270,8 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
    }

    companion object {
        private const val TAG = "AutoSelectPreferenceController"

        private val MINIMUM_DIALOG_TIME = 1.seconds
    }
}
+60 −1
Original line number Diff line number Diff line
@@ -18,10 +18,12 @@ package com.android.settings.network.telephony.gsm

import android.content.Context
import android.content.Intent
import android.platform.test.annotations.EnableFlags
import android.provider.Settings
import android.telephony.CarrierConfigManager
import android.telephony.ServiceState
import android.telephony.TelephonyManager
import android.telephony.satellite.SatelliteManager
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.assertIsOff
@@ -36,6 +38,7 @@ import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.settings.Settings.NetworkSelectActivity
import com.android.settings.flags.Flags
import com.android.settings.spa.preference.ComposePreference
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
@@ -46,6 +49,8 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doNothing
@@ -57,6 +62,9 @@ import org.mockito.kotlin.whenever

@RunWith(AndroidJUnit4::class)
class AutoSelectPreferenceControllerTest {
    @get:Rule
    val mockito = MockitoJUnit.rule()

    @get:Rule
    val composeTestRule = createComposeRule()

@@ -65,8 +73,12 @@ class AutoSelectPreferenceControllerTest {
        on { simOperatorName } doReturn OPERATOR_NAME
    }

    private val mockSatelliteManager = mock<SatelliteManager> {
    }

    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
        on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
        on { getSystemService(SatelliteManager::class.java) } doReturn mockSatelliteManager
        doNothing().whenever(mock).startActivity(any())
    }

@@ -115,7 +127,6 @@ class AutoSelectPreferenceControllerTest {
            .assertIsOff()
    }


    @Test
    fun isEnabled_isRoaming_enabled() {
        serviceState.roaming = true
@@ -158,6 +169,54 @@ class AutoSelectPreferenceControllerTest {
            .assertIsNotEnabled()
    }

    @Test
    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
    fun isEnabled_isSatelliteSessionStartedAndSelectedSubForSatellite_disabled() {
        controller.selectedNbIotSatelliteSubscriptionCallback
            .onSelectedNbIotSatelliteSubscriptionChanged(SUB_ID)
        controller.satelliteModemStateCallback
            .onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED)

        composeTestRule.setContent {
            controller.Content()
        }

        composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
            .assertIsNotEnabled()
    }

    @Test
    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
    fun isEnabled_isSatelliteSessionNotStartedButIsSelectedSubForSatellite_enabled() {
        controller.selectedNbIotSatelliteSubscriptionCallback
            .onSelectedNbIotSatelliteSubscriptionChanged(SUB_ID)
        controller.satelliteModemStateCallback
            .onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_OFF)

        composeTestRule.setContent {
            controller.Content()
        }

        composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
            .assertIsEnabled()
    }

    @Test
    @EnableFlags(Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION)
    fun isEnabled_isSatelliteSessionStartedButNotSelectedSubForSatellite_enabled() {
        controller.selectedNbIotSatelliteSubscriptionCallback
            .onSelectedNbIotSatelliteSubscriptionChanged(0)
        controller.satelliteModemStateCallback
            .onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED)

        composeTestRule.setContent {
            controller.Content()
        }

        composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
            .assertIsEnabled()
    }

    @Test
    fun onClick_turnOff_startNetworkSelectActivity() {
        serviceState.isManualSelection = false
+49 −0

File changed.

Preview size limit exceeded, changes collapsed.

Loading