From 901934372894f8dcc6cd7aacafcd7607a4515845 Mon Sep 17 00:00:00 2001 From: Takamasa Kuramitsu Date: Mon, 1 Oct 2018 22:34:06 +0900 Subject: [PATCH 01/14] Move content later button doesn't work on Migration Wizard "Move content later" button doesn't work on StorageWizardMigrateConfirm screen which is shown when end-user try to migrate data from adopted SD Card to internal storage. The cause is "Move content later" button triggers to StorageWizardReady screen but cannot launch because the mDisk is null when the destination of migration is internal storage. This CL fixes to just exit StorageWizardMigrateConfirm screen when mDisk is null. Bug: 117082495 Test: manual Change-Id: Iccdccf4dda126d77458b9db35e4ec6ae6a263cb7 --- .../deviceinfo/StorageWizardMigrateConfirm.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java b/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java index b17defd0fc1..48ec0e313d0 100644 --- a/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java +++ b/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java @@ -85,9 +85,13 @@ public class StorageWizardMigrateConfirm extends StorageWizardBase { FeatureFactory.getFactory(this).getMetricsFeatureProvider().action(this, MetricsEvent.ACTION_STORAGE_MIGRATE_LATER); - final Intent intent = new Intent(this, StorageWizardReady.class); - intent.putExtra(EXTRA_MIGRATE_SKIP, true); - startActivity(intent); + if (mDisk != null) { + final Intent intent = new Intent(this, StorageWizardReady.class); + intent.putExtra(EXTRA_MIGRATE_SKIP, true); + startActivity(intent); + } else { + finishAffinity(); + } } @Override From c888e19c87fcc924585a7d5c757bc16a6f32551b Mon Sep 17 00:00:00 2001 From: Sreekanth Badida Date: Mon, 5 Feb 2018 17:18:40 +0100 Subject: [PATCH 02/14] RadioInfo: Disable ims provisioning switches in USER-build Disables provisioning switches for Ims-related features in the RadioInfo dialog when using USER-build. This prevents the user from circumventing ims provisioning checks. Bug: 78372174 Test: Manual Change-Id: If538d7ed56ca53ae6a8be31ddf374d9a15a8fdec --- src/com/android/settings/RadioInfo.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java index ee20c586e9b..5101fe8ec54 100644 --- a/src/com/android/settings/RadioInfo.java +++ b/src/com/android/settings/RadioInfo.java @@ -36,6 +36,7 @@ import android.net.NetworkRequest; import android.net.TrafficStats; import android.net.Uri; import android.os.AsyncResult; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -1358,25 +1359,26 @@ public class RadioInfo extends Activity { imsVolteProvisionedSwitch.setOnCheckedChangeListener(null); imsVolteProvisionedSwitch.setChecked(isImsVolteProvisioned()); imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener); - imsVolteProvisionedSwitch.setEnabled( - mImsManager.isVolteEnabledByPlatform(phone.getContext())); + imsVolteProvisionedSwitch.setEnabled(!Build.IS_USER + && mImsManager.isVolteEnabledByPlatform(phone.getContext())); imsVtProvisionedSwitch.setOnCheckedChangeListener(null); imsVtProvisionedSwitch.setChecked(isImsVtProvisioned()); imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener); - imsVtProvisionedSwitch.setEnabled( - mImsManager.isVtEnabledByPlatform(phone.getContext())); + imsVtProvisionedSwitch.setEnabled(!Build.IS_USER + && mImsManager.isVtEnabledByPlatform(phone.getContext())); imsWfcProvisionedSwitch.setOnCheckedChangeListener(null); imsWfcProvisionedSwitch.setChecked(isImsWfcProvisioned()); imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener); - imsWfcProvisionedSwitch.setEnabled( - mImsManager.isWfcEnabledByPlatform(phone.getContext())); + imsWfcProvisionedSwitch.setEnabled(!Build.IS_USER + && mImsManager.isWfcEnabledByPlatform(phone.getContext())); eabProvisionedSwitch.setOnCheckedChangeListener(null); eabProvisionedSwitch.setChecked(isEabProvisioned()); eabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener); - eabProvisionedSwitch.setEnabled(isEabEnabledByPlatform(phone.getContext())); + eabProvisionedSwitch.setEnabled(!Build.IS_USER + && isEabEnabledByPlatform(phone.getContext())); } OnClickListener mDnsCheckButtonHandler = new OnClickListener() { From 36063b922272a744e6fc02d02176dcef62f57eb2 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Mon, 8 Oct 2018 15:13:53 -0700 Subject: [PATCH 03/14] 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 { From 1a4781881eb458ad3141a6fee292f2f3bcc22e78 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 9 Oct 2018 12:26:51 -0700 Subject: [PATCH 04/14] Add network listener in MobileSettingsActivity Listen to subscription change. If it is changed, refresh UI and build new fragment for it. Bug: 114749736 Test: RunSettingsRoboTests Change-Id: I436b4d62b06230e767892bda6cf8582d4946097b --- .../mobilenetwork/MobileSettingsActivity.java | 65 +++++++++++++++---- .../MobileSettingsActivityTest.java | 19 +++++- 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java b/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java index ba92ebf7955..4442ddfa3d9 100644 --- a/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java +++ b/src/com/android/settings/mobilenetwork/MobileSettingsActivity.java @@ -23,6 +23,7 @@ import android.telephony.SubscriptionManager; import android.view.Menu; import android.view.View; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -41,13 +42,23 @@ public class MobileSettingsActivity extends SettingsBaseActivity { @VisibleForTesting static final String MOBILE_SETTINGS_TAG = "mobile_settings:"; public static final String KEY_SUBSCRIPTION_ID = "key_subscription_id"; + public static final String KEY_CUR_SUBSCRIPTION_ID = "key_cur_subscription_id"; private SubscriptionManager mSubscriptionManager; @VisibleForTesting - int mPrevSubscriptionId; + Integer mCurSubscriptionId; @VisibleForTesting List mSubscriptionInfos; + private final SubscriptionManager.OnSubscriptionsChangedListener + mOnSubscriptionsChangeListener + = new SubscriptionManager.OnSubscriptionsChangedListener() { + @Override + public void onSubscriptionsChanged() { + updateSubscriptions(null); + } + }; + @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); @@ -58,18 +69,42 @@ public class MobileSettingsActivity extends SettingsBaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mSubscriptionManager = getSystemService(SubscriptionManager.class); - mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList(); - mPrevSubscriptionId = CollectionUtils.isEmpty(mSubscriptionInfos) - ? SubscriptionManager.INVALID_SUBSCRIPTION_ID - : mSubscriptionInfos.get(0).getSubscriptionId(); setContentView(R.layout.mobile_settings_container); + mSubscriptionManager = getSystemService(SubscriptionManager.class); + mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList(); + mCurSubscriptionId = savedInstanceState != null + ? savedInstanceState.getInt(KEY_CUR_SUBSCRIPTION_ID) + : null; + + mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener); + + updateSubscriptions(savedInstanceState); + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + saveInstanceState(outState); + } + + @VisibleForTesting + void saveInstanceState(@NonNull Bundle outState) { + outState.putInt(KEY_CUR_SUBSCRIPTION_ID, mCurSubscriptionId); + } + + @VisibleForTesting + void updateSubscriptions(Bundle savedInstanceState) { + //TODO(b/114749736): Sort it by phoneId + mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList(); + final int subId = CollectionUtils.isEmpty(mSubscriptionInfos) + ? SubscriptionManager.INVALID_SUBSCRIPTION_ID + : mSubscriptionInfos.get(0).getSubscriptionId(); updateBottomNavigationView(); if (savedInstanceState == null) { - switchFragment(new MobileNetworkFragment(), mPrevSubscriptionId); + switchFragment(new MobileNetworkFragment(), subId); } } @@ -89,24 +124,27 @@ public class MobileSettingsActivity extends SettingsBaseActivity { } navigation.setOnNavigationItemSelectedListener(item -> { switchFragment(new MobileNetworkFragment(), item.getItemId()); - mPrevSubscriptionId = item.getItemId(); return true; }); - } } @VisibleForTesting void switchFragment(Fragment fragment, int subscriptionId) { + if (mCurSubscriptionId != null && subscriptionId == mCurSubscriptionId) { + return; + } final FragmentManager fragmentManager = getSupportFragmentManager(); final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); final Bundle bundle = new Bundle(); bundle.putInt(KEY_SUBSCRIPTION_ID, subscriptionId); - final Fragment hideFragment = fragmentManager.findFragmentByTag( - buildFragmentTag(mPrevSubscriptionId)); - if (hideFragment != null) { - fragmentTransaction.hide(hideFragment); + if (mCurSubscriptionId != null) { + final Fragment hideFragment = fragmentManager.findFragmentByTag( + buildFragmentTag(mCurSubscriptionId)); + if (hideFragment != null) { + fragmentTransaction.hide(hideFragment); + } } Fragment showFragment = fragmentManager.findFragmentByTag(buildFragmentTag(subscriptionId)); @@ -118,6 +156,7 @@ public class MobileSettingsActivity extends SettingsBaseActivity { fragmentTransaction.show(showFragment); } fragmentTransaction.commit(); + mCurSubscriptionId = subscriptionId; } private String buildFragmentTag(int subscriptionId) { diff --git a/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java b/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java index a5a26b47e72..b18676ff006 100644 --- a/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java +++ b/tests/robotests/src/com/android/settings/mobilenetwork/MobileSettingsActivityTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.content.Context; +import android.os.Bundle; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.view.Menu; @@ -45,6 +46,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; @@ -120,7 +122,7 @@ public class MobileSettingsActivityTest { @Test public void switchFragment_hidePreviousFragment() { - mMobileSettingsActivity.mPrevSubscriptionId = PREV_SUB_ID; + mMobileSettingsActivity.mCurSubscriptionId = PREV_SUB_ID; mMobileSettingsActivity.switchFragment(mShowFragment, CURRENT_SUB_ID); @@ -129,7 +131,7 @@ public class MobileSettingsActivityTest { @Test public void switchFragment_fragmentExist_showItWithArguments() { - mMobileSettingsActivity.mPrevSubscriptionId = PREV_SUB_ID; + mMobileSettingsActivity.mCurSubscriptionId = PREV_SUB_ID; mMobileSettingsActivity.switchFragment(mShowFragment, CURRENT_SUB_ID); @@ -137,4 +139,17 @@ public class MobileSettingsActivityTest { MobileSettingsActivity.KEY_SUBSCRIPTION_ID)).isEqualTo(CURRENT_SUB_ID); verify(mFragmentTransaction).show(mShowFragment); } + + @Test + public void onSaveInstanceState_saveCurrentSubId() { + mMobileSettingsActivity = Robolectric.buildActivity( + MobileSettingsActivity.class).get(); + mMobileSettingsActivity.mCurSubscriptionId = PREV_SUB_ID; + final Bundle bundle = new Bundle(); + + mMobileSettingsActivity.saveInstanceState(bundle); + + assertThat(bundle.getInt(MobileSettingsActivity.KEY_CUR_SUBSCRIPTION_ID)).isEqualTo( + PREV_SUB_ID); + } } From 2554d0271e34da7255a198c16dcaac8423d6cd44 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 9 Oct 2018 13:24:06 -0700 Subject: [PATCH 05/14] Add target fragment for RoamingDialogFragment Bug: 114749736 Test: Manual Change-Id: I6f2939d99b72ff2dcf094c84bac75c2ca5d7ff66 --- .../android/settings/mobilenetwork/MobileNetworkFragment.java | 1 + .../android/settings/mobilenetwork/RoamingDialogFragment.java | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java b/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java index b31d4d2dfd0..716a496066b 100644 --- a/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java +++ b/src/com/android/settings/mobilenetwork/MobileNetworkFragment.java @@ -1074,6 +1074,7 @@ public class MobileNetworkFragment extends DashboardFragment implements 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; diff --git a/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java b/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java index 6f71d9c4cba..794b993af52 100644 --- a/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java +++ b/src/com/android/settings/mobilenetwork/RoamingDialogFragment.java @@ -60,7 +60,6 @@ public class RoamingDialogFragment extends InstrumentedDialogFragment implements mSubId = args.getInt(SUB_ID_KEY); mCarrierConfigManager = new CarrierConfigManager(context); - //TODO(b/114749736): set target fragment in host fragment Fragment fragment = getTargetFragment(); try { mListener = (RoamingDialogListener) fragment; From 496094ccdec152cb42809fef59be905d08578771 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 9 Oct 2018 13:13:55 -0700 Subject: [PATCH 06/14] Copy wifiCalling method from telephony to settings Bug: 114749736 Test: Build Change-Id: Iec45273e6a74afe940c280e50a473edc31473994 --- .../mobilenetwork/MobileNetworkUtils.java | 51 +++++++++++++++++-- .../mobilenetwork/MobileNetworkUtilsTest.java | 47 +++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java b/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java index 44b1cef8b61..d5ab909b72e 100644 --- a/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java +++ b/src/com/android/settings/mobilenetwork/MobileNetworkUtils.java @@ -22,6 +22,7 @@ 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; @@ -36,6 +37,8 @@ import android.telephony.ims.feature.ImsFeature; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.VisibleForTesting; + import com.android.ims.ImsException; import com.android.ims.ImsManager; @@ -54,6 +57,8 @@ public class MobileNetworkUtils { // the default value is false. private static final String KEY_ENABLE_ESIM_UI_BY_DEFAULT = "esim.enable_esim_system_ui_by_default"; + private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT = + "android.telecom.action.CONNECTION_SERVICE_CONFIGURE"; /** * Returns if DPC APNs are enforced. @@ -91,11 +96,10 @@ public class MobileNetworkUtils { boolean isWifiCallingEnabled; if (simCallManager != null) { - //TODO(b/114749736): build intent to query wifi calling feature - final Intent intent = null; - PackageManager pm = context.getPackageManager(); - isWifiCallingEnabled = intent != null - && !pm.queryIntentActivities(intent, 0 /* flags */).isEmpty(); + Intent intent = buildPhoneAccountConfigureIntent( + context, simCallManager); + + isWifiCallingEnabled = intent != null; } else { ImsManager imsMgr = ImsManager.getInstance(context, phoneId); isWifiCallingEnabled = imsMgr != null @@ -107,6 +111,43 @@ public class MobileNetworkUtils { return isWifiCallingEnabled; } + @VisibleForTesting + static Intent buildPhoneAccountConfigureIntent( + Context context, PhoneAccountHandle accountHandle) { + Intent intent = buildConfigureIntent( + context, accountHandle, TelecomManager.ACTION_CONFIGURE_PHONE_ACCOUNT); + + if (intent == null) { + // If the new configuration didn't work, try the old configuration intent. + intent = buildConfigureIntent(context, accountHandle, + LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT); + } + return intent; + } + + private static Intent buildConfigureIntent( + Context context, PhoneAccountHandle accountHandle, String actionStr) { + if (accountHandle == null || accountHandle.getComponentName() == null + || TextUtils.isEmpty(accountHandle.getComponentName().getPackageName())) { + return null; + } + + // Build the settings intent. + Intent intent = new Intent(actionStr); + intent.setPackage(accountHandle.getComponentName().getPackageName()); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, accountHandle); + + // Check to see that the phone account package can handle the setting intent. + PackageManager pm = context.getPackageManager(); + List resolutions = pm.queryIntentActivities(intent, 0); + if (resolutions.size() == 0) { + intent = null; // set no intent if the package cannot handle it. + } + + return intent; + } + public static boolean isImsServiceStateReady(ImsManager imsMgr) { boolean isImsServiceStateReady = false; diff --git a/tests/robotests/src/com/android/settings/mobilenetwork/MobileNetworkUtilsTest.java b/tests/robotests/src/com/android/settings/mobilenetwork/MobileNetworkUtilsTest.java index 2b21f1fac5c..4b91f6d7352 100644 --- a/tests/robotests/src/com/android/settings/mobilenetwork/MobileNetworkUtilsTest.java +++ b/tests/robotests/src/com/android/settings/mobilenetwork/MobileNetworkUtilsTest.java @@ -16,13 +16,24 @@ package com.android.settings.mobilenetwork; +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.ArgumentMatchers.nullable; 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.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.telecom.PhoneAccountHandle; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -36,10 +47,12 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; +import java.util.ArrayList; import java.util.Arrays; @RunWith(SettingsRobolectricTestRunner.class) public class MobileNetworkUtilsTest { + private static final String PACKAGE_NAME = "com.android.app"; private static final int SUB_ID_1 = 1; private static final int SUB_ID_2 = 2; @@ -53,6 +66,14 @@ public class MobileNetworkUtilsTest { private SubscriptionInfo mSubscriptionInfo1; @Mock private SubscriptionInfo mSubscriptionInfo2; + @Mock + private PackageManager mPackageManager; + @Mock + private PhoneAccountHandle mPhoneAccountHandle; + @Mock + private ComponentName mComponentName; + @Mock + private ResolveInfo mResolveInfo; private Context mContext; @@ -65,6 +86,9 @@ public class MobileNetworkUtilsTest { 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(mPackageManager).when(mContext).getPackageManager(); + doReturn(mComponentName).when(mPhoneAccountHandle).getComponentName(); + doReturn(PACKAGE_NAME).when(mComponentName).getPackageName(); doReturn(SUB_ID_1).when(mSubscriptionInfo1).getSubscriptionId(); doReturn(SUB_ID_2).when(mSubscriptionInfo2).getSubscriptionId(); @@ -96,4 +120,27 @@ public class MobileNetworkUtilsTest { verify(mTelephonyManager).setDataEnabled(true); verify(mTelephonyManager2).setDataEnabled(false); } + + @Test + public void buildConfigureIntent_nullHandle_returnNull() { + assertThat(MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, null)).isNull(); + } + + @Test + public void buildConfigureIntent_noActivityHandleIntent_returnNull() { + doReturn(new ArrayList()).when(mPackageManager).queryIntentActivities( + nullable(Intent.class), anyInt()); + + assertThat(MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, + mPhoneAccountHandle)).isNull(); + } + + @Test + public void buildConfigureIntent_hasActivityHandleIntent_returnIntent() { + doReturn(Arrays.asList(mResolveInfo)).when(mPackageManager).queryIntentActivities( + nullable(Intent.class), anyInt()); + + assertThat(MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, + mPhoneAccountHandle)).isNotNull(); + } } From 3181e1aceb68036fa342a8de4e4715a2bc26e89a Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 10 Oct 2018 15:25:47 -0700 Subject: [PATCH 07/14] Change search fab to search bar. - Remove search fab from layout xml - Change RelativeLayout to CoordinatorLayout so we can use prebuilt scrolling behavior - Minor update to theme so search bar background works in dark mode for the homepage activity. Change-Id: If7408c12684be65137e04ae3bb4137204c2d77e0 Fixes: 117508596 Test: robotests, visual --- res/layout/settings_homepage.xml | 2 +- res/layout/settings_homepage_container.xml | 48 +++++++++++-------- res/values-night/themes.xml | 1 + res/values/themes.xml | 3 ++ .../android/settings/SettingsActivity.java | 9 ---- .../homepage/SettingsHomepageActivity.java | 6 +-- .../search/SearchFeatureProvider.java | 19 ++++++-- .../search/SearchFeatureProviderImplTest.java | 4 +- 8 files changed, 53 insertions(+), 39 deletions(-) diff --git a/res/layout/settings_homepage.xml b/res/layout/settings_homepage.xml index 035e8b486cd..83c771c3302 100644 --- a/res/layout/settings_homepage.xml +++ b/res/layout/settings_homepage.xml @@ -19,4 +19,4 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/card_container" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="match_parent" /> diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml index b35b4ced254..ba8b48adb03 100644 --- a/res/layout/settings_homepage_container.xml +++ b/res/layout/settings_homepage_container.xml @@ -15,11 +15,34 @@ limitations under the License. --> - + android:layout_height="match_parent" + android:orientation="vertical"> + + + + + + + + + + + + app:menu="@menu/home_bottom_navigation"/> - - - - \ No newline at end of file + diff --git a/res/values-night/themes.xml b/res/values-night/themes.xml index eb0a7499675..725fe17685d 100644 --- a/res/values-night/themes.xml +++ b/res/values-night/themes.xml @@ -18,6 +18,7 @@ diff --git a/res/values/themes.xml b/res/values/themes.xml index df490f2471e..4050cb2b708 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -170,6 +170,9 @@ @*android:color/primary_device_default_settings_light @*android:color/accent_device_default_light @style/PreferenceTheme + + + @*android:style/ThemeOverlay.DeviceDefault.ActionBar.Accent