diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index 8206223689c..09be2f28d22 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -241,11 +241,13 @@
settings:controller="com.android.settings.network.telephony.CarrierPreferenceController">
-
+ settings:controller="com.android.settings.network.telephony.Enable2gPreferenceController"
+ settings:useAdminDisabledSummary="true"
+ settings:userRestriction="no_cellular_2g"/>
Radio HAL version 1.6 or greater
*
*/
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
- if (preference == null || !SubscriptionManager.isUsableSubscriptionId(mSubId)) {
- return;
- }
- final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(mSubId);
- boolean isDisabledByCarrier =
- carrierConfig != null
- && carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G);
- preference.setEnabled(!isDisabledByCarrier);
- String summary;
- if (isDisabledByCarrier) {
- summary = mContext.getString(R.string.enable_2g_summary_disabled_carrier,
- getCarrierName());
- } else {
- summary = mContext.getString(R.string.enable_2g_summary);
- }
- preference.setSummary(summary);
- }
-
- private String getCarrierName() {
- SubscriptionInfo subInfo = SubscriptionUtil.getSubById(mSubscriptionManager, mSubId);
- if (subInfo == null) {
- return "";
- }
- CharSequence carrierName = subInfo.getCarrierName();
- return TextUtils.isEmpty(carrierName) ? "" : carrierName.toString();
- }
-
@Override
public int getAvailabilityStatus(int subId) {
final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
@@ -143,9 +160,9 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
}
boolean visible =
SubscriptionManager.isUsableSubscriptionId(subId)
- && carrierConfig != null
- && mTelephonyManager.isRadioInterfaceCapabilitySupported(
- mTelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK);
+ && carrierConfig != null
+ && mTelephonyManager.isRadioInterfaceCapabilitySupported(
+ mTelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK);
return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@@ -158,6 +175,14 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
*/
@Override
public boolean isChecked() {
+ // If an enterprise admin has disabled 2g, we show the toggle as not checked to avoid
+ // user confusion of seeing a checked toggle, but having 2g actually disabled.
+ // The RestrictedSwitchPreference will take care of transparently informing the user that
+ // the setting was disabled by their admin
+ if (isDisabledByAdmin()) {
+ return false;
+ }
+
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
return (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
@@ -176,6 +201,10 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
*/
@Override
public boolean setChecked(boolean isChecked) {
+ if (isDisabledByAdmin()) {
+ return false;
+ }
+
if (!SubscriptionManager.isUsableSubscriptionId(mSubId)) {
return false;
}
@@ -199,4 +228,8 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
mContext, SettingsEnums.ACTION_2G_ENABLED, isChecked);
return true;
}
+
+ private boolean isDisabledByAdmin() {
+ return (mRestrictedPreference != null && mRestrictedPreference.isDisabledByAdmin());
+ }
}
diff --git a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
index 850ebc1d7a7..22f2d3a3bb3 100644
--- a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
@@ -27,15 +27,19 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.os.Looper;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.network.CarrierConfigCache;
+import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.Before;
import org.junit.Test;
@@ -46,6 +50,7 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public final class Enable2gPreferenceControllerTest {
private static final int SUB_ID = 2;
+ private static final String PREFERENCE_KEY = "TEST_2G_PREFERENCE";
@Mock
private CarrierConfigCache mCarrierConfigCache;
@@ -54,12 +59,18 @@ public final class Enable2gPreferenceControllerTest {
@Mock
private TelephonyManager mInvalidTelephonyManager;
+ private RestrictedSwitchPreference mPreference;
+ private PreferenceScreen mPreferenceScreen;
private PersistableBundle mPersistableBundle;
private Enable2gPreferenceController mController;
private Context mContext;
@Before
public void setUp() {
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
@@ -75,7 +86,12 @@ public final class Enable2gPreferenceControllerTest {
doReturn(mPersistableBundle).when(mCarrierConfigCache).getConfigForSubId(SUB_ID);
doReturn(mPersistableBundle).when(mCarrierConfigCache).getConfigForSubId(
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- mController = new Enable2gPreferenceController(mContext, "mobile_data");
+ mController = new Enable2gPreferenceController(mContext, PREFERENCE_KEY);
+
+ mPreference = spy(new RestrictedSwitchPreference(mContext));
+ mPreference.setKey(PREFERENCE_KEY);
+ mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
+ mPreferenceScreen.addPreference(mPreference);
mController.init(SUB_ID);
}
@@ -137,13 +153,15 @@ public final class Enable2gPreferenceControllerTest {
assertThat(mController.setChecked(false)).isFalse();
}
+ @Test
+ public void setChecked_disabledByAdmin_returnFalse() {
+ when2gIsDisabledByAdmin(true);
+ assertThat(mController.setChecked(false)).isFalse();
+ }
+
@Test
public void onPreferenceChange_update() {
- // Set "Enable 2G" flag to "on"
- when(mTelephonyManager.getAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G)).thenReturn(
- (long) (TelephonyManager.NETWORK_TYPE_BITMASK_GSM
- | TelephonyManager.NETWORK_TYPE_BITMASK_LTE));
+ when2gIsEnabledForReasonEnable2g();
// Setup state to allow disabling
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
@@ -159,4 +177,42 @@ public final class Enable2gPreferenceControllerTest {
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G,
TelephonyManager.NETWORK_TYPE_BITMASK_LTE);
}
+
+ @Test
+ public void disabledByAdmin_toggleUnchecked() {
+ when2gIsEnabledForReasonEnable2g();
+ when2gIsDisabledByAdmin(true);
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void userRestrictionInactivated_userToggleMaintainsState() {
+ // Initially, 2g is enabled
+ when2gIsEnabledForReasonEnable2g();
+ when2gIsDisabledByAdmin(false);
+ assertThat(mController.isChecked()).isTrue();
+
+ // When we disable the preference by an admin, the preference should be unchecked
+ when2gIsDisabledByAdmin(true);
+ assertThat(mController.isChecked()).isFalse();
+
+ // If the preference is re-enabled by an admin, former state should hold
+ when2gIsDisabledByAdmin(false);
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ private void when2gIsEnabledForReasonEnable2g() {
+ when(mTelephonyManager.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G)).thenReturn(
+ (long) (TelephonyManager.NETWORK_TYPE_BITMASK_GSM
+ | TelephonyManager.NETWORK_TYPE_BITMASK_LTE));
+ }
+
+ private void when2gIsDisabledByAdmin(boolean is2gDisabledByAdmin) {
+ // Our controller depends on state being initialized when the associated preference is
+ // displayed because the admin disablement functionality flows from the association of a
+ // Preference with the PreferenceScreen
+ when(mPreference.isDisabledByAdmin()).thenReturn(is2gDisabledByAdmin);
+ mController.displayPreference(mPreferenceScreen);
+ }
}