From 36063b922272a744e6fc02d02176dcef62f57eb2 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Mon, 8 Oct 2018 15:13:53 -0700 Subject: [PATCH] Refactor MobileDataPreference 1. Remove it and change it to SwitchPrference 2. Build MobileDataDialogFragment to show dialog when needed 3. Create controller for it to decide when to launch the dialog Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I02b9662c5829e765f2c71d10ed951d792cf7aaa1 --- res/xml/network_setting_fragment.xml | 7 +- .../MobileDataDialogFragment.java | 133 +++++++ .../mobilenetwork/MobileDataPreference.java | 324 ------------------ .../MobileDataPreferenceController.java | 189 ++++++++++ .../mobilenetwork/MobileNetworkFragment.java | 48 +-- .../mobilenetwork/MobileNetworkUtils.java | 29 +- .../mobilenetwork/MobileSettingsActivity.java | 10 +- .../MobileDataPreferenceControllerTest.java | 149 ++++++++ .../mobilenetwork/MobileNetworkUtilsTest.java | 99 ++++++ .../MobileSettingsActivityTest.java | 8 +- 10 files changed, 640 insertions(+), 356 deletions(-) create mode 100644 src/com/android/settings/mobilenetwork/MobileDataDialogFragment.java delete mode 100644 src/com/android/settings/mobilenetwork/MobileDataPreference.java create mode 100644 src/com/android/settings/mobilenetwork/MobileDataPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/mobilenetwork/MobileDataPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/mobilenetwork/MobileNetworkUtilsTest.java diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index c383ab6652b..396f2e4a6c6 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -16,6 +16,8 @@ - + android:summary="@string/mobile_data_settings_summary" + settings:controller="com.android.settings.mobilenetwork.MobileDataPreferenceController"/> 1); - final boolean isMultipleDataOnCapable = - (mTelephonyManager.getNumberOfModemsWithSimultaneousDataConnections() > 1); - final boolean isDefaultDataSubscription = (nextSir != null && currentSir != null - && currentSir.getSubscriptionId() == nextSir.getSubscriptionId()); - if (mChecked) { - if (!isMultiSim) { - // disabling data; show confirmation dialog which eventually - // calls setMobileDataEnabled() once user confirms. - mMultiSimDialog = false; - super.performClick(); - } else { - // Don't show any dialog. - setMobileDataEnabled(false /* enabled */, false /* disableOtherSubscriptions */); - } - } else { - if (isMultiSim && !isMultipleDataOnCapable && !isDefaultDataSubscription) { - // enabling data and setting to default; show confirmation dialog which eventually - // calls setMobileDataEnabled() once user confirms. - mMultiSimDialog = true; - super.performClick(); - } else { - // Don't show any dialog. - setMobileDataEnabled(true /* enabled */, false /* disableOtherSubscriptions */); - } - } - } - - private void setMobileDataEnabled(boolean enabled, boolean disableOtherSubscriptions) { - if (DBG) Log.d(TAG, "setMobileDataEnabled(" + enabled + "," + mSubId + ")"); - - MetricsLogger.action(getContext(), MetricsEvent.ACTION_MOBILE_NETWORK_MOBILE_DATA_TOGGLE, - enabled); - - mTelephonyManager.setDataEnabled(mSubId, enabled); - - if (disableOtherSubscriptions) { - disableDataForOtherSubscriptions(mSubId); - } - - setChecked(enabled); - } - - private void setChecked(boolean checked) { - if (mChecked == checked) return; - mChecked = checked; - notifyChanged(); - } - - @Override - public void onBindViewHolder(PreferenceViewHolder holder) { - super.onBindViewHolder(holder); - View checkableView = holder.findViewById(com.android.internal.R.id.switch_widget); - checkableView.setClickable(false); - ((Checkable) checkableView).setChecked(mChecked); - } - - //TODO(b/114749736): move it to preference controller - protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { - if (mMultiSimDialog) { - showMultiSimDialog(builder); - } else { - showDisableDialog(builder); - } - } - - private void showDisableDialog(AlertDialog.Builder builder) { - builder.setTitle(null) - .setMessage(R.string.data_usage_disable_mobile) - .setPositiveButton(android.R.string.ok, this) - .setNegativeButton(android.R.string.cancel, null); - } - - private void showMultiSimDialog(AlertDialog.Builder builder) { - final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(mSubId); - final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo(); - - final String previousName = (nextSir == null) - ? getContext().getResources().getString(R.string.sim_selection_required_pref) - : nextSir.getDisplayName().toString(); - - builder.setTitle(R.string.sim_change_data_title); - builder.setMessage(getContext().getString(R.string.sim_change_data_message, - String.valueOf(currentSir != null ? currentSir.getDisplayName() : null), - previousName)); - - builder.setPositiveButton(android.R.string.ok, this); - builder.setNegativeButton(R.string.cancel, null); - } - - private void disableDataForOtherSubscriptions(int subId) { - List subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); - if (subInfoList != null) { - for (SubscriptionInfo subInfo : subInfoList) { - if (subInfo.getSubscriptionId() != subId) { - mTelephonyManager.setDataEnabled(subInfo.getSubscriptionId(), false); - } - } - } - } - - @Override - public void onClick(DialogInterface dialog, int which) { - if (which != DialogInterface.BUTTON_POSITIVE) { - return; - } - if (mMultiSimDialog) { - mSubscriptionManager.setDefaultDataSubId(mSubId); - setMobileDataEnabled(true /* enabled */, true /* disableOtherSubscriptions */); - } else { - // TODO: extend to modify policy enabled flag. - setMobileDataEnabled(false /* enabled */, false /* disableOtherSubscriptions */); - } - } - - private final DataStateListener mListener = new DataStateListener() { - @Override - public void onChange(boolean selfChange) { - updateChecked(); - } - }; - - /** - * Listener that listens mobile data state change. - */ - public abstract static class DataStateListener extends ContentObserver { - public DataStateListener() { - super(new Handler(Looper.getMainLooper())); - } - - /** - * Set / Unset data state listening, specifying subId. - */ - public void setListener(boolean listening, int subId, Context context) { - if (listening) { - Uri uri = Global.getUriFor(Global.MOBILE_DATA); - if (TelephonyManager.getDefault().getSimCount() != 1) { - uri = Global.getUriFor(Global.MOBILE_DATA + subId); - } - context.getContentResolver().registerContentObserver(uri, false, this); - } else { - context.getContentResolver().unregisterContentObserver(this); - } - } - } - - /** - * Class that represents state of mobile data state. - * Used by onSaveInstanceState and onRestoreInstanceState. - */ - public static class CellDataState extends BaseSavedState { - public int mSubId; - public boolean mChecked; - public boolean mMultiSimDialog; - - public CellDataState(Parcelable base) { - super(base); - } - - public CellDataState(Parcel source) { - super(source); - mChecked = source.readByte() != 0; - mMultiSimDialog = source.readByte() != 0; - mSubId = source.readInt(); - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeByte((byte) (mChecked ? 1 : 0)); - dest.writeByte((byte) (mMultiSimDialog ? 1 : 0)); - dest.writeInt(mSubId); - } - - public static final Creator CREATOR = new Creator() { - @Override - public CellDataState createFromParcel(Parcel source) { - return new CellDataState(source); - } - - @Override - public CellDataState[] newArray(int size) { - return new CellDataState[size]; - } - }; - } -} diff --git a/src/com/android/settings/mobilenetwork/MobileDataPreferenceController.java b/src/com/android/settings/mobilenetwork/MobileDataPreferenceController.java new file mode 100644 index 00000000000..c341d7e0095 --- /dev/null +++ b/src/com/android/settings/mobilenetwork/MobileDataPreferenceController.java @@ -0,0 +1,189 @@ +/* + * 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.mobilenetwork; + +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; +import android.telephony.SubscriptionInfo; +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 androidx.preference.SwitchPreference; + +import com.android.settings.core.TogglePreferenceController; +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 "Mobile data" + */ +public class MobileDataPreferenceController extends TogglePreferenceController + implements LifecycleObserver, OnStart, OnStop { + + private static final String DIALOG_TAG = "MobileDataDialog"; + + private SwitchPreference mPreference; + private TelephonyManager mTelephonyManager; + private SubscriptionManager mSubscriptionManager; + private DataContentObserver mDataContentObserver; + private FragmentManager mFragmentManager; + private int mSubId; + @VisibleForTesting + int mDialogType; + @VisibleForTesting + boolean mNeedDialog; + + public MobileDataPreferenceController(Context context, String key) { + super(context, key); + mSubscriptionManager = context.getSystemService(SubscriptionManager.class); + mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); + } + + @Override + public int getAvailabilityStatus() { + return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey()); + } + + @Override + public void onStart() { + if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + mDataContentObserver.register(mContext, mSubId); + } + } + + @Override + public void onStop() { + if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + mDataContentObserver.unRegister(mContext); + } + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (TextUtils.equals(preference.getKey(), getPreferenceKey())) { + if (mNeedDialog) { + showDialog(mDialogType); + } + return true; + } + + return false; + } + + @Override + public boolean setChecked(boolean isChecked) { + mNeedDialog = isDialogNeeded(); + + if (!mNeedDialog) { + // Update data directly if we don't need dialog + MobileNetworkUtils.setMobileDataEnabled(mContext, mSubId, isChecked, false); + return true; + } + + return false; + } + + @Override + public boolean isChecked() { + return mTelephonyManager.isDataEnabled(); + } + + public void init(FragmentManager fragmentManager, int subId) { + mFragmentManager = fragmentManager; + mSubId = subId; + mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); + } + + @VisibleForTesting + boolean isDialogNeeded() { + final boolean enableData = !mTelephonyManager.isDataEnabled(); + final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo( + mSubId); + final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo(); + final boolean isMultiSim = (mTelephonyManager.getSimCount() > 1); + final boolean isMultipleDataOnCapable = + (mTelephonyManager.getNumberOfModemsWithSimultaneousDataConnections() > 1); + final boolean isDefaultDataSubscription = (nextSir != null && currentSir != null + && currentSir.getSubscriptionId() == nextSir.getSubscriptionId()); + if (enableData) { + if (isMultiSim && !isMultipleDataOnCapable && !isDefaultDataSubscription) { + mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG; + return true; + } + } else { + if (!isMultiSim) { + mDialogType = MobileDataDialogFragment.TYPE_DISABLE_DIALOG; + return true; + } + } + + return false; + } + + private void showDialog(int type) { + final MobileDataDialogFragment dialogFragment = MobileDataDialogFragment.newInstance(type, + mSubId); + dialogFragment.show(mFragmentManager, DIALOG_TAG); + } + + /** + * Listener that listens mobile data state change. + */ + public class DataContentObserver extends ContentObserver { + + public DataContentObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + updateState(mPreference); + } + + public void register(Context context, int subId) { + Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA); + if (TelephonyManager.getDefault().getSimCount() != 1) { + uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId); + } + context.getContentResolver().registerContentObserver(uri, false, this); + + } + + public void unRegister(Context context) { + context.getContentResolver().unregisterContentObserver(this); + } + } +} diff --git a/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java b/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java index d8df8fac555..b31d4d2dfd0 100644 --- a/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java +++ b/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java @@ -34,6 +34,7 @@ import android.os.Message; import android.os.PersistableBundle; import android.os.UserHandle; import android.os.UserManager; +import android.provider.SearchIndexableResource; import android.provider.Settings; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; @@ -61,8 +62,11 @@ import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedSwitchPreference; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.search.SearchIndexable; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -156,7 +160,6 @@ public class MobileNetworkFragment extends DashboardFragment implements private Preference mWiFiCallingPref; private SwitchPreference mVideoCallingPref; private NetworkSelectListPreference mButtonNetworkSelect; - private MobileDataPreference mMobileDataPref; private DataUsagePreference mDataUsagePref; private static final String iface = "rmnet0"; //TODO: this will go away @@ -238,6 +241,9 @@ public class MobileNetworkFragment extends DashboardFragment implements */ @Override public boolean onPreferenceTreeClick(Preference preference) { + if (super.onPreferenceTreeClick(preference)) { + return true; + } sendMetricsEventPreferenceClicked(getPreferenceScreen(), preference); /** TODO: Refactor and get rid of the if's using subclasses */ @@ -298,7 +304,7 @@ public class MobileNetworkFragment extends DashboardFragment implements startActivity(intent); return true; } else if (preference == mWiFiCallingPref || preference == mVideoCallingPref - || preference == mMobileDataPref || preference == mDataUsagePref) { + || preference == mDataUsagePref) { return false; } else { // if the button is anything but the simple toggle preference, @@ -383,6 +389,15 @@ public class MobileNetworkFragment extends DashboardFragment implements mPhoneStateListener.updateSubscriptionId(mSubId); } + @Override + public void onAttach(Context context) { + super.onAttach(context); + mSubId = getArguments().getInt(MobileSettingsActivity.KEY_SUBSCRIPTION_ID, + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + + use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId); + } + @Override public void onCreate(Bundle icicle) { Log.i(LOG_TAG, "onCreate:+"); @@ -407,7 +422,6 @@ public class MobileNetworkFragment extends DashboardFragment implements mCallingCategory = (PreferenceCategory) findPreference(CATEGORY_CALLING_KEY); mWiFiCallingPref = findPreference(BUTTON_WIFI_CALLING_KEY); mVideoCallingPref = (SwitchPreference) findPreference(BUTTON_VIDEO_CALLING_KEY); - mMobileDataPref = (MobileDataPreference) findPreference(BUTTON_MOBILE_DATA_ENABLE_KEY); mDataUsagePref = (DataUsagePreference) findPreference(BUTTON_DATA_USAGE_KEY); try { @@ -439,8 +453,6 @@ public class MobileNetworkFragment extends DashboardFragment implements // Initialize mActiveSubInfo int max = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); mActiveSubInfos = mSubscriptionManager.getActiveSubscriptionInfoList(); - mSubId = getArguments().getInt(MobileSettingsActivity.KEY_SUBSCRIPTION_ID, - SubscriptionManager.INVALID_SUBSCRIPTION_ID); updatePhone(); if (hasActiveSubscriptions()) { @@ -490,14 +502,6 @@ public class MobileNetworkFragment extends DashboardFragment implements } } - @Override - public void onDestroy() { - super.onDestroy(); - if (mMobileDataPref != null) { - mMobileDataPref.dispose(); - } - } - @Override public void onResume() { super.onResume(); @@ -567,17 +571,14 @@ public class MobileNetworkFragment extends DashboardFragment implements actionBar.setDisplayHomeAsUpEnabled(true); } - prefSet.addPreference(mMobileDataPref); prefSet.addPreference(mButtonDataRoam); prefSet.addPreference(mDataUsagePref); - mMobileDataPref.setEnabled(hasActiveSubscriptions); mButtonDataRoam.setEnabled(hasActiveSubscriptions); mDataUsagePref.setEnabled(hasActiveSubscriptions); if (hasActiveSubscriptions) { // Customized preferences needs to be initialized with subId. - mMobileDataPref.initialize(phoneSubId); mDataUsagePref.initialize(phoneSubId); // Initialize states of mButtonDataRoam. @@ -609,8 +610,6 @@ public class MobileNetworkFragment extends DashboardFragment implements return; } - prefSet.removeAll(); - updateBodyBasicFields(activity, prefSet, mSubId, hasActiveSubscriptions); if (hasActiveSubscriptions) { @@ -1751,8 +1750,6 @@ public class MobileNetworkFragment extends DashboardFragment implements if (preference == null) { return MetricsProto.MetricsEvent.VIEW_UNKNOWN; - } else if (preference == mMobileDataPref) { - return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_MOBILE_DATA_TOGGLE; } else if (preference == mButtonDataRoam) { return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_DATA_ROAMING_TOGGLE; } else if (preference == mDataUsagePref) { @@ -1864,6 +1861,17 @@ public class MobileNetworkFragment extends DashboardFragment implements protected boolean isPageSearchEnabled(Context context) { return false; } + + @Override + public List getXmlResourcesToIndex(Context context, + boolean enabled) { + final ArrayList result = new ArrayList<>(); + + final SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.network_setting_fragment; + result.add(sir); + return result; + } }; private static final class SetPreferredNetworkAsyncTask extends AsyncTask { diff --git a/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java b/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java index 21093758a3f..44b1cef8b61 100644 --- a/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java +++ b/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java @@ -22,13 +22,14 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.database.Cursor; import android.os.PersistableBundle; import android.os.SystemProperties; import android.provider.Settings; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.euicc.EuiccManager; import android.telephony.ims.feature.ImsFeature; @@ -170,4 +171,30 @@ public class MobileNetworkUtils { //TODO(b/114749736): get carrier config from subId return new PersistableBundle(); } + + /** + * Set whether to enable data for {@code subId}, also whether to disable data for other + * subscription + */ + public static void setMobileDataEnabled(Context context, int subId, boolean enabled, + boolean disableOtherSubscriptions) { + final TelephonyManager telephonyManager = TelephonyManager.from(context) + .createForSubscriptionId(subId); + final SubscriptionManager subscriptionManager = context.getSystemService( + SubscriptionManager.class); + telephonyManager.setDataEnabled(enabled); + + if (disableOtherSubscriptions) { + List subInfoList = + subscriptionManager.getActiveSubscriptionInfoList(); + if (subInfoList != null) { + for (SubscriptionInfo subInfo : subInfoList) { + if (subInfo.getSubscriptionId() != subId) { + TelephonyManager.from(context).createForSubscriptionId( + subInfo.getSubscriptionId()).setDataEnabled(false); + } + } + } + } + } } \ No newline at end of file diff --git a/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java b/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java index 37a180cf3e8..ba92ebf7955 100644 --- a/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java +++ b/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java @@ -23,6 +23,11 @@ import android.telephony.SubscriptionManager; import android.view.Menu; import android.view.View; +import androidx.annotation.VisibleForTesting; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + import com.android.internal.util.CollectionUtils; import com.android.settings.R; import com.android.settings.core.SettingsBaseActivity; @@ -31,11 +36,6 @@ import com.google.android.material.bottomnavigation.BottomNavigationView; import java.util.List; -import androidx.annotation.VisibleForTesting; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; - public class MobileSettingsActivity extends SettingsBaseActivity { @VisibleForTesting diff --git a/tests/robotests/src/com/android/settings/mobilenetwork/MobileDataPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/mobilenetwork/MobileDataPreferenceControllerTest.java new file mode 100644 index 00000000000..9bf9b545153 --- /dev/null +++ b/tests/robotests/src/com/android/settings/mobilenetwork/MobileDataPreferenceControllerTest.java @@ -0,0 +1,149 @@ +/* + * 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.mobilenetwork; + +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; +import androidx.preference.SwitchPreference; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +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 MobileDataPreferenceControllerTest { + 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 SubscriptionInfo mSubscriptionInfo; + @Mock + private FragmentTransaction mFragmentTransaction; + + private MobileDataPreferenceController mController; + private SwitchPreference 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(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId( + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction(); + + mPreference = new SwitchPreference(mContext); + mController = new MobileDataPreferenceController(mContext, "mobile_data"); + mController.init(mFragmentManager, SUB_ID); + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void getAvailabilityStatus_invalidSubscription_returnUnavailable() { + mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void isDialogNeeded_disableSingleSim_returnTrue() { + doReturn(true).when(mTelephonyManager).isDataEnabled(); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); + doReturn(1).when(mTelephonyManager).getSimCount(); + + assertThat(mController.isDialogNeeded()).isTrue(); + assertThat(mController.mDialogType).isEqualTo(MobileDataDialogFragment.TYPE_DISABLE_DIALOG); + } + + @Test + public void isDialogNeeded_enableNonDefaultSimInMultiSimMode_returnTrue() { + doReturn(false).when(mTelephonyManager).isDataEnabled(); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + doReturn(null).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); + doReturn(2).when(mTelephonyManager).getSimCount(); + doReturn(1).when(mTelephonyManager).getNumberOfModemsWithSimultaneousDataConnections(); + + assertThat(mController.isDialogNeeded()).isTrue(); + assertThat(mController.mDialogType).isEqualTo( + MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG); + } + + @Test + public void handlePreferenceTreeClick_needDialog_showDialog() { + mController.mNeedDialog = true; + + mController.handlePreferenceTreeClick(mPreference); + + verify(mFragmentManager).beginTransaction(); + } + + @Test + public void onPreferenceChange_needDialog_doNothing() { + doReturn(true).when(mTelephonyManager).isDataEnabled(); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); + doReturn(1).when(mTelephonyManager).getSimCount(); + + mController.onPreferenceChange(mPreference, true); + + verify(mTelephonyManager, never()).setDataEnabled(true); + } + + @Test + public void onPreferenceChange_notNeedDialog_update() { + doReturn(true).when(mTelephonyManager).isDataEnabled(); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); + doReturn(2).when(mTelephonyManager).getSimCount(); + + mController.onPreferenceChange(mPreference, true); + + verify(mTelephonyManager).setDataEnabled(true); + } + +} diff --git a/tests/robotests/src/com/android/settings/mobilenetwork/MobileNetworkUtilsTest.java b/tests/robotests/src/com/android/settings/mobilenetwork/MobileNetworkUtilsTest.java new file mode 100644 index 00000000000..2b21f1fac5c --- /dev/null +++ b/tests/robotests/src/com/android/settings/mobilenetwork/MobileNetworkUtilsTest.java @@ -0,0 +1,99 @@ +/* + * 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.mobilenetwork; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +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; + +import java.util.Arrays; + +@RunWith(SettingsRobolectricTestRunner.class) +public class MobileNetworkUtilsTest { + private static final int SUB_ID_1 = 1; + private static final int SUB_ID_2 = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private TelephonyManager mTelephonyManager2; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private SubscriptionInfo mSubscriptionInfo1; + @Mock + private SubscriptionInfo mSubscriptionInfo2; + + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class); + doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID_1); + doReturn(mTelephonyManager2).when(mTelephonyManager).createForSubscriptionId(SUB_ID_2); + + doReturn(SUB_ID_1).when(mSubscriptionInfo1).getSubscriptionId(); + doReturn(SUB_ID_2).when(mSubscriptionInfo2).getSubscriptionId(); + + doReturn(Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2)).when( + mSubscriptionManager).getActiveSubscriptionInfoList(); + } + + @Test + public void setMobileDataEnabled_setEnabled_enabled() { + MobileNetworkUtils.setMobileDataEnabled(mContext, SUB_ID_1, true, false); + + verify(mTelephonyManager).setDataEnabled(true); + verify(mTelephonyManager2, never()).setDataEnabled(anyBoolean()); + } + + @Test + public void setMobileDataEnabled_setDisabled_disabled() { + MobileNetworkUtils.setMobileDataEnabled(mContext, SUB_ID_2, true, false); + + verify(mTelephonyManager2).setDataEnabled(true); + verify(mTelephonyManager, never()).setDataEnabled(anyBoolean()); + } + + @Test + public void setMobileDataEnabled_disableOtherSubscriptions() { + MobileNetworkUtils.setMobileDataEnabled(mContext, SUB_ID_1, true, true); + + verify(mTelephonyManager).setDataEnabled(true); + verify(mTelephonyManager2).setDataEnabled(false); + } +} diff --git a/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java b/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java index cb86d6f3d27..a5a26b47e72 100644 --- a/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java +++ b/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java @@ -30,6 +30,10 @@ import android.telephony.SubscriptionManager; import android.view.Menu; import android.view.View; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + import com.android.internal.view.menu.ContextMenuBuilder; import com.android.settings.R; import com.android.settings.testutils.SettingsRobolectricTestRunner; @@ -46,10 +50,6 @@ import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.List; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; - @RunWith(SettingsRobolectricTestRunner.class) public class MobileSettingsActivityTest {