diff options
9 files changed, 581 insertions, 67 deletions
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml index 5b961595fbd3..ae2537fe29f6 100644 --- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml +++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml @@ -190,6 +190,11 @@ </LinearLayout> + <ViewStub android:id="@+id/secondary_mobile_network_stub" + android:inflatedId="@+id/secondary_mobile_network_layout" + android:layout="@layout/qs_dialog_secondary_mobile_network" + style="@style/InternetDialog.Network"/> + <LinearLayout android:id="@+id/turn_on_wifi_layout" style="@style/InternetDialog.Network" diff --git a/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml b/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml new file mode 100644 index 000000000000..4592c5e6332c --- /dev/null +++ b/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 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. + --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + style="@style/InternetDialog.Network"> + + <FrameLayout + android:layout_width="24dp" + android:layout_height="24dp" + android:clickable="false" + android:layout_gravity="center_vertical|start"> + <ImageView + android:id="@+id/secondary_signal_icon" + android:autoMirrored="true" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"/> + </FrameLayout> + + <LinearLayout + android:layout_weight="1" + android:orientation="vertical" + android:clickable="false" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="start|center_vertical"> + <TextView + android:id="@+id/secondary_mobile_title" + android:maxLines="1" + style="@style/InternetDialog.NetworkTitle"/> + <TextView + android:id="@+id/secondary_mobile_summary" + style="@style/InternetDialog.NetworkSummary"/> + </LinearLayout> + + <FrameLayout + android:layout_width="24dp" + android:layout_height="match_parent" + android:clickable="false" + android:layout_gravity="end|center_vertical" + android:gravity="center"> + <ImageView + android:id="@+id/secondary_settings_icon" + android:src="@drawable/ic_settings_24dp" + android:layout_width="24dp" + android:layout_gravity="end|center_vertical" + android:layout_height="wrap_content"/> + </FrameLayout> +</LinearLayout> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index d4d8843acdea..44031bb99751 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2022,6 +2022,15 @@ <!-- Text used to refer to the user's current carrier in mobile_data_disable_message if the users's mobile network carrier name is not available [CHAR LIMIT=NONE] --> <string name="mobile_data_disable_message_default_carrier">your carrier</string> + <!-- Title of the dialog to turn off data usage [CHAR LIMIT=NONE] --> + <string name="auto_data_switch_disable_title">Switch back to <xliff:g id="carrier" example="T-Mobile">%s</xliff:g>?</string> + <!-- Message body of the dialog to turn off data usage [CHAR LIMIT=NONE] --> + <string name="auto_data_switch_disable_message">Mobile data won\’t automatically switch based on availability</string> + <!-- Negative button title of the quick settings switch back to DDS dialog [CHAR LIMIT=NONE] --> + <string name="auto_data_switch_dialog_negative_button">No thanks</string> + <!-- Positive button title of the quick settings switch back to DDS dialog [CHAR LIMIT=NONE] --> + <string name="auto_data_switch_dialog_positive_button">Yes, switch</string> + <!-- Warning shown when user input has been blocked due to another app overlaying screen content. Since we don't know what the app is showing on top of the input target, we can't verify user consent. [CHAR LIMIT=NONE] --> @@ -2527,6 +2536,12 @@ Summary indicating that a SIM has an active mobile data connection [CHAR LIMIT=50] --> <string name="mobile_data_connection_active">Connected</string> <!-- Provider Model: + Summary indicating that a SIM is temporarily connected to mobile data [CHAR LIMIT=50] --> + <string name="mobile_data_temp_connection_active">Temporarily connected</string> + <!-- Provider Model: + Summary indicating that a SIM is temporarily connected to mobile data [CHAR LIMIT=50] --> + <string name="mobile_data_poor_connection">Poor connection</string> + <!-- Provider Model: Summary indicating that a SIM has no mobile data connection [CHAR LIMIT=50] --> <string name="mobile_data_off_summary">Mobile data won\u0027t auto\u2011connect</string> <!-- Provider Model: diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 9bd3cb17d66e..142dbc861d02 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -154,6 +154,9 @@ object Flags { // TODO(b/254512678): Tracking Bug @JvmField val NEW_FOOTER_ACTIONS = ReleasedFlag(507) + // TODO(b/244064524): Tracking Bug + @JvmField val QS_SECONDARY_DATA_SUB_INFO = UnreleasedFlag(508, teamfood = true) + // 600- status bar // TODO(b/254513246): Tracking Bug val STATUS_BAR_USER_SWITCHER = ResourceBooleanFlag(602, R.bool.flag_user_switcher_chip) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java index 24c4723d8b50..a895d72a7492 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -39,6 +39,7 @@ import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewStub; import android.view.Window; import android.view.WindowManager; import android.widget.Button; @@ -62,6 +63,7 @@ import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils; import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan; +import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -72,6 +74,8 @@ import com.android.wifitrackerlib.WifiEntry; import java.util.List; import java.util.concurrent.Executor; +import javax.inject.Inject; + /** * Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks. */ @@ -86,6 +90,7 @@ public class InternetDialog extends SystemUIDialog implements private final Handler mHandler; private final Executor mBackgroundExecutor; + private final DialogLaunchAnimator mDialogLaunchAnimator; @VisibleForTesting protected InternetAdapter mAdapter; @@ -109,6 +114,7 @@ public class InternetDialog extends SystemUIDialog implements private LinearLayout mInternetDialogLayout; private LinearLayout mConnectedWifListLayout; private LinearLayout mMobileNetworkLayout; + private LinearLayout mSecondaryMobileNetworkLayout; private LinearLayout mTurnWifiOnLayout; private LinearLayout mEthernetLayout; private TextView mWifiToggleTitleText; @@ -123,6 +129,8 @@ public class InternetDialog extends SystemUIDialog implements private ImageView mSignalIcon; private TextView mMobileTitleText; private TextView mMobileSummaryText; + private TextView mSecondaryMobileTitleText; + private TextView mSecondaryMobileSummaryText; private TextView mAirplaneModeSummaryText; private Switch mMobileDataToggle; private View mMobileToggleDivider; @@ -158,9 +166,11 @@ public class InternetDialog extends SystemUIDialog implements mInternetDialogSubTitle.setText(getSubtitleText()); }; + @Inject public InternetDialog(Context context, InternetDialogFactory internetDialogFactory, InternetDialogController internetDialogController, boolean canConfigMobileData, boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger, + DialogLaunchAnimator dialogLaunchAnimator, @Main Handler handler, @Background Executor executor, KeyguardStateController keyguardStateController) { super(context); @@ -183,6 +193,7 @@ public class InternetDialog extends SystemUIDialog implements mKeyguard = keyguardStateController; mUiEventLogger = uiEventLogger; + mDialogLaunchAnimator = dialogLaunchAnimator; mAdapter = new InternetAdapter(mInternetDialogController); if (!aboveStatusBar) { getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); @@ -287,6 +298,9 @@ public class InternetDialog extends SystemUIDialog implements mMobileNetworkLayout.setOnClickListener(null); mMobileDataToggle.setOnCheckedChangeListener(null); mConnectedWifListLayout.setOnClickListener(null); + if (mSecondaryMobileNetworkLayout != null) { + mSecondaryMobileNetworkLayout.setOnClickListener(null); + } mSeeAllLayout.setOnClickListener(null); mWiFiToggle.setOnCheckedChangeListener(null); mDoneButton.setOnClickListener(null); @@ -341,6 +355,10 @@ public class InternetDialog extends SystemUIDialog implements private void setOnClickListener() { mMobileNetworkLayout.setOnClickListener(v -> { + int autoSwitchNonDdsSubId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId(); + if (autoSwitchNonDdsSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + showTurnOffAutoDataSwitchDialog(autoSwitchNonDdsSubId); + } mInternetDialogController.connectCarrierNetwork(); }); mMobileDataToggle.setOnCheckedChangeListener( @@ -385,11 +403,14 @@ public class InternetDialog extends SystemUIDialog implements if (!mInternetDialogController.hasActiveSubId() && (!isWifiEnabled || !isCarrierNetworkActive)) { mMobileNetworkLayout.setVisibility(View.GONE); + if (mSecondaryMobileNetworkLayout != null) { + mSecondaryMobileNetworkLayout.setVisibility(View.GONE); + } } else { mMobileNetworkLayout.setVisibility(View.VISIBLE); mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled()); - mMobileTitleText.setText(getMobileNetworkTitle()); - String summary = getMobileNetworkSummary(); + mMobileTitleText.setText(getMobileNetworkTitle(mDefaultDataSubId)); + String summary = getMobileNetworkSummary(mDefaultDataSubId); if (!TextUtils.isEmpty(summary)) { mMobileSummaryText.setText( Html.fromHtml(summary, Html.FROM_HTML_MODE_LEGACY)); @@ -399,28 +420,11 @@ public class InternetDialog extends SystemUIDialog implements mMobileSummaryText.setVisibility(View.GONE); } mBackgroundExecutor.execute(() -> { - Drawable drawable = getSignalStrengthDrawable(); + Drawable drawable = getSignalStrengthDrawable(mDefaultDataSubId); mHandler.post(() -> { mSignalIcon.setImageDrawable(drawable); }); }); - mMobileTitleText.setTextAppearance(isNetworkConnected - ? R.style.TextAppearance_InternetDialog_Active - : R.style.TextAppearance_InternetDialog); - int secondaryRes = isNetworkConnected - ? R.style.TextAppearance_InternetDialog_Secondary_Active - : R.style.TextAppearance_InternetDialog_Secondary; - mMobileSummaryText.setTextAppearance(secondaryRes); - // Set airplane mode to the summary for carrier network - if (mInternetDialogController.isAirplaneModeEnabled()) { - mAirplaneModeSummaryText.setVisibility(View.VISIBLE); - mAirplaneModeSummaryText.setText(mContext.getText(R.string.airplane_mode)); - mAirplaneModeSummaryText.setTextAppearance(secondaryRes); - } else { - mAirplaneModeSummaryText.setVisibility(View.GONE); - } - mMobileNetworkLayout.setBackground( - isNetworkConnected ? mBackgroundOn : mBackgroundOff); TypedArray array = mContext.obtainStyledAttributes( R.style.InternetDialog_Divider_Active, new int[]{android.R.attr.background}); @@ -433,6 +437,86 @@ public class InternetDialog extends SystemUIDialog implements mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE); mMobileToggleDivider.setVisibility( mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE); + + // Display the info for the non-DDS if it's actively being used + int autoSwitchNonDdsSubId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId(); + int nonDdsVisibility = autoSwitchNonDdsSubId + != SubscriptionManager.INVALID_SUBSCRIPTION_ID ? View.VISIBLE : View.GONE; + + int secondaryRes = isNetworkConnected + ? R.style.TextAppearance_InternetDialog_Secondary_Active + : R.style.TextAppearance_InternetDialog_Secondary; + if (nonDdsVisibility == View.VISIBLE) { + // non DDS is the currently active sub, set primary visual for it + ViewStub stub = mDialogView.findViewById(R.id.secondary_mobile_network_stub); + if (stub != null) { + stub.inflate(); + } + mSecondaryMobileNetworkLayout = findViewById(R.id.secondary_mobile_network_layout); + mSecondaryMobileNetworkLayout.setOnClickListener( + this::onClickConnectedSecondarySub); + mSecondaryMobileNetworkLayout.setBackground(mBackgroundOn); + + mSecondaryMobileTitleText = mDialogView.requireViewById( + R.id.secondary_mobile_title); + mSecondaryMobileTitleText.setText(getMobileNetworkTitle(autoSwitchNonDdsSubId)); + mSecondaryMobileTitleText.setTextAppearance( + R.style.TextAppearance_InternetDialog_Active); + + mSecondaryMobileSummaryText = + mDialogView.requireViewById(R.id.secondary_mobile_summary); + summary = getMobileNetworkSummary(autoSwitchNonDdsSubId); + if (!TextUtils.isEmpty(summary)) { + mSecondaryMobileSummaryText.setText( + Html.fromHtml(summary, Html.FROM_HTML_MODE_LEGACY)); + mSecondaryMobileSummaryText.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE); + mSecondaryMobileSummaryText.setTextAppearance( + R.style.TextAppearance_InternetDialog_Active); + } + + ImageView mSecondarySignalIcon = + mDialogView.requireViewById(R.id.secondary_signal_icon); + mBackgroundExecutor.execute(() -> { + Drawable drawable = getSignalStrengthDrawable(autoSwitchNonDdsSubId); + mHandler.post(() -> { + mSecondarySignalIcon.setImageDrawable(drawable); + }); + }); + + ImageView mSecondaryMobileSettingsIcon = + mDialogView.requireViewById(R.id.secondary_settings_icon); + mSecondaryMobileSettingsIcon.setColorFilter( + mContext.getColor(R.color.connected_network_primary_color)); + + // set secondary visual for default data sub + mMobileNetworkLayout.setBackground(mBackgroundOff); + mMobileTitleText.setTextAppearance(R.style.TextAppearance_InternetDialog); + mMobileSummaryText.setTextAppearance( + R.style.TextAppearance_InternetDialog_Secondary); + mSignalIcon.setColorFilter( + mContext.getColor(R.color.connected_network_secondary_color)); + } else { + mMobileNetworkLayout.setBackground( + isNetworkConnected ? mBackgroundOn : mBackgroundOff); + mMobileTitleText.setTextAppearance(isNetworkConnected + ? + R.style.TextAppearance_InternetDialog_Active + : R.style.TextAppearance_InternetDialog); + mMobileSummaryText.setTextAppearance(secondaryRes); + } + + if (mSecondaryMobileNetworkLayout != null) { + mSecondaryMobileNetworkLayout.setVisibility(nonDdsVisibility); + } + + // Set airplane mode to the summary for carrier network + if (mInternetDialogController.isAirplaneModeEnabled()) { + mAirplaneModeSummaryText.setVisibility(View.VISIBLE); + mAirplaneModeSummaryText.setText(mContext.getText(R.string.airplane_mode)); + mAirplaneModeSummaryText.setTextAppearance(secondaryRes); + } else { + mAirplaneModeSummaryText.setVisibility(View.GONE); + } } } @@ -471,6 +555,10 @@ public class InternetDialog extends SystemUIDialog implements mInternetDialogController.getInternetWifiDrawable(mConnectedWifiEntry)); mWifiSettingsIcon.setColorFilter( mContext.getColor(R.color.connected_network_primary_color)); + + if (mSecondaryMobileNetworkLayout != null) { + mSecondaryMobileNetworkLayout.setVisibility(View.GONE); + } } @MainThread @@ -541,6 +629,11 @@ public class InternetDialog extends SystemUIDialog implements mInternetDialogController.launchWifiDetailsSetting(mConnectedWifiEntry.getKey(), view); } + /** For DSDS auto data switch **/ + void onClickConnectedSecondarySub(View view) { + mInternetDialogController.launchMobileNetworkSettings(view); + } + void onClickSeeMoreButton(View view) { mInternetDialogController.launchNetworkSetting(view); } @@ -555,16 +648,16 @@ public class InternetDialog extends SystemUIDialog implements mIsProgressBarVisible && !mIsSearchingHidden); } - private Drawable getSignalStrengthDrawable() { - return mInternetDialogController.getSignalStrengthDrawable(); + private Drawable getSignalStrengthDrawable(int subId) { + return mInternetDialogController.getSignalStrengthDrawable(subId); } - CharSequence getMobileNetworkTitle() { - return mInternetDialogController.getMobileNetworkTitle(); + CharSequence getMobileNetworkTitle(int subId) { + return mInternetDialogController.getMobileNetworkTitle(subId); } - String getMobileNetworkSummary() { - return mInternetDialogController.getMobileNetworkSummary(); + String getMobileNetworkSummary(int subId) { + return mInternetDialogController.getMobileNetworkSummary(subId); } protected void showProgressBar() { @@ -602,8 +695,8 @@ public class InternetDialog extends SystemUIDialog implements } private void showTurnOffMobileDialog() { - CharSequence carrierName = getMobileNetworkTitle(); - boolean isInService = mInternetDialogController.isVoiceStateInService(); + CharSequence carrierName = getMobileNetworkTitle(mDefaultDataSubId); + boolean isInService = mInternetDialogController.isVoiceStateInService(mDefaultDataSubId); if (TextUtils.isEmpty(carrierName) || !isInService) { carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier); } @@ -627,7 +720,33 @@ public class InternetDialog extends SystemUIDialog implements SystemUIDialog.setShowForAllUsers(mAlertDialog, true); SystemUIDialog.registerDismissListener(mAlertDialog); SystemUIDialog.setWindowOnTop(mAlertDialog, mKeyguard.isShowing()); - mAlertDialog.show(); + mDialogLaunchAnimator.showFromDialog(mAlertDialog, this, null, false); + } + + private void showTurnOffAutoDataSwitchDialog(int subId) { + CharSequence carrierName = getMobileNetworkTitle(mDefaultDataSubId); + if (TextUtils.isEmpty(carrierName)) { + carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier); + } + mAlertDialog = new Builder(mContext) + .setTitle(mContext.getString(R.string.auto_data_switch_disable_title, carrierName)) + .setMessage(R.string.auto_data_switch_disable_message) + .setNegativeButton(R.string.auto_data_switch_dialog_negative_button, + (d, w) -> {}) + .setPositiveButton(R.string.auto_data_switch_dialog_positive_button, + (d, w) -> { + mInternetDialogController + .setAutoDataSwitchMobileDataPolicy(subId, false); + if (mSecondaryMobileNetworkLayout != null) { + mSecondaryMobileNetworkLayout.setVisibility(View.GONE); + } + }) + .create(); + mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + SystemUIDialog.setShowForAllUsers(mAlertDialog, true); + SystemUIDialog.registerDismissListener(mAlertDialog); + SystemUIDialog.setWindowOnTop(mAlertDialog, mKeyguard.isShowing()); + mDialogLaunchAnimator.showFromDialog(mAlertDialog, this, null, false); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index 0e00c46bc77f..aa6e67841e78 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -37,6 +37,7 @@ import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; import android.net.wifi.WifiManager; +import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; @@ -78,6 +79,8 @@ import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.connectivity.AccessPointController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -90,6 +93,7 @@ import com.android.wifitrackerlib.MergedCarrierEntry; import com.android.wifitrackerlib.WifiEntry; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -113,6 +117,17 @@ public class InternetDialogController implements AccessPointController.AccessPoi "android.settings.NETWORK_PROVIDER_SETTINGS"; private static final String ACTION_WIFI_SCANNING_SETTINGS = "android.settings.WIFI_SCANNING_SETTINGS"; + /** + * Fragment "key" argument passed thru {@link #SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS} + */ + private static final String SETTINGS_EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key"; + /** + * When starting this activity, this extra can also be specified to supply a Bundle of arguments + * to pass to that fragment when it is instantiated during the initial creation of the activity. + */ + private static final String SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS = + ":settings:show_fragment_args"; + private static final String AUTO_DATA_SWITCH_SETTING_R_ID = "auto_data_switch"; public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT); public static final int NO_CELL_DATA_TYPE_ICON = 0; private static final int SUBTITLE_TEXT_WIFI_IS_OFF = R.string.wifi_is_off; @@ -130,9 +145,12 @@ public class InternetDialogController implements AccessPointController.AccessPoi static final int MAX_WIFI_ENTRY_COUNT = 3; + private final FeatureFlags mFeatureFlags; + private WifiManager mWifiManager; private Context mContext; private SubscriptionManager mSubscriptionManager; + private Map<Integer, TelephonyManager> mSubIdTelephonyManagerMap = new HashMap<>(); private TelephonyManager mTelephonyManager; private ConnectivityManager mConnectivityManager; private CarrierConfigTracker mCarrierConfigTracker; @@ -155,6 +173,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi private WindowManager mWindowManager; private ToastFactory mToastFactory; private SignalDrawable mSignalDrawable; + private SignalDrawable mSecondarySignalDrawable; // For the secondary mobile data sub in DSDS private LocationController mLocationController; private DialogLaunchAnimator mDialogLaunchAnimator; private boolean mHasWifiEntries; @@ -213,7 +232,8 @@ public class InternetDialogController implements AccessPointController.AccessPoi CarrierConfigTracker carrierConfigTracker, LocationController locationController, DialogLaunchAnimator dialogLaunchAnimator, - WifiStateWorker wifiStateWorker + WifiStateWorker wifiStateWorker, + FeatureFlags featureFlags ) { if (DEBUG) { Log.d(TAG, "Init InternetDialogController"); @@ -242,10 +262,12 @@ public class InternetDialogController implements AccessPointController.AccessPoi mWindowManager = windowManager; mToastFactory = toastFactory; mSignalDrawable = new SignalDrawable(mContext); + mSecondarySignalDrawable = new SignalDrawable(mContext); mLocationController = locationController; mDialogLaunchAnimator = dialogLaunchAnimator; mConnectedWifiInternetMonitor = new ConnectedWifiInternetMonitor(); mWifiStateWorker = wifiStateWorker; + mFeatureFlags = featureFlags; } void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) { @@ -267,6 +289,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi } mConfig = MobileMappings.Config.readConfig(mContext); mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId); + mSubIdTelephonyManagerMap.put(mDefaultDataSubId, mTelephonyManager); mInternetTelephonyCallback = new InternetTelephonyCallback(); mTelephonyManager.registerTelephonyCallback(mExecutor, mInternetTelephonyCallback); // Listen the connectivity changes @@ -280,7 +303,9 @@ public class InternetDialogController implements AccessPointController.AccessPoi Log.d(TAG, "onStop"); } mBroadcastDispatcher.unregisterReceiver(mConnectionStateReceiver); - mTelephonyManager.unregisterTelephonyCallback(mInternetTelephonyCallback); + for (TelephonyManager tm : mSubIdTelephonyManagerMap.values()) { + tm.unregisterTelephonyCallback(mInternetTelephonyCallback); + } mSubscriptionManager.removeOnSubscriptionsChangedListener( mOnSubscriptionsChangedListener); mAccessPointController.removeAccessPointCallback(this); @@ -371,7 +396,10 @@ public class InternetDialogController implements AccessPointController.AccessPoi if (DEBUG) { Log.d(TAG, "No Wi-Fi item."); } - if (!hasActiveSubId() || (!isVoiceStateInService() && !isDataStateInService())) { + boolean isActiveOnNonDds = getActiveAutoSwitchNonDdsSubId() != SubscriptionManager + .INVALID_SUBSCRIPTION_ID; + if (!hasActiveSubId() || (!isVoiceStateInService(mDefaultDataSubId) + && !isDataStateInService(mDefaultDataSubId) && !isActiveOnNonDds)) { if (DEBUG) { Log.d(TAG, "No carrier or service is out of service."); } @@ -412,7 +440,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi return drawable; } - Drawable getSignalStrengthDrawable() { + Drawable getSignalStrengthDrawable(int subId) { Drawable drawable = mContext.getDrawable( R.drawable.ic_signal_strength_zero_bar_no_internet); try { @@ -424,9 +452,10 @@ public class InternetDialogController implements AccessPointController.AccessPoi } boolean isCarrierNetworkActive = isCarrierNetworkActive(); - if (isDataStateInService() || isVoiceStateInService() || isCarrierNetworkActive) { + if (isDataStateInService(subId) || isVoiceStateInService(subId) + || isCarrierNetworkActive) { AtomicReference<Drawable> shared = new AtomicReference<>(); - shared.set(getSignalStrengthDrawableWithLevel(isCarrierNetworkActive)); + shared.set(getSignalStrengthDrawableWithLevel(isCarrierNetworkActive, subId)); drawable = shared.get(); } @@ -447,24 +476,30 @@ public class InternetDialogController implements AccessPointController.AccessPoi * * @return The Drawable which is a signal bar icon with level. */ - Drawable getSignalStrengthDrawableWithLevel(boolean isCarrierNetworkActive) { - final SignalStrength strength = mTelephonyManager.getSignalStrength(); + Drawable getSignalStrengthDrawableWithLevel(boolean isCarrierNetworkActive, int subId) { + TelephonyManager tm = mSubIdTelephonyManagerMap.getOrDefault(subId, mTelephonyManager); + final SignalStrength strength = tm.getSignalStrength(); int level = (strength == null) ? 0 : strength.getLevel(); int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS; if (isCarrierNetworkActive) { level = getCarrierNetworkLevel(); numLevels = WifiEntry.WIFI_LEVEL_MAX + 1; - } else if (mSubscriptionManager != null && shouldInflateSignalStrength(mDefaultDataSubId)) { + } else if (mSubscriptionManager != null && shouldInflateSignalStrength(subId)) { level += 1; numLevels += 1; } - return getSignalStrengthIcon(mContext, level, numLevels, NO_CELL_DATA_TYPE_ICON, + return getSignalStrengthIcon(subId, mContext, level, numLevels, NO_CELL_DATA_TYPE_ICON, !isMobileDataEnabled()); } - Drawable getSignalStrengthIcon(Context context, int level, int numLevels, + Drawable getSignalStrengthIcon(int subId, Context context, int level, int numLevels, int iconType, boolean cutOut) { - mSignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut)); + boolean isForDds = subId == mDefaultDataSubId; + if (isForDds) { + mSignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut)); + } else { + mSecondarySignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut)); + } // Make the network type drawable final Drawable networkDrawable = @@ -473,7 +508,8 @@ public class InternetDialogController implements AccessPointController.AccessPoi : context.getResources().getDrawable(iconType, context.getTheme()); // Overlay the two drawables - final Drawable[] layers = {networkDrawable, mSignalDrawable}; + final Drawable[] layers = {networkDrawable, isForDds + ? mSignalDrawable : mSecondarySignalDrawable}; final int iconSize = context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size); @@ -571,14 +607,39 @@ public class InternetDialogController implements AccessPointController.AccessPoi info -> info.uniqueName)); } - CharSequence getMobileNetworkTitle() { - return getUniqueSubscriptionDisplayName(mDefaultDataSubId, mContext); + /** + * @return the subId of the visible non-DDS if it's actively being used for data, otherwise + * return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}. + */ + int getActiveAutoSwitchNonDdsSubId() { + if (!mFeatureFlags.isEnabled(Flags.QS_SECONDARY_DATA_SUB_INFO)) { + // sets the non-DDS to be not found to hide its visual + return SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo( + SubscriptionManager.getActiveDataSubscriptionId()); + if (subInfo != null && subInfo.getSubscriptionId() != mDefaultDataSubId + && !subInfo.isOpportunistic()) { + int subId = subInfo.getSubscriptionId(); + if (mSubIdTelephonyManagerMap.get(subId) == null) { + TelephonyManager secondaryTm = mTelephonyManager.createForSubscriptionId(subId); + secondaryTm.registerTelephonyCallback(mExecutor, mInternetTelephonyCallback); + mSubIdTelephonyManagerMap.put(subId, secondaryTm); + } + return subId; + } + return SubscriptionManager.INVALID_SUBSCRIPTION_ID; + + } + + CharSequence getMobileNetworkTitle(int subId) { + return getUniqueSubscriptionDisplayName(subId, mContext); } - String getMobileNetworkSummary() { + String getMobileNetworkSummary(int subId) { String description = getNetworkTypeDescription(mContext, mConfig, - mTelephonyDisplayInfo, mDefaultDataSubId); - return getMobileSummary(mContext, description); + mTelephonyDisplayInfo, subId); + return getMobileSummary(mContext, description, subId); } /** @@ -606,22 +667,28 @@ public class InternetDialogController implements AccessPointController.AccessPoi ? SubscriptionManager.getResourcesForSubId(context, subId).getString(resId) : ""; } - private String getMobileSummary(Context context, String networkTypeDescription) { + private String getMobileSummary(Context context, String networkTypeDescription, int subId) { if (!isMobileDataEnabled()) { return context.getString(R.string.mobile_data_off_summary); } String summary = networkTypeDescription; + boolean isForDds = subId == mDefaultDataSubId; + int activeSubId = getActiveAutoSwitchNonDdsSubId(); + boolean isOnNonDds = activeSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID; // Set network description for the carrier network when connecting to the carrier network // under the airplane mode ON. if (activeNetworkIsCellular() || isCarrierNetworkActive()) { summary = context.getString(R.string.preference_summary_default_combination, - context.getString(R.string.mobile_data_connection_active), + context.getString( + isForDds // if nonDds is active, explains Dds status as poor connection + ? (isOnNonDds ? R.string.mobile_data_poor_connection + : R.string.mobile_data_connection_active) + : R.string.mobile_data_temp_connection_active), networkTypeDescription); - } else if (!isDataStateInService()) { + } else if (!isDataStateInService(subId)) { summary = context.getString(R.string.mobile_data_no_connection); } - return summary; } @@ -647,6 +714,26 @@ public class InternetDialogController implements AccessPointController.AccessPoi } } + void launchMobileNetworkSettings(View view) { + final int subId = getActiveAutoSwitchNonDdsSubId(); + if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + Log.w(TAG, "launchMobileNetworkSettings fail, invalid subId:" + subId); + return; + } + startActivity(getSubSettingIntent(subId), view); + } + + Intent getSubSettingIntent(int subId) { + final Intent intent = new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS); + + final Bundle fragmentArgs = new Bundle(); + // Special contract for Settings to highlight permission row + fragmentArgs.putString(SETTINGS_EXTRA_FRAGMENT_ARG_KEY, AUTO_DATA_SWITCH_SETTING_R_ID); + fragmentArgs.putInt(Settings.EXTRA_SUB_ID, subId); + intent.putExtra(SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs); + return intent; + } + void launchWifiScanningSetting(View view) { final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -824,8 +911,20 @@ public class InternetDialogController implements AccessPointController.AccessPoi mWorkerHandler.post(() -> setMergedCarrierWifiEnabledIfNeed(subId, enabled)); } - boolean isDataStateInService() { - final ServiceState serviceState = mTelephonyManager.getServiceState(); + void setAutoDataSwitchMobileDataPolicy(int subId, boolean enable) { + TelephonyManager tm = mSubIdTelephonyManagerMap.getOrDefault(subId, mTelephonyManager); + if (tm == null) { + if (DEBUG) { + Log.d(TAG, "TelephonyManager is null, can not set mobile data."); + } + return; + } + tm.setMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, enable); + } + + boolean isDataStateInService(int subId) { + TelephonyManager tm = mSubIdTelephonyManagerMap.getOrDefault(subId, mTelephonyManager); + final ServiceState serviceState = tm.getServiceState(); NetworkRegistrationInfo regInfo = (serviceState == null) ? null : serviceState.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, @@ -833,7 +932,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi return (regInfo == null) ? false : regInfo.isRegistered(); } - boolean isVoiceStateInService() { + boolean isVoiceStateInService(int subId) { if (mTelephonyManager == null) { if (DEBUG) { Log.d(TAG, "TelephonyManager is null, can not detect voice state."); @@ -841,7 +940,8 @@ public class InternetDialogController implements AccessPointController.AccessPoi return false; } - final ServiceState serviceState = mTelephonyManager.getServiceState(); + TelephonyManager tm = mSubIdTelephonyManagerMap.getOrDefault(subId, mTelephonyManager); + final ServiceState serviceState = tm.getServiceState(); return serviceState != null && serviceState.getState() == serviceState.STATE_IN_SERVICE; } @@ -1132,6 +1232,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi if (SubscriptionManager.isUsableSubscriptionId(mDefaultDataSubId)) { mTelephonyManager.unregisterTelephonyCallback(mInternetTelephonyCallback); mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId); + mSubIdTelephonyManagerMap.put(mDefaultDataSubId, mTelephonyManager); mTelephonyManager.registerTelephonyCallback(mHandler::post, mInternetTelephonyCallback); mCallback.onSubscriptionsChanged(mDefaultDataSubId); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt index 8566ca308738..796672dc0ead 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt @@ -66,7 +66,8 @@ class InternetDialogFactory @Inject constructor( } else { internetDialog = InternetDialog( context, this, internetDialogController, - canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler, + canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, + dialogLaunchAnimator, handler, executor, keyguardStateController ) if (view != null) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java index d70370552bb1..2ef731236851 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java @@ -5,6 +5,7 @@ import static android.telephony.SignalStrength.NUM_SIGNAL_STRENGTH_BINS; import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GREAT; import static android.telephony.SignalStrength.SIGNAL_STRENGTH_POOR; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.systemui.qs.tiles.dialog.InternetDialogController.TOAST_PARAMS_HORIZONTAL_WEIGHT; import static com.android.systemui.qs.tiles.dialog.InternetDialogController.TOAST_PARAMS_VERTICAL_WEIGHT; import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX; @@ -13,6 +14,7 @@ import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -38,6 +40,7 @@ import android.net.wifi.WifiManager; import android.os.Handler; import android.telephony.ServiceState; import android.telephony.SignalStrength; +import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.testing.AndroidTestingRunner; @@ -57,6 +60,8 @@ import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.UnreleasedFlag; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.connectivity.AccessPointController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -70,12 +75,15 @@ import com.android.systemui.util.time.FakeSystemClock; import com.android.wifitrackerlib.MergedCarrierEntry; import com.android.wifitrackerlib.WifiEntry; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; +import org.mockito.quality.Strictness; import java.util.ArrayList; import java.util.List; @@ -86,6 +94,9 @@ import java.util.List; public class InternetDialogControllerTest extends SysuiTestCase { private static final int SUB_ID = 1; + private static final int SUB_ID2 = 2; + + private MockitoSession mStaticMockSession; //SystemUIToast private static final int GRAVITY_FLAGS = Gravity.FILL_HORIZONTAL | Gravity.FILL_VERTICAL; @@ -158,6 +169,8 @@ public class InternetDialogControllerTest extends SysuiTestCase { private WifiStateWorker mWifiStateWorker; @Mock private SignalStrength mSignalStrength; + @Mock + private FeatureFlags mFlags; private TestableResources mTestableResources; private InternetDialogController mInternetDialogController; @@ -167,6 +180,10 @@ public class InternetDialogControllerTest extends SysuiTestCase { @Before public void setUp() { + mStaticMockSession = mockitoSession() + .mockStatic(SubscriptionManager.class) + .strictness(Strictness.LENIENT) + .startMocking(); MockitoAnnotations.initMocks(this); mTestableResources = mContext.getOrCreateTestableResources(); doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt()); @@ -183,6 +200,7 @@ public class InternetDialogControllerTest extends SysuiTestCase { mAccessPoints.add(mWifiEntry1); when(mAccessPointController.getMergedCarrierEntry()).thenReturn(mMergedCarrierEntry); when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID}); + when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(SUB_ID); when(mToastFactory.createToast(any(), anyString(), anyString(), anyInt(), anyInt())) .thenReturn(mSystemUIToast); when(mSystemUIToast.getView()).thenReturn(mToastView); @@ -196,7 +214,7 @@ public class InternetDialogControllerTest extends SysuiTestCase { mConnectivityManager, mHandler, mExecutor, mBroadcastDispatcher, mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController, mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker, - mLocationController, mDialogLaunchAnimator, mWifiStateWorker); + mLocationController, mDialogLaunchAnimator, mWifiStateWorker, mFlags); mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, mInternetDialogController.mOnSubscriptionsChangedListener); mInternetDialogController.onStart(mInternetDialogCallback, true); @@ -205,6 +223,11 @@ public class InternetDialogControllerTest extends SysuiTestCase { mInternetDialogController.mWifiIconInjector = mWifiIconInjector; } + @After + public void tearDown() { + mStaticMockSession.finishMocking(); + } + @Test public void connectCarrierNetwork_mergedCarrierEntryCanConnect_connectAndCreateSysUiToast() { when(mTelephonyManager.isDataEnabled()).thenReturn(true); @@ -387,15 +410,45 @@ public class InternetDialogControllerTest extends SysuiTestCase { @Test public void getSubtitleText_withNoService_returnNoNetworksAvailable() { + when(mFlags.isEnabled(any(UnreleasedFlag.class))).thenReturn(true); + InternetDialogController spyController = spy(mInternetDialogController); fakeAirplaneModeEnabled(false); when(mWifiStateWorker.isWifiEnabled()).thenReturn(true); - mInternetDialogController.onAccessPointsChanged(null /* accessPoints */); + spyController.onAccessPointsChanged(null /* accessPoints */); + doReturn(SUB_ID2).when(spyController).getActiveAutoSwitchNonDdsSubId(); doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState(); doReturn(mServiceState).when(mTelephonyManager).getServiceState(); doReturn(TelephonyManager.DATA_DISCONNECTED).when(mTelephonyManager).getDataState(); - assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false), + assertFalse(TextUtils.equals(spyController.getSubtitleText(false), + getResourcesString("all_network_unavailable"))); + + doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID) + .when(spyController).getActiveAutoSwitchNonDdsSubId(); + spyController.onAccessPointsChanged(null /* accessPoints */); + assertTrue(TextUtils.equals(spyController.getSubtitleText(false), + getResourcesString("all_network_unavailable"))); + } + + @Test + public void getSubtitleText_withNoService_returnNoNetworksAvailable_flagOff() { + InternetDialogController spyController = spy(mInternetDialogController); + fakeAirplaneModeEnabled(false); + when(mWifiStateWorker.isWifiEnabled()).thenReturn(true); + spyController.onAccessPointsChanged(null /* accessPoints */); + + doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState(); + doReturn(mServiceState).when(mTelephonyManager).getServiceState(); + doReturn(TelephonyManager.DATA_DISCONNECTED).when(mTelephonyManager).getDataState(); + + assertTrue(TextUtils.equals(spyController.getSubtitleText(false), + getResourcesString("all_network_unavailable"))); + + doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID) + .when(spyController).getActiveAutoSwitchNonDdsSubId(); + spyController.onAccessPointsChanged(null /* accessPoints */); + assertTrue(TextUtils.equals(spyController.getSubtitleText(false), getResourcesString("all_network_unavailable"))); } @@ -713,6 +766,108 @@ public class InternetDialogControllerTest extends SysuiTestCase { } @Test + public void getSignalStrengthIcon_differentSubId() { + when(mFlags.isEnabled(any(UnreleasedFlag.class))).thenReturn(true); + InternetDialogController spyController = spy(mInternetDialogController); + Drawable icons = spyController.getSignalStrengthIcon(SUB_ID, mContext, 1, 1, 0, false); + Drawable icons2 = spyController.getSignalStrengthIcon(SUB_ID2, mContext, 1, 1, 0, false); + + assertThat(icons).isNotEqualTo(icons2); + } + + @Test + public void getActiveAutoSwitchNonDdsSubId() { + when(mFlags.isEnabled(any(UnreleasedFlag.class))).thenReturn(true); + // active on non-DDS + SubscriptionInfo info = mock(SubscriptionInfo.class); + doReturn(SUB_ID2).when(info).getSubscriptionId(); + when(mSubscriptionManager.getActiveSubscriptionInfo(anyInt())).thenReturn(info); + + int subId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId(); + assertThat(subId).isEqualTo(SUB_ID2); + + // active on CBRS + doReturn(true).when(info).isOpportunistic(); + subId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId(); + assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID); + + // active on DDS + doReturn(false).when(info).isOpportunistic(); + doReturn(SUB_ID).when(info).getSubscriptionId(); + when(mSubscriptionManager.getActiveSubscriptionInfo(anyInt())).thenReturn(info); + + subId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId(); + assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } + + @Test + public void getActiveAutoSwitchNonDdsSubId_flagOff() { + // active on non-DDS + SubscriptionInfo info = mock(SubscriptionInfo.class); + doReturn(SUB_ID2).when(info).getSubscriptionId(); + when(mSubscriptionManager.getActiveSubscriptionInfo(anyInt())).thenReturn(info); + + int subId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId(); + assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } + + @Test + public void getMobileNetworkSummary() { + when(mFlags.isEnabled(any(UnreleasedFlag.class))).thenReturn(true); + InternetDialogController spyController = spy(mInternetDialogController); + doReturn(SUB_ID2).when(spyController).getActiveAutoSwitchNonDdsSubId(); + doReturn(true).when(spyController).isMobileDataEnabled(); + doReturn(true).when(spyController).activeNetworkIsCellular(); + String dds = spyController.getMobileNetworkSummary(SUB_ID); + String nonDds = spyController.getMobileNetworkSummary(SUB_ID2); + + assertThat(dds).contains(mContext.getString(R.string.mobile_data_poor_connection)); + assertThat(dds).isNotEqualTo(nonDds); + } + + @Test + public void getMobileNetworkSummary_flagOff() { + InternetDialogController spyController = spy(mInternetDialogController); + doReturn(true).when(spyController).isMobileDataEnabled(); + doReturn(true).when(spyController).activeNetworkIsCellular(); + String dds = spyController.getMobileNetworkSummary(SUB_ID); + + assertThat(dds).contains(mContext.getString(R.string.mobile_data_connection_active)); + } + + @Test + public void launchMobileNetworkSettings_validSubId() { + when(mFlags.isEnabled(any(UnreleasedFlag.class))).thenReturn(true); + InternetDialogController spyController = spy(mInternetDialogController); + doReturn(SUB_ID2).when(spyController).getActiveAutoSwitchNonDdsSubId(); + spyController.launchMobileNetworkSettings(mDialogLaunchView); + + verify(mActivityStarter).postStartActivityDismissingKeyguard(any(Intent.class), anyInt(), + any()); + } + + @Test + public void launchMobileNetworkSettings_invalidSubId() { + when(mFlags.isEnabled(any(UnreleasedFlag.class))).thenReturn(true); + InternetDialogController spyController = spy(mInternetDialogController); + doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID) + .when(spyController).getActiveAutoSwitchNonDdsSubId(); + spyController.launchMobileNetworkSettings(mDialogLaunchView); + + verify(mActivityStarter, never()) + .postStartActivityDismissingKeyguard(any(Intent.class), anyInt()); + } + + @Test + public void setAutoDataSwitchMobileDataPolicy() { + when(mFlags.isEnabled(any(UnreleasedFlag.class))).thenReturn(true); + mInternetDialogController.setAutoDataSwitchMobileDataPolicy(SUB_ID, true); + + verify(mTelephonyManager).setMobileDataPolicyEnabled(eq( + TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH), eq(true)); + } + + @Test public void getSignalStrengthDrawableWithLevel_carrierNetworkIsNotActive_useMobileDataLevel() { // Fake mobile data level as SIGNAL_STRENGTH_POOR(1) when(mSignalStrength.getLevel()).thenReturn(SIGNAL_STRENGTH_POOR); @@ -720,9 +875,9 @@ public class InternetDialogControllerTest extends SysuiTestCase { when(mInternetDialogController.getCarrierNetworkLevel()).thenReturn(WIFI_LEVEL_MAX); InternetDialogController spyController = spy(mInternetDialogController); - spyController.getSignalStrengthDrawableWithLevel(false /* isCarrierNetworkActive */); + spyController.getSignalStrengthDrawableWithLevel(false /* isCarrierNetworkActive */, 0); - verify(spyController).getSignalStrengthIcon(any(), eq(SIGNAL_STRENGTH_POOR), + verify(spyController).getSignalStrengthIcon(eq(0), any(), eq(SIGNAL_STRENGTH_POOR), eq(NUM_SIGNAL_STRENGTH_BINS), anyInt(), anyBoolean()); } @@ -734,9 +889,9 @@ public class InternetDialogControllerTest extends SysuiTestCase { when(mInternetDialogController.getCarrierNetworkLevel()).thenReturn(WIFI_LEVEL_MAX); InternetDialogController spyController = spy(mInternetDialogController); - spyController.getSignalStrengthDrawableWithLevel(true /* isCarrierNetworkActive */); + spyController.getSignalStrengthDrawableWithLevel(true /* isCarrierNetworkActive */, 0); - verify(spyController).getSignalStrengthIcon(any(), eq(WIFI_LEVEL_MAX), + verify(spyController).getSignalStrengthIcon(eq(0), any(), eq(WIFI_LEVEL_MAX), eq(WIFI_LEVEL_MAX + 1), anyInt(), anyBoolean()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java index f92247580df0..4084cf44446d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java @@ -8,12 +8,15 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.AlertDialog; +import android.content.DialogInterface; import android.os.Handler; import android.telephony.TelephonyManager; import android.testing.AndroidTestingRunner; @@ -31,6 +34,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -72,6 +76,8 @@ public class InternetDialogTest extends SysuiTestCase { private InternetDialogController mInternetDialogController; @Mock private KeyguardStateController mKeyguard; + @Mock + private DialogLaunchAnimator mDialogLaunchAnimator; private FakeExecutor mBgExecutor = new FakeExecutor(new FakeSystemClock()); private InternetDialog mInternetDialog; @@ -100,8 +106,9 @@ public class InternetDialogTest extends SysuiTestCase { when(mInternetWifiEntry.hasInternetAccess()).thenReturn(true); when(mWifiEntries.size()).thenReturn(1); - when(mInternetDialogController.getMobileNetworkTitle()).thenReturn(MOBILE_NETWORK_TITLE); - when(mInternetDialogController.getMobileNetworkSummary()) + when(mInternetDialogController.getMobileNetworkTitle(anyInt())) + .thenReturn(MOBILE_NETWORK_TITLE); + when(mInternetDialogController.getMobileNetworkSummary(anyInt())) .thenReturn(MOBILE_NETWORK_SUMMARY); when(mInternetDialogController.isWifiEnabled()).thenReturn(true); @@ -115,7 +122,8 @@ public class InternetDialogTest extends SysuiTestCase { private void createInternetDialog() { mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class), - mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler, + mInternetDialogController, true, true, true, mock(UiEventLogger.class), + mDialogLaunchAnimator, mHandler, mBgExecutor, mKeyguard); mInternetDialog.mAdapter = mInternetAdapter; mInternetDialog.mConnectedWifiEntry = mInternetWifiEntry; @@ -307,12 +315,18 @@ public class InternetDialogTest extends SysuiTestCase { @Test public void updateDialog_wifiOnAndHasInternetWifi_showConnectedWifi() { + mInternetDialog.dismissDialog(); + doReturn(true).when(mInternetDialogController).hasActiveSubId(); + createInternetDialog(); // The preconditions WiFi ON and Internet WiFi are already in setUp() doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); - mInternetDialog.updateDialog(false); + mInternetDialog.updateDialog(true); assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); + LinearLayout secondaryLayout = mDialogView.requireViewById( + R.id.secondary_mobile_network_layout); + assertThat(secondaryLayout.getVisibility()).isEqualTo(View.GONE); } @Test @@ -460,6 +474,44 @@ public class InternetDialogTest extends SysuiTestCase { } @Test + public void updateDialog_showSecondaryDataSub() { + mInternetDialog.dismissDialog(); + doReturn(1).when(mInternetDialogController).getActiveAutoSwitchNonDdsSubId(); + doReturn(true).when(mInternetDialogController).hasActiveSubId(); + doReturn(false).when(mInternetDialogController).isAirplaneModeEnabled(); + createInternetDialog(); + + clearInvocations(mInternetDialogController); + mInternetDialog.updateDialog(true); + + LinearLayout primaryLayout = mDialogView.requireViewById( + R.id.mobile_network_layout); + LinearLayout secondaryLayout = mDialogView.requireViewById( + R.id.secondary_mobile_network_layout); + + verify(mInternetDialogController).getMobileNetworkSummary(1); + assertThat(primaryLayout.getBackground()).isNotEqualTo(secondaryLayout.getBackground()); + + // Tap the primary sub info + primaryLayout.performClick(); + ArgumentCaptor<AlertDialog> dialogArgumentCaptor = + ArgumentCaptor.forClass(AlertDialog.class); + verify(mDialogLaunchAnimator).showFromDialog(dialogArgumentCaptor.capture(), + eq(mInternetDialog), eq(null), eq(false)); + AlertDialog dialog = dialogArgumentCaptor.getValue(); + dialog.show(); + dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick(); + TestableLooper.get(this).processAllMessages(); + verify(mInternetDialogController).setAutoDataSwitchMobileDataPolicy(1, false); + + // Tap the secondary sub info + secondaryLayout.performClick(); + verify(mInternetDialogController).launchMobileNetworkSettings(any(View.class)); + + dialog.dismiss(); + } + + @Test public void updateDialog_wifiOn_hideWifiScanNotify() { // The preconditions WiFi ON and WiFi entries are already in setUp() |