diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 90aa55ff1a7..bac0f601d66 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2991,7 +2991,7 @@ android:label="@string/settings_panel_title" android:theme="@style/Theme.BottomDialog" android:excludeFromRecents="true" - android:launchMode="singleTask" + android:launchMode="singleTop" android:exported="true"> @@ -3021,16 +3021,7 @@ - - - - - - - - + android:grantUriPermissions="true" /> + android:title="@string/call_category" + settings:searchable="false"> @Override public List loadInBackground() { final List result = new ArrayList<>(); + if (mContext.getResources().getBoolean(R.bool.config_use_legacy_suggestion)) { + Log.d(TAG, "Skipping - in legacy suggestion mode"); + return result; + } try (Cursor cursor = getContextualCardsFromProvider()) { if (cursor.getCount() > 0) { for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { diff --git a/src/com/android/settings/network/telephony/ApnPreferenceController.java b/src/com/android/settings/network/telephony/ApnPreferenceController.java index f5cd1403172..9fdb6ead962 100644 --- a/src/com/android/settings/network/telephony/ApnPreferenceController.java +++ b/src/com/android/settings/network/telephony/ApnPreferenceController.java @@ -32,7 +32,6 @@ import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.SettingsActivity; -import com.android.settings.core.BasePreferenceController; import com.android.settings.network.ApnSettings; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedPreference; @@ -43,12 +42,11 @@ import com.android.settingslib.core.lifecycle.events.OnStop; /** * Preference controller for "Apn settings" */ -public class ApnPreferenceController extends BasePreferenceController implements +public class ApnPreferenceController extends TelephonyBasePreferenceController implements LifecycleObserver, OnStart, OnStop { @VisibleForTesting CarrierConfigManager mCarrierConfigManager; - private int mSubId; private Preference mPreference; private DpcApnEnforcedObserver mDpcApnEnforcedObserver; @@ -59,12 +57,12 @@ public class ApnPreferenceController extends BasePreferenceController implements } @Override - public int getAvailabilityStatus() { - final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); - final boolean isCdmaApn = MobileNetworkUtils.isCdmaOptions(mContext, mSubId) + public int getAvailabilityStatus(int subId) { + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); + final boolean isCdmaApn = MobileNetworkUtils.isCdmaOptions(mContext, subId) && carrierConfig != null && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL); - final boolean isGsmApn = MobileNetworkUtils.isGsmOptions(mContext, mSubId) + final boolean isGsmApn = MobileNetworkUtils.isGsmOptions(mContext, subId) && carrierConfig != null && carrierConfig.getBoolean(CarrierConfigManager.KEY_APN_EXPAND_BOOL); diff --git a/src/com/android/settings/network/telephony/CarrierPreferenceController.java b/src/com/android/settings/network/telephony/CarrierPreferenceController.java index fbbfb9e88b2..c381dc422b2 100644 --- a/src/com/android/settings/network/telephony/CarrierPreferenceController.java +++ b/src/com/android/settings/network/telephony/CarrierPreferenceController.java @@ -28,21 +28,17 @@ import android.telephony.SubscriptionManager; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; -import com.android.settings.core.BasePreferenceController; - /** * Preference controller for "Carrier Settings" */ -public class CarrierPreferenceController extends BasePreferenceController { +public class CarrierPreferenceController extends TelephonyBasePreferenceController { @VisibleForTesting CarrierConfigManager mCarrierConfigManager; - private int mSubId; public CarrierPreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = new CarrierConfigManager(context); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } public void init(int subId) { @@ -50,14 +46,14 @@ public class CarrierPreferenceController extends BasePreferenceController { } @Override - public int getAvailabilityStatus() { - final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); + public int getAvailabilityStatus(int subId) { + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); // Return available if it is in CDMA or GSM mode, and the flag is on return carrierConfig != null && carrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_SETTINGS_ENABLE_BOOL) - && (MobileNetworkUtils.isCdmaOptions(mContext, mSubId) - || MobileNetworkUtils.isGsmOptions(mContext, mSubId)) + && (MobileNetworkUtils.isCdmaOptions(mContext, subId) + || MobileNetworkUtils.isGsmOptions(mContext, subId)) ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; } diff --git a/src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java b/src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java index 75579dd0d74..d1fbd73e6b9 100644 --- a/src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java +++ b/src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java @@ -29,18 +29,15 @@ import android.text.TextUtils; import androidx.preference.Preference; import com.android.internal.telephony.PhoneConstants; -import com.android.settings.core.BasePreferenceController; /** * Preference controller for "Data service setup" */ -public class DataServiceSetupPreferenceController extends BasePreferenceController { +public class DataServiceSetupPreferenceController extends TelephonyBasePreferenceController { private CarrierConfigManager mCarrierConfigManager; private TelephonyManager mTelephonyManager; - private PersistableBundle mCarrierConfig; private String mSetupUrl; - private int mSubId; public DataServiceSetupPreferenceController(Context context, String key) { super(context, key); @@ -48,16 +45,16 @@ public class DataServiceSetupPreferenceController extends BasePreferenceControll mTelephonyManager = context.getSystemService(TelephonyManager.class); mSetupUrl = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { + public int getAvailabilityStatus(int subId) { final boolean isLteOnCdma = mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE; - return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID - && mCarrierConfig != null - && !mCarrierConfig.getBoolean( + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); + return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + && carrierConfig != null + && !carrierConfig.getBoolean( CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL) && isLteOnCdma && !TextUtils.isEmpty(mSetupUrl) ? AVAILABLE @@ -67,7 +64,6 @@ public class DataServiceSetupPreferenceController extends BasePreferenceControll public void init(int subId) { mSubId = subId; mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); - mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); } @Override diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java index b94f7e5e80f..7028a3e7ff0 100644 --- a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java +++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java @@ -28,27 +28,24 @@ import android.text.format.Formatter; import androidx.preference.Preference; import com.android.settings.R; -import com.android.settings.core.BasePreferenceController; import com.android.settingslib.net.DataUsageController; /** * Preference controller for "Data usage" */ -public class DataUsagePreferenceController extends BasePreferenceController { +public class DataUsagePreferenceController extends TelephonyBasePreferenceController { private NetworkTemplate mTemplate; private DataUsageController.DataUsageInfo mDataUsageInfo; private Intent mIntent; - private int mSubId; public DataUsagePreferenceController(Context context, String key) { super(context, key); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { - return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + public int getAvailabilityStatus(int subId) { + return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID ? AVAILABLE : AVAILABLE_UNSEARCHABLE; } diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java index fcd2fa049ca..9c5a98ef01d 100644 --- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java @@ -31,18 +31,16 @@ import androidx.preference.Preference; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.settings.R; -import com.android.settings.core.BasePreferenceController; /** * Preference controller for "Enabled network mode" */ -public class EnabledNetworkModePreferenceController extends BasePreferenceController implements +public class EnabledNetworkModePreferenceController extends + TelephonyBasePreferenceController implements ListPreference.OnPreferenceChangeListener { private CarrierConfigManager mCarrierConfigManager; private TelephonyManager mTelephonyManager; - private PersistableBundle mPersistableBundle; - private int mSubId; private boolean mIsGlobalCdma; @VisibleForTesting boolean mShow4GForLTE; @@ -50,26 +48,26 @@ public class EnabledNetworkModePreferenceController extends BasePreferenceContro public EnabledNetworkModePreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { + public int getAvailabilityStatus(int subId) { boolean visible; - if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); + if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { visible = false; - } else if (mPersistableBundle == null) { + } else if (carrierConfig == null) { visible = false; - } else if (mPersistableBundle.getBoolean( + } else if (carrierConfig.getBoolean( CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)) { visible = false; - } else if (mPersistableBundle.getBoolean( + } else if (carrierConfig.getBoolean( CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL) && !mTelephonyManager.getServiceState().getRoaming() && mTelephonyManager.getServiceState().getDataRegState() == ServiceState.STATE_IN_SERVICE) { visible = false; - } else if (mPersistableBundle.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) { + } else if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) { visible = false; } else { visible = true; @@ -104,15 +102,15 @@ public class EnabledNetworkModePreferenceController extends BasePreferenceContro public void init(int subId) { mSubId = subId; - mPersistableBundle = mCarrierConfigManager.getConfigForSubId(mSubId); + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); final boolean isLteOnCdma = mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE; mIsGlobalCdma = isLteOnCdma - && mPersistableBundle.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL); - mShow4GForLTE = mPersistableBundle != null - ? mPersistableBundle.getBoolean( + && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL); + mShow4GForLTE = carrierConfig != null + ? carrierConfig.getBoolean( CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL) : false; } diff --git a/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java b/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java index cc8e78d06da..c510294c5b6 100644 --- a/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java +++ b/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java @@ -31,7 +31,6 @@ import androidx.preference.SwitchPreference; import com.android.ims.ImsManager; import com.android.settings.R; -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; @@ -42,8 +41,8 @@ import java.util.List; /** * Preference controller for "Enhanced 4G LTE" */ -public class Enhanced4gLtePreferenceController extends TogglePreferenceController implements - LifecycleObserver, OnStart, OnStop { +public class Enhanced4gLtePreferenceController extends TelephonyTogglePreferenceController + implements LifecycleObserver, OnStart, OnStop { private Preference mPreference; private TelephonyManager mTelephonyManager; @@ -53,24 +52,23 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle ImsManager mImsManager; private PhoneCallStateListener mPhoneStateListener; private final List m4gLteListeners; - private int mSubId; public Enhanced4gLtePreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); m4gLteListeners = new ArrayList<>(); mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper()); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { - final boolean isVisible = mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID - && mImsManager != null && mCarrierConfig != null + public int getAvailabilityStatus(int subId) { + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); + final boolean isVisible = subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + && mImsManager != null && carrierConfig != null && mImsManager.isVolteEnabledByPlatform() && mImsManager.isVolteProvisionedOnDevice() && MobileNetworkUtils.isImsServiceStateReady(mImsManager) - && !mCarrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL); + && !carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL); return isVisible ? (is4gLtePrefEnabled() ? AVAILABLE : AVAILABLE_UNSEARCHABLE) : CONDITIONALLY_UNAVAILABLE; diff --git a/src/com/android/settings/network/telephony/EuiccPreferenceController.java b/src/com/android/settings/network/telephony/EuiccPreferenceController.java index ae207a28636..ecd20edfc57 100644 --- a/src/com/android/settings/network/telephony/EuiccPreferenceController.java +++ b/src/com/android/settings/network/telephony/EuiccPreferenceController.java @@ -18,31 +18,26 @@ package com.android.settings.network.telephony; import android.content.Context; import android.content.Intent; -import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.euicc.EuiccManager; import android.text.TextUtils; import androidx.preference.Preference; -import com.android.settings.core.BasePreferenceController; - /** * Preference controller for "Euicc preference" */ -public class EuiccPreferenceController extends BasePreferenceController { +public class EuiccPreferenceController extends TelephonyBasePreferenceController { private TelephonyManager mTelephonyManager; - private int mSubId; public EuiccPreferenceController(Context context, String key) { super(context, key); mTelephonyManager = context.getSystemService(TelephonyManager.class); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { + public int getAvailabilityStatus(int subId) { return MobileNetworkUtils.showEuiccSettings(mContext) ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java index 47822b6fce3..f678e08032a 100644 --- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java +++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java @@ -40,7 +40,7 @@ import com.android.settingslib.core.lifecycle.events.OnStop; /** * Preference controller for "Mobile data" */ -public class MobileDataPreferenceController extends TogglePreferenceController +public class MobileDataPreferenceController extends TelephonyTogglePreferenceController implements LifecycleObserver, OnStart, OnStop { private static final String DIALOG_TAG = "MobileDataDialog"; @@ -50,7 +50,6 @@ public class MobileDataPreferenceController extends TogglePreferenceController private SubscriptionManager mSubscriptionManager; private DataContentObserver mDataContentObserver; private FragmentManager mFragmentManager; - private int mSubId; @VisibleForTesting int mDialogType; @VisibleForTesting @@ -58,15 +57,13 @@ public class MobileDataPreferenceController extends TogglePreferenceController public MobileDataPreferenceController(Context context, String key) { super(context, key); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mSubscriptionManager = context.getSystemService(SubscriptionManager.class); mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { - return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + public int getAvailabilityStatus(int subId) { + return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; } @@ -74,7 +71,7 @@ public class MobileDataPreferenceController extends TogglePreferenceController @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey()); + mPreference = screen.findPreference(getPreferenceKey()); } @Override @@ -122,6 +119,14 @@ public class MobileDataPreferenceController extends TogglePreferenceController && mSubId == SubscriptionManager.getDefaultDataSubscriptionId(); } + public static Uri getObservableUri(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); + } + return uri; + } + public void init(FragmentManager fragmentManager, int subId) { mFragmentManager = fragmentManager; mSubId = subId; @@ -172,10 +177,7 @@ public class MobileDataPreferenceController extends TogglePreferenceController } 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); - } + final Uri uri = getObservableUri(subId); context.getContentResolver().registerContentObserver(uri, false, this); } diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java new file mode 100644 index 00000000000..6efd8c3aed6 --- /dev/null +++ b/src/com/android/settings/network/telephony/MobileDataSlice.java @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2019 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 android.app.slice.Slice.EXTRA_TOGGLE_STATE; + +import android.annotation.ColorInt; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.core.graphics.drawable.IconCompat; +import androidx.slice.Slice; +import androidx.slice.builders.ListBuilder; +import androidx.slice.builders.SliceAction; + +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.network.AirplaneModePreferenceController; +import com.android.settings.slices.CustomSliceRegistry; +import com.android.settings.slices.CustomSliceable; +import com.android.settings.slices.SliceBackgroundWorker; + +import com.google.common.annotations.VisibleForTesting; + +import java.io.IOException; + +/** + * Custom {@link Slice} for Mobile Data. + *

+ * We make a custom slice instead of using {@link MobileDataPreferenceController} because the + * pref controller is generalized across any carrier, and thus does not control a specific + * subscription. We attempt to reuse any telephony-specific code from the preference controller. + * + *

+ * + */ +public class MobileDataSlice implements CustomSliceable { + + private final Context mContext; + private final SubscriptionManager mSubscriptionManager; + private final TelephonyManager mTelephonyManager; + + public MobileDataSlice(Context context) { + mContext = context; + mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); + mTelephonyManager = mContext.getSystemService(TelephonyManager.class); + } + + @Override + public Slice getSlice() { + final IconCompat icon = IconCompat.createWithResource(mContext, + R.drawable.ic_network_cell); + final String title = mContext.getText(R.string.mobile_data_settings_title).toString(); + final CharSequence summary = getSummary(); + @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext); + final PendingIntent toggleAction = getBroadcastIntent(mContext); + final PendingIntent primaryAction = getPrimaryAction(); + final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon, + ListBuilder.ICON_IMAGE, title); + final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction, + null /* actionTitle */, isMobileDataEnabled()); + + final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), + ListBuilder.INFINITY) + .setAccentColor(color) + .addRow(new ListBuilder.RowBuilder() + .setTitle(title) + .setSubtitle(summary) + .addEndItem(toggleSliceAction) + .setPrimaryAction(primarySliceAction)); + return listBuilder.build(); + } + + @Override + public Uri getUri() { + return CustomSliceRegistry.MOBILE_DATA_SLICE_URI; + } + + @Override + public void onNotifyChange(Intent intent) { + // Don't make a change if we are in Airplane Mode. + if (isAirplaneModeEnabled()) { + return; + } + + final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE, + isMobileDataEnabled()); + + final int defaultSubId = getDefaultSubscriptionId(mSubscriptionManager); + if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + return; // No subscription - do nothing. + } + + MobileNetworkUtils.setMobileDataEnabled(mContext, defaultSubId, newState, + false /* disableOtherSubscriptions */); + // Do not notifyChange on Uri. The service takes longer to update the current value than it + // does for the Slice to check the current value again. Let {@link WifiScanWorker} + // handle it. + } + + @Override + public IntentFilter getIntentFilter() { + final IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); + return filter; + } + + @Override + public Intent getIntent() { + return new Intent(mContext, MobileNetworkActivity.class); + } + + @Override + public Class getBackgroundWorkerClass() { + return MobileDataWorker.class; + } + + protected static int getDefaultSubscriptionId(SubscriptionManager subscriptionManager) { + final SubscriptionInfo defaultSubscription = + subscriptionManager.getDefaultDataSubscriptionInfo(); + if (defaultSubscription == null) { + return SubscriptionManager.INVALID_SUBSCRIPTION_ID; // No default subscription + } + + return defaultSubscription.getSubscriptionId(); + } + + private CharSequence getSummary() { + final SubscriptionInfo defaultSubscription = + mSubscriptionManager.getDefaultDataSubscriptionInfo(); + if (defaultSubscription == null) { + return null; // no summary text + } + + return defaultSubscription.getDisplayName(); + } + + private PendingIntent getPrimaryAction() { + final Intent intent = getIntent(); + return PendingIntent.getActivity(mContext, 0 /* requestCode */, + intent, 0 /* flags */); + } + + @VisibleForTesting + boolean isAirplaneModeEnabled() { + // Generic key since we only want the method check - no UI. + AirplaneModePreferenceController controller = new AirplaneModePreferenceController(mContext, + "key" /* Key */); + return controller.isChecked(); + } + + @VisibleForTesting + boolean isMobileDataEnabled() { + if (mTelephonyManager == null) { + return false; + } + + return mTelephonyManager.isDataEnabled(); + } + + /** + * Listener for mobile data state changes. + * + *

+ * Listen to individual subscription changes since there is no framework broadcast. + * + * This worker registers a ContentObserver in the background and updates the MobileData + * Slice when the value changes. + */ + public static class MobileDataWorker extends SliceBackgroundWorker { + + DataContentObserver mMobileDataObserver; + + public MobileDataWorker(Context context, Uri uri) { + super(context, uri); + final Handler handler = new Handler(Looper.getMainLooper()); + mMobileDataObserver = new DataContentObserver(handler, this); + } + + @Override + protected void onSlicePinned() { + final SubscriptionManager subscriptionManager = + getContext().getSystemService(SubscriptionManager.class); + mMobileDataObserver.register(getContext(), + getDefaultSubscriptionId(subscriptionManager)); + } + + @Override + protected void onSliceUnpinned() { + mMobileDataObserver.unRegister(getContext()); + } + + @Override + public void close() throws IOException { + mMobileDataObserver = null; + } + + public void updateSlice() { + notifySliceChange(); + } + + public class DataContentObserver extends ContentObserver { + + private final MobileDataWorker mSliceBackgroundWorker; + + public DataContentObserver(Handler handler, MobileDataWorker backgroundWorker) { + super(handler); + mSliceBackgroundWorker = backgroundWorker; + } + + @Override + public void onChange(boolean selfChange) { + mSliceBackgroundWorker.updateSlice(); + } + + public void register(Context context, int subId) { + final Uri uri = MobileDataPreferenceController.getObservableUri(subId); + context.getContentResolver().registerContentObserver(uri, false, this); + } + + public void unRegister(Context context) { + context.getContentResolver().unregisterContentObserver(this); + } + } + } +} diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index e05f185716a..6d29da19af8 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -114,7 +114,7 @@ public class MobileNetworkSettings extends RestrictedDashboardFragment { @Override protected List createPreferenceControllers(Context context) { mSubId = getArguments().getInt(Settings.EXTRA_SUB_ID, - SubscriptionManager.INVALID_SUBSCRIPTION_ID); + MobileNetworkUtils.getSearchableSubscriptionId(context)); if (FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2) && mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { @@ -250,11 +250,6 @@ public class MobileNetworkSettings extends RestrictedDashboardFragment { public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { - @Override - protected boolean isPageSearchEnabled(Context context) { - return false; - } - @Override public List getXmlResourcesToIndex(Context context, boolean enabled) { diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java index c5cdd3a03ef..8e44dd418ff 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java +++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java @@ -44,6 +44,8 @@ import com.android.ims.ImsException; import com.android.ims.ImsManager; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; +import com.android.internal.util.ArrayUtils; +import com.android.settings.core.BasePreferenceController; import java.util.Arrays; import java.util.List; @@ -403,4 +405,52 @@ public class MobileNetworkUtils { } return false; } + + + /** + * Return subId that supported by search. If there are more than one, return first one, + * otherwise return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} + */ + public static int getSearchableSubscriptionId(Context context) { + final SubscriptionManager subscriptionManager = context.getSystemService( + SubscriptionManager.class); + final int subIds[] = subscriptionManager.getActiveSubscriptionIdList(); + + return subIds.length >= 1 ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + + /** + * Return availability for a default subscription id. If subId already been set, use it to + * check, otherwise traverse all active subIds on device to check. + * @param context context + * @param defSubId Default subId get from telephony preference controller + * @param callback Callback to check availability for a specific subId + * @return Availability + * + * @see BasePreferenceController#getAvailabilityStatus() + */ + public static int getAvailability(Context context, int defSubId, + TelephonyAvailabilityCallback callback) { + final SubscriptionManager subscriptionManager = context.getSystemService( + SubscriptionManager.class); + if (defSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + // If subId has been set, return the corresponding status + return callback.getAvailabilityStatus(defSubId); + } else { + // Otherwise, search whether there is one subId in device that support this preference + final int[] subIds = subscriptionManager.getActiveSubscriptionIdList(); + if (ArrayUtils.isEmpty(subIds)) { + return callback.getAvailabilityStatus( + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } else { + for (final int subId : subIds) { + final int status = callback.getAvailabilityStatus(subId); + if (status == BasePreferenceController.AVAILABLE) { + return status; + } + } + return callback.getAvailabilityStatus(subIds[0]); + } + } + } } diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java index 0326f42d8c6..27a7bce5bb2 100644 --- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java @@ -35,38 +35,37 @@ import com.android.settings.core.BasePreferenceController; /** * Preference controller for "Preferred network mode" */ -public class PreferredNetworkModePreferenceController extends BasePreferenceController implements - ListPreference.OnPreferenceChangeListener { +public class PreferredNetworkModePreferenceController extends TelephonyBasePreferenceController + implements ListPreference.OnPreferenceChangeListener { private CarrierConfigManager mCarrierConfigManager; private TelephonyManager mTelephonyManager; private PersistableBundle mPersistableBundle; - private int mSubId; private boolean mIsGlobalCdma; public PreferredNetworkModePreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { + public int getAvailabilityStatus(int subId) { + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); boolean visible; - if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { visible = false; - } else if (mPersistableBundle == null) { + } else if (carrierConfig == null) { visible = false; - } else if (mPersistableBundle.getBoolean( + } else if (carrierConfig.getBoolean( CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)) { visible = false; - } else if (mPersistableBundle.getBoolean( + } else if (carrierConfig.getBoolean( CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL) && !mTelephonyManager.getServiceState().getRoaming() && mTelephonyManager.getServiceState().getDataRegState() == ServiceState.STATE_IN_SERVICE) { visible = false; - } else if (mPersistableBundle.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) { + } else if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) { visible = true; } else { visible = false; @@ -100,13 +99,13 @@ public class PreferredNetworkModePreferenceController extends BasePreferenceCont public void init(int subId) { mSubId = subId; - mPersistableBundle = mCarrierConfigManager.getConfigForSubId(mSubId); + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); final boolean isLteOnCdma = mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE; mIsGlobalCdma = isLteOnCdma - && mPersistableBundle.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL); + && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL); } private int getPreferredNetworkMode() { diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.java b/src/com/android/settings/network/telephony/RoamingPreferenceController.java index 688268c7887..4140d5d9709 100644 --- a/src/com/android/settings/network/telephony/RoamingPreferenceController.java +++ b/src/com/android/settings/network/telephony/RoamingPreferenceController.java @@ -42,7 +42,7 @@ import com.android.settingslib.core.lifecycle.events.OnStop; /** * Preference controller for "Roaming" */ -public class RoamingPreferenceController extends TogglePreferenceController implements +public class RoamingPreferenceController extends TelephonyTogglePreferenceController implements LifecycleObserver, OnStart, OnStop { private static final String DIALOG_TAG = "MobileDataDialog"; @@ -50,7 +50,6 @@ public class RoamingPreferenceController extends TogglePreferenceController impl private RestrictedSwitchPreference mSwitchPreference; private TelephonyManager mTelephonyManager; private CarrierConfigManager mCarrierConfigManager; - private int mSubId; private DataContentObserver mDataContentObserver; @VisibleForTesting boolean mNeedDialog; @@ -59,10 +58,8 @@ public class RoamingPreferenceController extends TogglePreferenceController impl public RoamingPreferenceController(Context context, String key) { super(context, key); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override @@ -78,12 +75,12 @@ public class RoamingPreferenceController extends TogglePreferenceController impl @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - mSwitchPreference = (RestrictedSwitchPreference) screen.findPreference(getPreferenceKey()); + mSwitchPreference = screen.findPreference(getPreferenceKey()); } @Override - public int getAvailabilityStatus() { - return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + public int getAvailabilityStatus(int subId) { + return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID ? AVAILABLE : AVAILABLE_UNSEARCHABLE; } diff --git a/src/com/android/settings/network/telephony/TelephonyAvailabilityCallback.java b/src/com/android/settings/network/telephony/TelephonyAvailabilityCallback.java new file mode 100644 index 00000000000..d60bccdbc1f --- /dev/null +++ b/src/com/android/settings/network/telephony/TelephonyAvailabilityCallback.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 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; + +/** + * Callback to decide whether preference is available based on subscription id + */ +public interface TelephonyAvailabilityCallback { + /** + * Return availability status for a specific subId + * + * @see TelephonyBasePreferenceController + * @see TelephonyTogglePreferenceController + */ + int getAvailabilityStatus(int subId); +} diff --git a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java new file mode 100644 index 00000000000..e4ff5c4c78e --- /dev/null +++ b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 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.telephony.SubscriptionManager; + +import com.android.settings.core.BasePreferenceController; + +/** + * {@link BasePreferenceController} that used by all preferences that requires subscription id. + */ +public abstract class TelephonyBasePreferenceController extends BasePreferenceController + implements TelephonyAvailabilityCallback { + protected int mSubId; + + public TelephonyBasePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + + @Override + public int getAvailabilityStatus() { + return MobileNetworkUtils.getAvailability(mContext, mSubId, this::getAvailabilityStatus); + } +} diff --git a/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java b/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java new file mode 100644 index 00000000000..71efc57fb5a --- /dev/null +++ b/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 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.telephony.SubscriptionManager; + +import com.android.settings.core.TogglePreferenceController; + +/** + * {@link TogglePreferenceController} that used by all preferences that requires subscription id. + */ +public abstract class TelephonyTogglePreferenceController extends TogglePreferenceController + implements TelephonyAvailabilityCallback { + protected int mSubId; + + public TelephonyTogglePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + + @Override + public int getAvailabilityStatus() { + return MobileNetworkUtils.getAvailability(mContext, mSubId, this::getAvailabilityStatus); + } +} diff --git a/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java index 1007ef8e03a..44984e65dc3 100644 --- a/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java +++ b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java @@ -42,7 +42,7 @@ import com.android.settingslib.core.lifecycle.events.OnStop; /** * Preference controller for "Video Calling" */ -public class VideoCallingPreferenceController extends TogglePreferenceController implements +public class VideoCallingPreferenceController extends TelephonyTogglePreferenceController implements LifecycleObserver, OnStart, OnStop, Enhanced4gLtePreferenceController.On4gLteUpdateListener { @@ -54,21 +54,19 @@ public class VideoCallingPreferenceController extends TogglePreferenceController ImsManager mImsManager; private PhoneCallStateListener mPhoneStateListener; private DataContentObserver mDataContentObserver; - private int mSubId; public VideoCallingPreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper()); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { - return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + public int getAvailabilityStatus(int subId) { + return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && MobileNetworkUtils.isWifiCallingEnabled(mContext, - SubscriptionManager.getPhoneId(mSubId)) + SubscriptionManager.getPhoneId(subId)) && isVideoCallEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java index ec9a8412b4b..26c4d06d853 100644 --- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java +++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java @@ -33,7 +33,6 @@ import androidx.preference.PreferenceScreen; import com.android.ims.ImsConfig; import com.android.ims.ImsManager; -import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; @@ -43,7 +42,7 @@ import java.util.List; /** * Preference controller for "Wifi Calling" */ -public class WifiCallingPreferenceController extends BasePreferenceController implements +public class WifiCallingPreferenceController extends TelephonyBasePreferenceController implements LifecycleObserver, OnStart, OnStop { @VisibleForTesting @@ -56,19 +55,17 @@ public class WifiCallingPreferenceController extends BasePreferenceController im PhoneAccountHandle mSimCallManager; private PhoneCallStateListener mPhoneStateListener; private Preference mPreference; - private int mSubId; public WifiCallingPreferenceController(Context context, String key) { super(context, key); mTelephonyManager = context.getSystemService(TelephonyManager.class); mSimCallManager = context.getSystemService(TelecomManager.class).getSimCallManager(); mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper()); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override - public int getAvailabilityStatus() { - return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + public int getAvailabilityStatus(int subId) { + return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && MobileNetworkUtils.isWifiCallingEnabled(mContext, SubscriptionManager.getPhoneId(mSubId)) ? AVAILABLE diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java index aae42f87e94..d20b75afce4 100644 --- a/src/com/android/settings/panel/InternetConnectivityPanel.java +++ b/src/com/android/settings/panel/InternetConnectivityPanel.java @@ -55,6 +55,7 @@ public class InternetConnectivityPanel implements PanelContent { public List getSlices() { final List uris = new ArrayList<>(); uris.add(CustomSliceRegistry.WIFI_SLICE_URI); + uris.add(CustomSliceRegistry.MOBILE_DATA_SLICE_URI); uris.add(CustomSliceRegistry.AIRPLANE_URI); return uris; } diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java index 3786c5c2ed9..c9e473a9c20 100644 --- a/src/com/android/settings/slices/CustomSliceManager.java +++ b/src/com/android/settings/slices/CustomSliceManager.java @@ -18,7 +18,6 @@ package com.android.settings.slices; import android.content.Context; import android.net.Uri; -import android.text.TextUtils; import android.util.ArrayMap; import androidx.annotation.VisibleForTesting; @@ -35,6 +34,7 @@ import com.android.settings.homepage.contextualcards.slices.LowStorageSlice; import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice; import com.android.settings.location.LocationSlice; import com.android.settings.media.MediaOutputSlice; +import com.android.settings.network.telephony.MobileDataSlice; import com.android.settings.wifi.slice.ContextualWifiSlice; import com.android.settings.wifi.slice.WifiSlice; @@ -123,6 +123,7 @@ public class CustomSliceManager { mUriMap.put(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, FlashlightSlice.class); mUriMap.put(CustomSliceRegistry.LOCATION_SLICE_URI, LocationSlice.class); mUriMap.put(CustomSliceRegistry.LOW_STORAGE_SLICE_URI, LowStorageSlice.class); + mUriMap.put(CustomSliceRegistry.MOBILE_DATA_SLICE_URI, MobileDataSlice.class); mUriMap.put(CustomSliceRegistry.NOTIFICATION_CHANNEL_SLICE_URI, NotificationChannelSlice.class); mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class); diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java index 66e85c0612d..ab1b2484828 100644 --- a/src/com/android/settings/slices/CustomSliceRegistry.java +++ b/src/com/android/settings/slices/CustomSliceRegistry.java @@ -164,6 +164,16 @@ public class CustomSliceRegistry { .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) .appendPath("toggle_nfc") .build(); + + /** + * Backing Uri for Mobile Data Slice. + */ + public static final Uri MOBILE_DATA_SLICE_URI = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(SettingsSliceProvider.SLICE_AUTHORITY) + .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_ACTION) + .appendPath("mobile_data") + .build(); /** * Backing Uri for Notification channel Slice. */ diff --git a/src/com/android/settings/slices/CustomSliceable.java b/src/com/android/settings/slices/CustomSliceable.java index b538b898252..220cdc80dbf 100644 --- a/src/com/android/settings/slices/CustomSliceable.java +++ b/src/com/android/settings/slices/CustomSliceable.java @@ -71,7 +71,7 @@ public interface CustomSliceable { * * @param intent which has the action taken on a {@link Slice}. */ - void onNotifyChange(Intent intent); + default void onNotifyChange(Intent intent) {} /** * @return an {@link Intent} to the source of the Slice data. @@ -90,11 +90,12 @@ public interface CustomSliceable { } /** - * Settings Slices which can represent component lists that are updatable by the - * {@link SliceBackgroundWorker} class returned here. + * Settings Slices which require background work, such as updating lists should implement a + * {@link SliceBackgroundWorker} and return it here. An example of background work is updating + * a list of Wifi networks available in the area. * - * @return a {@link SliceBackgroundWorker} class for fetching the list of results in the - * background. + * @return a {@link Class} to perform background work for the + * slice. */ default Class getBackgroundWorkerClass() { return null; diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java index 80b71335646..d1648e03d0f 100644 --- a/src/com/android/settings/slices/SettingsSliceProvider.java +++ b/src/com/android/settings/slices/SettingsSliceProvider.java @@ -21,7 +21,6 @@ import static android.Manifest.permission.READ_SEARCH_INDEXABLES; import android.app.slice.SliceManager; import android.content.ContentResolver; import android.content.Context; -import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; import android.os.StrictMode; @@ -46,7 +45,6 @@ import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.SliceBroadcastRelay; import com.android.settingslib.utils.ThreadUtils; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -149,18 +147,6 @@ public class SettingsSliceProvider extends SliceProvider { return true; } - @Override - public Uri onMapIntentToUri(Intent intent) { - try { - return getContext().getSystemService(SliceManager.class).mapIntentToUri( - SliceDeepLinkSpringBoard.parse( - intent.getData(), getContext().getPackageName())); - } catch (URISyntaxException e) { - Log.e(TAG, "Uri syntax error, can't map intent to uri.", e); - return null; - } - } - @Override public void onSlicePinned(Uri sliceUri) { if (mCustomSliceManager.isValidUri(sliceUri)) { @@ -464,8 +450,9 @@ public class SettingsSliceProvider extends SliceProvider { private List getSpecialCaseOemUris() { return Arrays.asList( - CustomSliceRegistry.ZEN_MODE_SLICE_URI, - CustomSliceRegistry.FLASHLIGHT_SLICE_URI + CustomSliceRegistry.FLASHLIGHT_SLICE_URI, + CustomSliceRegistry.MOBILE_DATA_SLICE_URI, + CustomSliceRegistry.ZEN_MODE_SLICE_URI ); } diff --git a/src/com/android/settings/slices/SliceBackgroundWorker.java b/src/com/android/settings/slices/SliceBackgroundWorker.java index 6df45ba93e3..995394e7d41 100644 --- a/src/com/android/settings/slices/SliceBackgroundWorker.java +++ b/src/com/android/settings/slices/SliceBackgroundWorker.java @@ -59,6 +59,14 @@ public abstract class SliceBackgroundWorker implements Closeable { mUri = uri; } + protected Uri getUri() { + return mUri; + } + + protected Context getContext() { + return mContext; + } + /** * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link Uri} * if exists @@ -151,7 +159,7 @@ public abstract class SliceBackgroundWorker implements Closeable { /** * Notify that data was updated and attempt to sync changes to the Slice. */ - protected void notifySliceChange() { + protected final void notifySliceChange() { mContext.getContentResolver().notifyChange(mUri, null); } } \ No newline at end of file diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java index d633b7af16e..8d7f44f1525 100644 --- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java +++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java @@ -21,8 +21,6 @@ import android.os.Bundle; import android.provider.Settings; import android.util.Log; -import androidx.annotation.Keep; - import com.android.settings.bluetooth.BluetoothSliceBuilder; import com.android.settings.notification.ZenModeSliceBuilder; import com.android.settings.overlay.FeatureFactory; @@ -89,14 +87,6 @@ public class SliceDeepLinkSpringBoard extends Activity { } } - @Keep - public static Uri createDeepLink(String s) { - return new Uri.Builder().scheme(SETTINGS) - .authority(SettingsSliceProvider.SLICE_AUTHORITY) - .appendQueryParameter(INTENT, s) - .build(); - } - public static Intent parse(Uri uri, String pkg) throws URISyntaxException { Intent intent = Intent.parseUri(uri.getQueryParameter(INTENT), Intent.URI_ANDROID_APP_SCHEME); diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java index 1a0ed0ce90e..bee643df363 100644 --- a/src/com/android/settings/wifi/slice/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -142,7 +142,7 @@ public class WifiSlice implements CustomSliceable { .setTitle(title) .setSubtitle(!TextUtils.isEmpty(apSummary) ? apSummary - : mContext.getText(R.string.summary_placeholder)) + : null) .setPrimaryAction(SliceAction.create( getAccessPointAction(accessPoint), levelIcon, ListBuilder.ICON_IMAGE, title)); @@ -247,7 +247,7 @@ public class WifiSlice implements CustomSliceable { return mContext.getText(R.string.switch_off_text); case WifiManager.WIFI_STATE_UNKNOWN: default: - return ""; + return null; } } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java index c47fa38868d..f04008b199e 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.spy; import android.content.Context; import android.net.Uri; +import com.android.settings.R; import com.android.settings.slices.CustomSliceRegistry; import org.junit.Before; @@ -132,6 +133,14 @@ public class ContextualCardLoaderTest { assertThat(result).hasSize(2); } + @Test + public void loadInBackground_legacyMode_shouldReturnNothing() { + assertThat(mContext.getResources().getBoolean(R.bool.config_use_legacy_suggestion)) + .isTrue(); + + assertThat(mContextualCardLoader.loadInBackground()).isEmpty(); + } + private ContextualCard getContextualCard(String sliceUri) { return new ContextualCard.Builder() .setName("test_card") diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java new file mode 100644 index 00000000000..c497cf82665 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2019 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.times; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.content.Intent; +import android.provider.Settings; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.core.graphics.drawable.IconCompat; +import androidx.slice.Slice; +import androidx.slice.SliceMetadata; +import androidx.slice.SliceProvider; +import androidx.slice.core.SliceAction; +import androidx.slice.widget.SliceLiveData; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class MobileDataSliceTest { + + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private SubscriptionInfo mSubscriptionInfo; + + private Context mContext; + private MobileDataSlice mMobileDataSlice; + + @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(mSubscriptionInfo).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); + doReturn(SUB_ID).when(mSubscriptionInfo).getSubscriptionId(); + + // Set-up specs for SliceMetadata. + SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); + + mMobileDataSlice = spy(new MobileDataSlice(mContext)); + } + + @Test + public void getSlice_shouldHaveTitleAndToggle() { + final Slice mobileData = mMobileDataSlice.getSlice(); + + final SliceMetadata metadata = SliceMetadata.from(mContext, mobileData); + assertThat(metadata.getTitle()) + .isEqualTo(mContext.getString(R.string.mobile_data_settings_title)); + + final List toggles = metadata.getToggles(); + assertThat(toggles).hasSize(1); + + final SliceAction primaryAction = metadata.getPrimaryAction(); + final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext, + R.drawable.ic_network_cell); + assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString()); + } + + @Test + public void handleUriChange_turnedOn_updatesMobileData() { + doReturn(false).when(mMobileDataSlice).isAirplaneModeEnabled(); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + final Intent intent = mMobileDataSlice.getIntent(); + intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, true); + + mMobileDataSlice.onNotifyChange(intent); + + verify(mTelephonyManager).setDataEnabled(true); + } + + @Test + public void handleUriChange_turnedOff_updatesMobileData() { + doReturn(false).when(mMobileDataSlice).isAirplaneModeEnabled(); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + final Intent intent = mMobileDataSlice.getIntent(); + intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, false); + + mMobileDataSlice.onNotifyChange(intent); + + verify(mTelephonyManager).setDataEnabled(false); + } + + @Test + public void handleUriChange_turnedOff_airplaneModeOn_mobileDataDoesNotUpdate() { + doReturn(true).when(mMobileDataSlice).isAirplaneModeEnabled(); + doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + final Intent intent = mMobileDataSlice.getIntent(); + intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, false); + + mMobileDataSlice.onNotifyChange(intent); + + verify(mTelephonyManager, times(0)).setDataEnabled(true); + } + + @Test + public void isAirplaneModeEnabled_correctlyReturnsTrue() { + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1); + + final boolean isAirplaneModeEnabled = mMobileDataSlice.isAirplaneModeEnabled(); + + assertThat(isAirplaneModeEnabled).isTrue(); + } + + @Test + public void isAirplaneModeEnabled_correctlyReturnsFalse() { + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0); + + final boolean isAirplaneModeEnabled = mMobileDataSlice.isAirplaneModeEnabled(); + + assertThat(isAirplaneModeEnabled).isFalse(); + } + + @Test + public void isMobileDataEnabled_mobileDataEnabled() { + final boolean seed = true; + doReturn(seed).when(mTelephonyManager).isDataEnabled(); + + final boolean isMobileDataEnabled = mMobileDataSlice.isMobileDataEnabled(); + + assertThat(isMobileDataEnabled).isEqualTo(seed); + } +} diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java index 34e680e55f2..7dfe520b614 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java @@ -41,7 +41,6 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import com.android.internal.telephony.PhoneConstants; -import com.android.settings.R; import org.junit.Before; import org.junit.Test; @@ -184,4 +183,19 @@ public class MobileNetworkUtilsTest { assertThat(MobileNetworkUtils.isCdmaOptions(mContext, SUB_ID_1)).isTrue(); } + + @Test + public void getSearchableSubscriptionId_oneActive_returnValid() { + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID_1}); + + assertThat(MobileNetworkUtils.getSearchableSubscriptionId(mContext)).isEqualTo(SUB_ID_1); + } + + @Test + public void getSearchableSubscriptionId_nonActive_returnInvalid() { + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[0]); + + assertThat(MobileNetworkUtils.getSearchableSubscriptionId(mContext)) + .isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } } diff --git a/tests/robotests/src/com/android/settings/network/telephony/TelephonyBasePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/TelephonyBasePreferenceControllerTest.java new file mode 100644 index 00000000000..886ea177d9f --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/TelephonyBasePreferenceControllerTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2019 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.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.telephony.SubscriptionManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class TelephonyBasePreferenceControllerTest { + private static final int VALID_SUB_ID = 1; + + @Mock + private SubscriptionManager mSubscriptionManager; + + private TestPreferenceController mPreferenceController; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + when(mContext.getSystemService(SubscriptionManager.class)) + .thenReturn(mSubscriptionManager); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{}); + mPreferenceController = new TestPreferenceController(mContext, "prefKey"); + } + + @Test + public void isAvailable_validSubIdSet_returnTrue() { + mPreferenceController.init(VALID_SUB_ID); + + assertThat(mPreferenceController.isAvailable()).isTrue(); + } + + @Test + public void isAvailable_noIdSetHoweverHasDefaultOne_returnTrue() { + when(mSubscriptionManager.getActiveSubscriptionIdList()) + .thenReturn(new int[]{VALID_SUB_ID}); + + assertThat(mPreferenceController.isAvailable()).isTrue(); + } + + @Test + public void isAvailable_noDefaultAndNoSet_returnFalse() { + assertThat(mPreferenceController.isAvailable()).isFalse(); + } + + /** + * Test preference controller for {@link TelephonyBasePreferenceController} + */ + public class TestPreferenceController extends TelephonyBasePreferenceController { + public TestPreferenceController(Context context, String prefKey) { + super(context, prefKey); + } + + public void init(int subId) { + mSubId = subId; + } + + @Override + public int getAvailabilityStatus(int subId) { + return subId == VALID_SUB_ID ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + } +} diff --git a/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java b/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java index 3a4cf7b0ba6..42867fb6ca4 100644 --- a/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java +++ b/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java @@ -46,8 +46,10 @@ public class InternetConnectivityPanelTest { public void getSlices_containsNecessarySlices() { final List uris = mPanel.getSlices(); - assertThat(uris).containsExactly(CustomSliceRegistry.WIFI_SLICE_URI, - CustomSliceRegistry.AIRPLANE_URI); + assertThat(uris).containsExactly( + CustomSliceRegistry.AIRPLANE_URI, + CustomSliceRegistry.MOBILE_DATA_SLICE_URI, + CustomSliceRegistry.WIFI_SLICE_URI); } @Test diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java index 7eae3e4ad1a..efdcc264ec0 100644 --- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java +++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java @@ -116,7 +116,8 @@ public class SettingsSliceProviderTest { private static final List SPECIAL_CASE_OEM_URIS = Arrays.asList( CustomSliceRegistry.ZEN_MODE_SLICE_URI, - CustomSliceRegistry.FLASHLIGHT_SLICE_URI + CustomSliceRegistry.FLASHLIGHT_SLICE_URI, + CustomSliceRegistry.MOBILE_DATA_SLICE_URI ); @Before diff --git a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java deleted file mode 100644 index 0c5f50191ff..00000000000 --- a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.slices; - -import static com.android.settings.slices.SliceDeepLinkSpringBoard.createDeepLink; - -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.platform.test.annotations.Presubmit; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.MediumTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@MediumTest -public class SliceDeepLinkSpringBoardTest { - private Context mContext; - - @Before - public void setUp() { - mContext = InstrumentationRegistry.getTargetContext(); - } - - @Test - @Presubmit - public void launchesDeepLinkIntent_shouldNotCrash() { - final Intent deepLinkIntent = getSpringboardIntent( - "content://com.android.settings.slices/action/test_slice"); - - mContext.startActivity(deepLinkIntent); - } - - @Test - @Presubmit - public void launchesDeepLinkIntent_wifiSlice_shouldNotCrash() { - final Intent deepLinkIntent = getSpringboardIntent( - CustomSliceRegistry.WIFI_SLICE_URI.toString()); - - mContext.startActivity(deepLinkIntent); - } - - @Test - @Presubmit - public void launchesDeepLinkIntent_bluetoothSlice_shouldNotCrash() { - final Intent deepLinkIntent = getSpringboardIntent( - CustomSliceRegistry.BLUETOOTH_URI.toString()); - - mContext.startActivity(deepLinkIntent); - } - - @Test - @Presubmit - public void launchesDeepLinkIntent_dndSlice_shouldNotCrash() { - final Intent deepLinkIntent = getSpringboardIntent( - CustomSliceRegistry.ZEN_MODE_SLICE_URI.toString()); - - mContext.startActivity(deepLinkIntent); - } - - @Test - @Presubmit - public void launchesDeepLinkIntent_locationSlice_shouldNotCrash() { - final Intent deepLinkIntent = getSpringboardIntent( - CustomSliceRegistry.LOCATION_SLICE_URI.toString()); - - mContext.startActivity(deepLinkIntent); - } - - private Intent getSpringboardIntent(String uriString) { - final Uri uri = createDeepLink(new Intent(SliceDeepLinkSpringBoard.ACTION_VIEW_SLICE) - .setPackage(mContext.getPackageName()) - .putExtra(SliceDeepLinkSpringBoard.EXTRA_SLICE, uriString) - .toUri(Intent.URI_ANDROID_APP_SCHEME)); - - return new Intent(Intent.ACTION_VIEW) - .setData(uri) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } -}