OSDN Git Service

Refactor roaming preference
authorjackqdyulei <jackqdyulei@google.com>
Tue, 16 Oct 2018 00:31:16 +0000 (17:31 -0700)
committerjackqdyulei <jackqdyulei@google.com>
Wed, 17 Oct 2018 20:03:26 +0000 (13:03 -0700)
Use preferenceController instead

Bug: 114749736
Test: RunSettingsRoboTests
Change-Id: Idb0276ea0ed1738d93223e072338ba3c32498a9d

res/xml/network_setting_fragment.xml
src/com/android/settings/network/telephony/MobileNetworkFragment.java
src/com/android/settings/network/telephony/RoamingDialogFragment.java
src/com/android/settings/network/telephony/RoamingPreferenceController.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java [new file with mode: 0644]

index ce1644f..74e03ed 100644 (file)
@@ -36,7 +36,9 @@
         android:title="@string/roaming"
         android:persistent="false"
         android:summaryOn="@string/roaming_enable"
-        android:summaryOff="@string/roaming_disable"/>
+        android:summaryOff="@string/roaming_disable"
+        settings:userRestriction="no_data_roaming"
+        settings:controller="com.android.settings.network.telephony.RoamingPreferenceController"/>
 
     <Preference
         android:key="data_usage_summary"
index 5e6f5d5..dfccab6 100644 (file)
@@ -81,7 +81,7 @@ import java.util.List;
 
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class MobileNetworkFragment extends DashboardFragment implements
-        Preference.OnPreferenceChangeListener, RoamingDialogFragment.RoamingDialogListener {
+        Preference.OnPreferenceChangeListener {
 
     // debug data
     private static final String LOG_TAG = "NetworkSettings";
@@ -153,7 +153,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
     //UI objects
     private ListPreference mButtonPreferredNetworkMode;
     private ListPreference mButtonEnabledNetworks;
-    private RestrictedSwitchPreference mButtonDataRoam;
     private SwitchPreference mButton4glte;
     private Preference mLteDataServicePref;
     private Preference mEuiccSettingsPref;
@@ -228,15 +227,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
         return 0;
     }
 
-    @Override
-    public void onPositiveButtonClick(androidx.fragment.app.DialogFragment dialog) {
-        mTelephonyManager.setDataRoamingEnabled(true);
-        mButtonDataRoam.setChecked(true);
-        MetricsLogger.action(getContext(),
-                getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
-                true);
-    }
-
     /**
      * Invoked on each preference click in this hierarchy, overrides
      * PreferenceActivity's implementation.  Used to make sure we track the
@@ -299,9 +289,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
                     preferredNetworkMode);
             mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode));
             return true;
-        } else if (preference == mButtonDataRoam) {
-            // Do not disable the preference screen if the user clicks Data roaming.
-            return true;
         } else if (preference == mEuiccSettingsPref) {
             Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
             startActivity(intent);
@@ -398,6 +385,7 @@ public class MobileNetworkFragment extends DashboardFragment implements
                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
 
         use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId);
+        use(RoamingPreferenceController.class).init(getFragmentManager(), mSubId);
         use(CdmaApnPreferenceController.class).init(mSubId);
         use(CarrierPreferenceController.class).init(mSubId);
         use(DataUsagePreferenceController.class).init(mSubId);
@@ -446,13 +434,10 @@ public class MobileNetworkFragment extends DashboardFragment implements
         //get UI object references
         PreferenceScreen prefSet = getPreferenceScreen();
 
-        mButtonDataRoam = (RestrictedSwitchPreference) prefSet.findPreference(
-                BUTTON_ROAMING_KEY);
         mButtonPreferredNetworkMode = (ListPreference) prefSet.findPreference(
                 BUTTON_PREFERED_NETWORK_MODE);
         mButtonEnabledNetworks = (ListPreference) prefSet.findPreference(
                 BUTTON_ENABLED_NETWORKS_KEY);
-        mButtonDataRoam.setOnPreferenceChangeListener(this);
 
         mLteDataServicePref = prefSet.findPreference(BUTTON_CDMA_LTE_DATA_SERVICE_KEY);
 
@@ -525,11 +510,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
         // preferences.
         getPreferenceScreen().setEnabled(true);
 
-        // Set UI state in onResume because a user could go home, launch some
-        // app to change this setting's backend, and re-launch this settings app
-        // and the UI state would be inconsistent with actual state
-        mButtonDataRoam.setChecked(mTelephonyManager.isDataRoamingEnabled());
-
         if (getPreferenceScreen().findPreference(BUTTON_PREFERED_NETWORK_MODE) != null
                 || getPreferenceScreen().findPreference(BUTTON_ENABLED_NETWORKS_KEY) != null)  {
             updatePreferredNetworkUIFromDb();
@@ -579,25 +559,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
             // android.R.id.home will be triggered in onOptionsItemSelected()
             actionBar.setDisplayHomeAsUpEnabled(true);
         }
-
-        prefSet.addPreference(mButtonDataRoam);
-
-        mButtonDataRoam.setEnabled(hasActiveSubscriptions);
-
-        if (hasActiveSubscriptions) {
-
-            // Initialize states of mButtonDataRoam.
-            mButtonDataRoam.setChecked(mTelephonyManager.isDataRoamingEnabled());
-            if (mButtonDataRoam.isEnabled()) {
-                if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
-                        UserManager.DISALLOW_DATA_ROAMING, UserHandle.myUserId())) {
-                    mButtonDataRoam.setEnabled(false);
-                } else {
-                    mButtonDataRoam.checkRestrictionAndSetDisabled(
-                            UserManager.DISALLOW_DATA_ROAMING);
-                }
-            }
-        }
     }
 
     private void updateBody() {
@@ -1038,42 +999,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
             boolean enhanced4gMode = !mButton4glte.isChecked();
             mButton4glte.setChecked(enhanced4gMode);
             mImsMgr.setEnhanced4gLteModeSetting(mButton4glte.isChecked());
-        } else if (preference == mButtonDataRoam) {
-            if (DBG) log("onPreferenceTreeClick: preference == mButtonDataRoam.");
-
-            //normally called on the toggle click
-            if (!mButtonDataRoam.isChecked()) {
-                PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
-                        mSubId);
-                if (carrierConfig != null && carrierConfig.getBoolean(
-                        CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL)) {
-                    mTelephonyManager.setDataRoamingEnabled(true);
-                    MetricsLogger.action(getContext(),
-                            getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
-                            true);
-                } else {
-                    // MetricsEvent with no value update.
-                    MetricsLogger.action(getContext(),
-                            getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam));
-                    // First confirm with a warning dialog about charges
-                    mOkClicked = false;
-                    RoamingDialogFragment
-                            fragment = new RoamingDialogFragment();
-                    Bundle b = new Bundle();
-                    b.putInt(RoamingDialogFragment.SUB_ID_KEY, mSubId);
-                    fragment.setArguments(b);
-                    fragment.setTargetFragment(this, 0 /* requestCode */);
-                    fragment.show(getFragmentManager(), ROAMING_TAG);
-                    // Don't update the toggle unless the confirm button is actually pressed.
-                    return false;
-                }
-            } else {
-                mTelephonyManager.setDataRoamingEnabled(false);
-                MetricsLogger.action(getContext(),
-                        getMetricsEventCategory(getPreferenceScreen(), mButtonDataRoam),
-                        false);
-                return true;
-            }
         } else if (preference == mVideoCallingPref) {
             // If mButton4glte is not checked, mVideoCallingPref should be disabled.
             // So it only makes sense to call phoneMgr.enableVideoCalling if it's checked.
@@ -1734,8 +1659,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
 
         if (preference == null) {
             return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
-        } else if (preference == mButtonDataRoam) {
-            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_DATA_ROAMING_TOGGLE;
         } else if (preference == mLteDataServicePref) {
             return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_SET_UP_DATA_SERVICE;
         } else if (preference == mButton4glte) {
index efb91d5..4c82686 100644 (file)
@@ -23,11 +23,11 @@ import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
 
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.Fragment;
 
-
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 
@@ -42,15 +42,14 @@ public class RoamingDialogFragment extends InstrumentedDialogFragment implements
     private CarrierConfigManager mCarrierConfigManager;
     private int mSubId;
 
-    /**
-     * The interface we expect a host activity to implement.
-     */
-    public interface RoamingDialogListener {
-        void onPositiveButtonClick(DialogFragment dialog);
-    }
+    public static RoamingDialogFragment newInstance(int subId) {
+        final RoamingDialogFragment dialogFragment = new RoamingDialogFragment();
+        Bundle args = new Bundle();
+        args.putInt(SUB_ID_KEY, subId);
+        dialogFragment.setArguments(args);
 
-    // the host activity which implements the listening interface
-    private RoamingDialogListener mListener;
+        return dialogFragment;
+    }
 
     @Override
     public void onAttach(Context context) {
@@ -58,14 +57,6 @@ public class RoamingDialogFragment extends InstrumentedDialogFragment implements
         Bundle args = getArguments();
         mSubId = args.getInt(SUB_ID_KEY);
         mCarrierConfigManager = new CarrierConfigManager(context);
-
-        Fragment fragment = getTargetFragment();
-        try {
-            mListener = (RoamingDialogListener) fragment;
-        } catch (ClassCastException e) {
-            throw new ClassCastException(fragment.toString() +
-                    "must implement RoamingDialogListener");
-        }
     }
 
     @Override
@@ -95,7 +86,8 @@ public class RoamingDialogFragment extends InstrumentedDialogFragment implements
     public void onClick(DialogInterface dialog, int which) {
         // let the host know that the positive button has been clicked
         if (which == dialog.BUTTON_POSITIVE) {
-            mListener.onPositiveButtonClick(this);
+            TelephonyManager.from(getContext()).createForSubscriptionId(
+                    mSubId).setDataRoamingEnabled(true);
         }
     }
 }
diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.java b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
new file mode 100644 (file)
index 0000000..3c1741b
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.FragmentManager;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+/**
+ * Preference controller for "Roaming"
+ */
+public class RoamingPreferenceController extends TogglePreferenceController implements
+        LifecycleObserver, OnStart, OnStop {
+
+    private static final String DIALOG_TAG = "MobileDataDialog";
+
+    private RestrictedSwitchPreference mSwitchPreference;
+    private TelephonyManager mTelephonyManager;
+    private CarrierConfigManager mCarrierConfigManager;
+    private int mSubId;
+    private DataContentObserver mDataContentObserver;
+    @VisibleForTesting
+    boolean mNeedDialog;
+    @VisibleForTesting
+    FragmentManager mFragmentManager;
+
+    public RoamingPreferenceController(Context context, String key) {
+        super(context, key);
+        mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
+        mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper()));
+    }
+
+    @Override
+    public void onStart() {
+        mDataContentObserver.register(mContext, mSubId);
+    }
+
+    @Override
+    public void onStop() {
+        mDataContentObserver.unRegister(mContext);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mSwitchPreference = (RestrictedSwitchPreference) screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                ? AVAILABLE
+                : AVAILABLE_UNSEARCHABLE;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            if (mNeedDialog) {
+                showDialog();
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        mNeedDialog = isDialogNeeded();
+
+        if (!mNeedDialog) {
+            // Update data directly if we don't need dialog
+            mTelephonyManager.setDataRoamingEnabled(isChecked);
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        final RestrictedSwitchPreference switchPreference = (RestrictedSwitchPreference) preference;
+        switchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        switchPreference.setChecked(isChecked());
+    }
+
+    @VisibleForTesting
+    boolean isDialogNeeded() {
+        final boolean isRoamingEnabled = mTelephonyManager.isDataRoamingEnabled();
+        final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
+                mSubId);
+
+        // Need dialog if we need to turn on roaming and the roaming charge indication is allowed
+        if (!isRoamingEnabled && (carrierConfig == null || !carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL))) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return mTelephonyManager.isDataRoamingEnabled();
+    }
+
+    public void init(FragmentManager fragmentManager, int subId) {
+        mFragmentManager = fragmentManager;
+        mSubId = subId;
+        mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+    }
+
+    private void showDialog() {
+        final RoamingDialogFragment dialogFragment = RoamingDialogFragment.newInstance(mSubId);
+
+        dialogFragment.show(mFragmentManager, DIALOG_TAG);
+    }
+
+    /**
+     * Listener that listens data roaming change
+     */
+    public class DataContentObserver extends ContentObserver {
+
+        public DataContentObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            updateState(mSwitchPreference);
+        }
+
+        public void register(Context context, int subId) {
+            Uri uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING);
+            if (TelephonyManager.getDefault().getSimCount() != 1) {
+                uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING + subId);
+            }
+            context.getContentResolver().registerContentObserver(uri, false, this);
+
+        }
+
+        public void unRegister(Context context) {
+            context.getContentResolver().unregisterContentObserver(this);
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
new file mode 100644 (file)
index 0000000..79d281f
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class RoamingPreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private FragmentManager mFragmentManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private TelephonyManager mInvalidTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
+    private FragmentTransaction mFragmentTransaction;
+    @Mock
+    private CarrierConfigManager mCarrierConfigManager;
+
+    private RoamingPreferenceController mController;
+    private RestrictedSwitchPreference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
+        doReturn(mCarrierConfigManager).when(mContext).getSystemService(CarrierConfigManager.class);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
+
+        mPreference = new RestrictedSwitchPreference(mContext);
+        mController = new RoamingPreferenceController(mContext, "roaming");
+        mController.init(mFragmentManager, SUB_ID);
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void getAvailabilityStatus_validSubId_returnAvailable() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_invalidSubId_returnUnsearchable() {
+        mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE_UNSEARCHABLE);
+    }
+
+    @Test
+    public void isDialogNeeded_roamingDisabledWithoutFlag_returnTrue() {
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+        doReturn(false).when(mTelephonyManager).isDataRoamingEnabled();
+
+        assertThat(mController.isDialogNeeded()).isTrue();
+    }
+
+    @Test
+    public void isDialogNeeded_roamingEnabled_returnFalse() {
+        doReturn(true).when(mTelephonyManager).isDataRoamingEnabled();
+
+        assertThat(mController.isDialogNeeded()).isFalse();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_needDialog_showDialog() {
+        mController.mNeedDialog = true;
+
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mFragmentManager).beginTransaction();
+    }
+
+    @Test
+    public void updateState_invalidSubId_disabled() {
+        mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void updateState_validSubId_enabled() {
+        doReturn(true).when(mTelephonyManager).isDataRoamingEnabled();
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+}