diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index f5fb26cae30..bb217a0d20a 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -433,7 +433,8 @@ public class SettingsActivity extends SettingsBaseActivity final UserManager um = getSystemService(UserManager.class); final UserInfo userInfo = um.getUserInfo(getUser().getIdentifier()); if (userInfo.isManagedProfile()) { - trampolineIntent.putExtra(EXTRA_USER_HANDLE, getUser()); + trampolineIntent.setClass(this, DeepLinkHomepageActivityInternal.class) + .putExtra(EXTRA_USER_HANDLE, getUser()); startActivityAsUser(trampolineIntent, um.getPrimaryUser().getUserHandle()); } else { startActivity(trampolineIntent); diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java index e0292ef5b9c..e0e9073a220 100644 --- a/src/com/android/settings/SetupWizardUtils.java +++ b/src/com/android/settings/SetupWizardUtils.java @@ -48,6 +48,9 @@ public class SetupWizardUtils { if (WizardManagerHelper.isAnySetupWizard(intent)) { if (ThemeHelper.isSetupWizardDayNightEnabled(context)) { switch (theme) { + // TODO(b/233032365): Create glif v4 theme for this case. + case ThemeHelper.THEME_GLIF_V4_LIGHT: + case ThemeHelper.THEME_GLIF_V4: case ThemeHelper.THEME_GLIF_V3_LIGHT: case ThemeHelper.THEME_GLIF_V3: return R.style.GlifV3Theme_DayNight; @@ -60,8 +63,11 @@ public class SetupWizardUtils { } } else { switch (theme) { + // TODO(b/233032365): Create glif v4 theme for this case. + case ThemeHelper.THEME_GLIF_V4_LIGHT: case ThemeHelper.THEME_GLIF_V3_LIGHT: return R.style.GlifV3Theme_Light; + case ThemeHelper.THEME_GLIF_V4: case ThemeHelper.THEME_GLIF_V3: return R.style.GlifV3Theme; case ThemeHelper.THEME_GLIF_V2_LIGHT: @@ -76,6 +82,9 @@ public class SetupWizardUtils { } } else { switch (theme) { + // TODO(b/233032365): Create glif v4 theme for this case. + case ThemeHelper.THEME_GLIF_V4_LIGHT: + case ThemeHelper.THEME_GLIF_V4: case ThemeHelper.THEME_GLIF_V3_LIGHT: case ThemeHelper.THEME_GLIF_V3: return R.style.GlifV3Theme; diff --git a/src/com/android/settings/applications/AppLocaleUtil.java b/src/com/android/settings/applications/AppLocaleUtil.java index 31357968a07..8c3671ed943 100644 --- a/src/com/android/settings/applications/AppLocaleUtil.java +++ b/src/com/android/settings/applications/AppLocaleUtil.java @@ -49,17 +49,17 @@ public class AppLocaleUtil { boolean isDisallowedPackage = isDisallowedPackage(context, packageName); boolean hasLauncherEntry = hasLauncherEntry(packageName, infos); boolean isSignedWithPlatformKey = isSignedWithPlatformKey(context, packageName); - boolean isAppLocaleSupported = isAppLocaleSupported(context, packageName); + boolean canDisplay = !isDisallowedPackage + && !isSignedWithPlatformKey + && hasLauncherEntry + && isAppLocaleSupported(context, packageName); + Log.i(TAG, "Can display preference - [" + packageName + "] :" + " isDisallowedPackage : " + isDisallowedPackage + " / isSignedWithPlatformKey : " + isSignedWithPlatformKey + " / hasLauncherEntry : " + hasLauncherEntry - + " / isAppLocaleSupported : " + isAppLocaleSupported); - - return !isDisallowedPackage - && !isSignedWithPlatformKey - && hasLauncherEntry - && isAppLocaleSupported; + + " / canDisplay : " + canDisplay); + return canDisplay; } private static boolean isDisallowedPackage(Context context, String packageName) { diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index 9796454bbfc..ead9840af7a 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -173,8 +173,6 @@ public class ManageApplications extends InstrumentedFragment private static final String EXTRA_HAS_BRIDGE = "hasBridge"; private static final String EXTRA_FILTER_TYPE = "filterType"; @VisibleForTesting - static final String EXTRA_SEARCH_QUERY = "search_query"; - @VisibleForTesting static final String EXTRA_EXPAND_SEARCH_VIEW = "expand_search_view"; // attributes used as keys when passing values to AppInfoDashboardFragment activity @@ -255,8 +253,6 @@ public class ManageApplications extends InstrumentedFragment // Whether or not search view is expanded. @VisibleForTesting boolean mExpandSearch; - @VisibleForTesting - CharSequence mPreQuery; private View mRootView; private Spinner mFilterSpinner; @@ -362,7 +358,6 @@ public class ManageApplications extends InstrumentedFragment mFilterType = savedInstanceState.getInt(EXTRA_FILTER_TYPE, AppFilterRegistry.FILTER_APPS_ALL); mExpandSearch = savedInstanceState.getBoolean(EXTRA_EXPAND_SEARCH_VIEW); - mPreQuery = savedInstanceState.getCharSequence(EXTRA_SEARCH_QUERY); } mInvalidSizeStr = activity.getText(R.string.invalid_size_value); @@ -549,7 +544,6 @@ public class ManageApplications extends InstrumentedFragment outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem); if (mSearchView != null) { outState.putBoolean(EXTRA_EXPAND_SEARCH_VIEW, !mSearchView.isIconified()); - outState.putCharSequence(EXTRA_SEARCH_QUERY, mSearchView.getQuery()); } if (mApplications != null) { outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries); @@ -689,9 +683,6 @@ public class ManageApplications extends InstrumentedFragment if (mExpandSearch) { searchMenuItem.expandActionView(); } - if (!TextUtils.isEmpty(mPreQuery)) { - mSearchView.setQuery(mPreQuery, true); - } } updateOptionsMenu(); diff --git a/src/com/android/settings/core/InstrumentedPreferenceFragment.java b/src/com/android/settings/core/InstrumentedPreferenceFragment.java index 48e5176c891..bff405b8e6d 100644 --- a/src/com/android/settings/core/InstrumentedPreferenceFragment.java +++ b/src/com/android/settings/core/InstrumentedPreferenceFragment.java @@ -27,6 +27,7 @@ import android.util.Log; import androidx.annotation.XmlRes; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.jank.InteractionJankMonitor; @@ -34,6 +35,7 @@ import com.android.settings.overlay.FeatureFactory; import com.android.settings.survey.SurveyMixin; import com.android.settingslib.core.instrumentation.Instrumentable; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.android.settingslib.core.instrumentation.SettingsJankMonitor; import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin; import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment; @@ -45,7 +47,6 @@ public abstract class InstrumentedPreferenceFragment extends ObservablePreferenc private static final String TAG = "InstrumentedPrefFrag"; - protected MetricsFeatureProvider mMetricsFeatureProvider; // metrics placeholder value. Only use this for development. @@ -65,6 +66,19 @@ public abstract class InstrumentedPreferenceFragment extends ObservablePreferenc super.onAttach(context); } + @Override + public void onStart() { + super.onStart(); + // Override the OnPreferenceTreeClickListener in super.onStart() to inject jank detection. + getPreferenceManager().setOnPreferenceTreeClickListener((preference) -> { + if (preference instanceof SwitchPreference) { + SettingsJankMonitor.detectSwitchPreferenceClickJank( + getListView(), (SwitchPreference) preference); + } + return onPreferenceTreeClick(preference); + }); + } + @Override public void onResume() { mVisibilityLoggerMixin.setSourceMetricsCategory(getActivity()); diff --git a/src/com/android/settings/core/TogglePreferenceController.java b/src/com/android/settings/core/TogglePreferenceController.java index fa83aeacdf1..f14e0b23b87 100644 --- a/src/com/android/settings/core/TogglePreferenceController.java +++ b/src/com/android/settings/core/TogglePreferenceController.java @@ -16,12 +16,15 @@ package com.android.settings.core; import android.content.Context; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import androidx.preference.TwoStatePreference; import com.android.settings.overlay.FeatureFactory; import com.android.settings.slices.SliceData; import com.android.settings.widget.TwoStateButtonPreference; import com.android.settingslib.PrimarySwitchPreference; +import com.android.settingslib.core.instrumentation.SettingsJankMonitor; +import com.android.settingslib.widget.MainSwitchPreference; /** * Abstract class that consolidates logic for updating toggle controllers. @@ -50,6 +53,16 @@ public abstract class TogglePreferenceController extends BasePreferenceControlle */ public abstract boolean setChecked(boolean isChecked); + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + Preference preference = screen.findPreference(getPreferenceKey()); + if (preference instanceof MainSwitchPreference) { + ((MainSwitchPreference) preference).addOnSwitchChangeListener((switchView, isChecked) -> + SettingsJankMonitor.detectToggleJank(getPreferenceKey(), switchView)); + } + } + @Override public void updateState(Preference preference) { if (preference instanceof TwoStatePreference) { diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java index 08692dd56c7..09000bf785d 100644 --- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java +++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java @@ -180,15 +180,17 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { } pref.setOnPreferenceClickListener(preference -> { TopLevelHighlightMixin highlightMixin = null; + boolean isDuplicateClick = false; if (fragment instanceof TopLevelSettings && ActivityEmbeddingUtils.isEmbeddingActivityEnabled(mContext)) { // Highlight the preference whenever it's clicked final TopLevelSettings topLevelSettings = (TopLevelSettings) fragment; topLevelSettings.setHighlightPreferenceKey(key); highlightMixin = topLevelSettings.getHighlightMixin(); + isDuplicateClick = topLevelSettings.isDuplicateClick(preference); } launchIntentOrSelectProfile(activity, tile, intent, sourceMetricsCategory, - highlightMixin); + highlightMixin, isDuplicateClick); return true; }); } @@ -221,7 +223,7 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { SettingsEnums.DASHBOARD_SUMMARY) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); launchIntentOrSelectProfile(activity, tile, intent, SettingsEnums.DASHBOARD_SUMMARY, - /* highlightMixin= */ null); + /* highlightMixin= */ null, /* isDuplicateClick= */ false); } private DynamicDataObserver createDynamicDataObserver(String method, Uri uri, Preference pref) { @@ -438,31 +440,45 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { } private void launchIntentOrSelectProfile(FragmentActivity activity, Tile tile, Intent intent, - int sourceMetricCategory, TopLevelHighlightMixin highlightMixin) { + int sourceMetricCategory, TopLevelHighlightMixin highlightMixin, + boolean isDuplicateClick) { if (!isIntentResolvable(intent)) { Log.w(TAG, "Cannot resolve intent, skipping. " + intent); return; } ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile); - mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); if (tile.userHandle == null || tile.isPrimaryProfileOnly()) { - activity.startActivity(intent); + if (!isDuplicateClick) { + mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); + activity.startActivity(intent); + } } else if (tile.userHandle.size() == 1) { - activity.startActivityAsUser(intent, tile.userHandle.get(0)); + if (!isDuplicateClick) { + mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); + activity.startActivityAsUser(intent, tile.userHandle.get(0)); + } } else { final UserHandle userHandle = intent.getParcelableExtra(EXTRA_USER); if (userHandle != null && tile.userHandle.contains(userHandle)) { - activity.startActivityAsUser(intent, userHandle); + if (!isDuplicateClick) { + mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); + activity.startActivityAsUser(intent, userHandle); + } return; } final List resolvableUsers = getResolvableUsers(intent, tile); if (resolvableUsers.size() == 1) { - activity.startActivityAsUser(intent, resolvableUsers.get(0)); + if (!isDuplicateClick) { + mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); + activity.startActivityAsUser(intent, resolvableUsers.get(0)); + } return; } + // Show the profile select dialog regardless of the duplicate click. + mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); ProfileSelectDialog.show(activity.getSupportFragmentManager(), tile, sourceMetricCategory, /* onShowListener= */ highlightMixin, /* onDismissListener= */ highlightMixin, diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index c7bd3b5712e..3c72dd1c3b5 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -27,9 +27,11 @@ import android.app.ActivityManager; import android.app.settings.SettingsEnums; import android.content.ComponentName; import android.content.Intent; +import android.content.pm.UserInfo; import android.content.res.Configuration; import android.os.Bundle; import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.ArraySet; import android.util.FeatureFlagUtils; @@ -153,11 +155,6 @@ public class SettingsHomepageActivity extends FragmentActivity implements return mMainFragment; } - /** Whether the activity is showing in two-pane */ - public boolean isTwoPane() { - return mIsTwoPane; - } - @Override public CategoryMixin getCategoryMixin() { return mCategoryMixin; @@ -166,10 +163,26 @@ public class SettingsHomepageActivity extends FragmentActivity implements @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + mIsEmbeddingActivityEnabled = ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this); + if (mIsEmbeddingActivityEnabled) { + final UserManager um = getSystemService(UserManager.class); + final UserInfo userInfo = um.getUserInfo(getUser().getIdentifier()); + if (userInfo.isManagedProfile()) { + final Intent intent = new Intent(getIntent()) + .setClass(this, DeepLinkHomepageActivityInternal.class) + .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) + .putExtra(EXTRA_USER_HANDLE, getUser()); + intent.removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivityAsUser(intent, um.getPrimaryUser().getUserHandle()); + finish(); + return; + } + } + setupEdgeToEdge(); setContentView(R.layout.settings_homepage_container); - mIsEmbeddingActivityEnabled = ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this); mSplitController = SplitController.getInstance(); mIsTwoPane = mSplitController.isActivityEmbedded(this); @@ -423,7 +436,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements // To prevent launchDeepLinkIntentToRight again for configuration change. intent.setAction(null); - targetIntent.setFlags(targetIntent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); + targetIntent.removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK); targetIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); // Sender of intent may want to send intent extra data to the destination of targetIntent. diff --git a/src/com/android/settings/homepage/TopLevelHighlightMixin.java b/src/com/android/settings/homepage/TopLevelHighlightMixin.java index c473e87eeca..4718443f8a4 100644 --- a/src/com/android/settings/homepage/TopLevelHighlightMixin.java +++ b/src/com/android/settings/homepage/TopLevelHighlightMixin.java @@ -140,6 +140,10 @@ public class TopLevelHighlightMixin implements Parcelable, DialogInterface.OnSho } } + String getHighlightPreferenceKey() { + return mCurrentKey; + } + void highlightPreferenceIfNeeded() { if (mTopLevelAdapter != null) { mTopLevelAdapter.requestHighlight(); diff --git a/src/com/android/settings/homepage/TopLevelSettings.java b/src/com/android/settings/homepage/TopLevelSettings.java index 8623509ce9b..d221d253b14 100644 --- a/src/com/android/settings/homepage/TopLevelSettings.java +++ b/src/com/android/settings/homepage/TopLevelSettings.java @@ -16,12 +16,17 @@ package com.android.settings.homepage; +import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI; + import static com.android.settings.search.actionbar.SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR; import static com.android.settingslib.search.SearchIndexable.MOBILE; import android.app.ActivityManager; import android.app.settings.SettingsEnums; import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -38,6 +43,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.window.embedding.SplitController; import com.android.settings.R; +import com.android.settings.SettingsActivity; import com.android.settings.Utils; import com.android.settings.activityembedding.ActivityEmbeddingRulesController; import com.android.settings.activityembedding.ActivityEmbeddingUtils; @@ -51,12 +57,15 @@ import com.android.settingslib.core.instrumentation.Instrumentable; import com.android.settingslib.drawer.Tile; import com.android.settingslib.search.SearchIndexable; +import java.net.URISyntaxException; + @SearchIndexable(forTarget = MOBILE) public class TopLevelSettings extends DashboardFragment implements SplitLayoutListener, PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { private static final String TAG = "TopLevelSettings"; private static final String SAVED_HIGHLIGHT_MIXIN = "highlight_mixin"; + private static final String SAVED_FIRST_PREFERENCE_CLICK = "first_pref_click"; private static final String PREF_KEY_SUPPORT = "top_level_support"; private boolean mIsEmbeddingActivityEnabled; @@ -64,6 +73,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi private int mPaddingHorizontal; private boolean mScrollNeeded = true; private boolean mFirstStarted = true; + private boolean mFirstDuplicateClickCheck = true; public TopLevelSettings() { final Bundle args = new Bundle(); @@ -107,6 +117,10 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi @Override public boolean onPreferenceTreeClick(Preference preference) { + if (isDuplicateClick(preference)) { + return true; + } + // Register SplitPairRule for SubSettings. ActivityEmbeddingRulesController.registerSubSettingsPairRule(getContext(), true /* clearTop */); @@ -140,6 +154,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi boolean activityEmbedded = SplitController.getInstance().isActivityEmbedded(getActivity()); if (icicle != null) { + mFirstDuplicateClickCheck = icicle.getBoolean(SAVED_FIRST_PREFERENCE_CLICK); mHighlightMixin = icicle.getParcelable(SAVED_HIGHLIGHT_MIXIN); mScrollNeeded = !mHighlightMixin.isActivityEmbedded() && activityEmbedded; mHighlightMixin.setActivityEmbedded(activityEmbedded); @@ -173,6 +188,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); + outState.putBoolean(SAVED_FIRST_PREFERENCE_CLICK, mFirstDuplicateClickCheck); if (mHighlightMixin != null) { outState.putParcelable(SAVED_HIGHLIGHT_MIXIN, mHighlightMixin); } @@ -271,6 +287,41 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi } } + /** Returns whether clicking the specified preference is considered as a duplicate click. */ + public boolean isDuplicateClick(Preference pref) { + boolean firstCheck = mFirstDuplicateClickCheck; + mFirstDuplicateClickCheck = false; + /* + * Return false when + * 1. The device doesn't support activity embedding + * 2. The target preference is not highlighted + * 3. The current activity is not embedded + */ + if (mHighlightMixin == null + || !TextUtils.equals(pref.getKey(), mHighlightMixin.getHighlightPreferenceKey()) + || !SplitController.getInstance().isActivityEmbedded(getActivity())) { + return false; + } + + /* + * Return true when + * 1. This method has been called before + * 2. The preference doesn't have a target fragment, ex. Wallpaper and injections + */ + if (!firstCheck || TextUtils.isEmpty(pref.getFragment())) { + return true; + } + + /* + * Returns true when + * 1. The right pane fragment is not started by a deep link. + * 2. The target fragment equals the right pane fragment + */ + String intentUri = getIntent().getStringExtra(EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI); + return TextUtils.isEmpty(intentUri) + || TextUtils.equals(pref.getFragment(), getIntentTargetFragment(intentUri)); + } + /** Show/hide the highlight on the menu entry for the search page presence */ public void setMenuHighlightShowed(boolean show) { if (mHighlightMixin != null) { @@ -310,6 +361,27 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi } } + private String getIntentTargetFragment(String intentUri) { + Intent targetIntent; + try { + targetIntent = Intent.parseUri(intentUri, Intent.URI_INTENT_SCHEME); + } catch (URISyntaxException e) { + return null; + } + + String fragment = targetIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT); + if (!TextUtils.isEmpty(fragment)) { + return fragment; + } + + ActivityInfo info = targetIntent.resolveActivityInfo(getPackageManager(), + PackageManager.GET_META_DATA); + if (info == null || info.metaData == null) { + return null; + } + return info.metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS); + } + private void iteratePreferences(PreferenceJob job) { if (job == null || getPreferenceManager() == null) { return; diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java index 7ba16e31f45..fb384d4713e 100644 --- a/src/com/android/settings/network/SubscriptionsPreferenceController.java +++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java @@ -30,7 +30,6 @@ import android.content.IntentFilter; import android.graphics.drawable.Drawable; import android.net.wifi.WifiManager; import android.os.UserManager; -import android.provider.Settings; import android.telephony.AccessNetworkConstants; import android.telephony.NetworkRegistrationInfo; import android.telephony.ServiceState; @@ -65,6 +64,7 @@ import com.android.settingslib.mobile.MobileMappings; import com.android.settingslib.mobile.MobileMappings.Config; import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; +import com.android.wifitrackerlib.WifiEntry; import java.util.Collections; import java.util.List; @@ -282,16 +282,18 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl return Html.fromHtml(result, Html.FROM_HTML_MODE_LEGACY); } - private Drawable getIcon(int subId) { + @VisibleForTesting + Drawable getIcon(int subId) { final TelephonyManager tmForSubId = mTelephonyManager.createForSubscriptionId(subId); final SignalStrength strength = tmForSubId.getSignalStrength(); int level = (strength == null) ? 0 : strength.getLevel(); int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS; boolean isCarrierNetworkActive = isCarrierNetworkActive(); - if (shouldInflateSignalStrength(subId) || isCarrierNetworkActive) { - level = isCarrierNetworkActive - ? SignalStrength.NUM_SIGNAL_STRENGTH_BINS - : (level + 1); + if (isCarrierNetworkActive) { + level = getCarrierNetworkLevel(); + numLevels = WifiEntry.WIFI_LEVEL_MAX + 1; + } else if (shouldInflateSignalStrength(subId)) { + level += 1; numLevels += 1; } @@ -488,6 +490,11 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl && mWifiPickerTrackerHelper.isCarrierNetworkActive(); } + private int getCarrierNetworkLevel() { + if (mWifiPickerTrackerHelper == null) return WifiEntry.WIFI_LEVEL_MIN; + return mWifiPickerTrackerHelper.getCarrierNetworkLevel(); + } + /** * To inject necessary data from each static api. */ diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java index d348b24e58f..f5f18b4b9ee 100644 --- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java +++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java @@ -460,13 +460,10 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc switchDialogMsg.append( getString(R.string.sim_action_switch_sub_dialog_mep_text, displayName)); if (isRtlMode) { - /* There are two lines of message in the dialog, and the RTL symbols must be added - * before and after each sentence, so use the line break symbol to find the position. + /* The RTL symbols must be added before and after each sentence. * (Each message are all with two line break symbols) */ switchDialogMsg.insert(0, RTL_MARK) - .insert(switchDialogMsg.indexOf(LINE_BREAK) - LINE_BREAK_OFFSET_ONE, RTL_MARK) - .insert(switchDialogMsg.indexOf(LINE_BREAK) + LINE_BREAK_OFFSET_TWO, RTL_MARK) .insert(switchDialogMsg.length(), RTL_MARK); } ConfirmDialogFragment.show( diff --git a/src/com/android/settings/widget/SettingsMainSwitchPreference.java b/src/com/android/settings/widget/SettingsMainSwitchPreference.java index 92649113d82..ce91c9e693c 100644 --- a/src/com/android/settings/widget/SettingsMainSwitchPreference.java +++ b/src/com/android/settings/widget/SettingsMainSwitchPreference.java @@ -32,6 +32,7 @@ import androidx.preference.TwoStatePreference; import com.android.settings.R; import com.android.settings.widget.SettingsMainSwitchBar.OnBeforeCheckedChangeListener; import com.android.settingslib.RestrictedPreferenceHelper; +import com.android.settingslib.core.instrumentation.SettingsJankMonitor; import com.android.settingslib.widget.OnMainSwitchChangeListener; import com.google.android.setupdesign.util.LayoutStyler; @@ -153,6 +154,7 @@ public class SettingsMainSwitchPreference extends TwoStatePreference implements @Override public void onSwitchChanged(Switch switchView, boolean isChecked) { super.setChecked(isChecked); + SettingsJankMonitor.detectToggleJank(getKey(), switchView); } /** diff --git a/src/com/android/settings/wifi/WifiPickerTrackerHelper.java b/src/com/android/settings/wifi/WifiPickerTrackerHelper.java index d4a7da8f5fd..1be71c8cc65 100644 --- a/src/com/android/settings/wifi/WifiPickerTrackerHelper.java +++ b/src/com/android/settings/wifi/WifiPickerTrackerHelper.java @@ -155,6 +155,17 @@ public class WifiPickerTrackerHelper implements LifecycleObserver { return mergedCarrierEntry.getSsid(); } + /** Return the carrier network level */ + public int getCarrierNetworkLevel() { + final MergedCarrierEntry mergedCarrierEntry = mWifiPickerTracker.getMergedCarrierEntry(); + if (mergedCarrierEntry == null) return WifiEntry.WIFI_LEVEL_MIN; + + int level = mergedCarrierEntry.getLevel(); + // To avoid icons not found with WIFI_LEVEL_UNREACHABLE(-1), use WIFI_LEVEL_MIN(0) instead. + if (level < WifiEntry.WIFI_LEVEL_MIN) level = WifiEntry.WIFI_LEVEL_MIN; + return level; + } + @VisibleForTesting void setWifiPickerTracker(@NonNull WifiPickerTracker wifiPickerTracker) { mWifiPickerTracker = wifiPickerTracker; diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java index ec4f8f2e8b6..da17f1143bb 100644 --- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java +++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java @@ -188,24 +188,6 @@ public class ManageApplicationsTest { verify(searchMenu).expandActionView(); } - @Test - public void onCreateOptionsMenu_hasPreQuery_shouldSetQuery() { - final SearchView searchView = mock(SearchView.class); - final MenuItem searchMenu = mock(MenuItem.class); - final MenuItem helpMenu = mock(MenuItem.class); - when(searchMenu.getActionView()).thenReturn(searchView); - when(mMenu.findItem(R.id.search_app_list_menu)).thenReturn(searchMenu); - when(mMenu.add(anyInt() /* groupId */, anyInt() /* itemId */, anyInt() /* order */, - anyInt() /* titleRes */)).thenReturn(helpMenu); - doReturn("Test").when(mFragment).getText(anyInt() /* resId */); - doNothing().when(mFragment).updateOptionsMenu(); - - mFragment.mPreQuery = "test"; - mFragment.onCreateOptionsMenu(mMenu, mock(MenuInflater.class)); - - verify(searchView).setQuery("test", true); - } - @Test public void onQueryTextChange_shouldFilterSearchInApplicationsAdapter() { final ManageApplications.ApplicationsAdapter adapter = @@ -536,38 +518,6 @@ public class ManageApplicationsTest { assertThat(bundle.getBoolean(ManageApplications.EXTRA_EXPAND_SEARCH_VIEW)).isFalse(); } - @Test - public void onSaveInstanceState_noSearchView_shouldNotSaveQuery() { - final Bundle bundle = new Bundle(); - ReflectionHelpers.setField(mFragment, "mResetAppsHelper", mock(ResetAppsHelper.class)); - ReflectionHelpers.setField(mFragment, "mFilter", mock(AppFilterItem.class)); - ReflectionHelpers.setField(mFragment, "mApplications", - mock(ManageApplications.ApplicationsAdapter.class)); - - mFragment.onSaveInstanceState(bundle); - - assertThat(bundle.containsKey(ManageApplications.EXTRA_SEARCH_QUERY)).isFalse(); - } - - @Test - public void onSaveInstanceState_searchViewSet_shouldSaveQuery() { - final SearchView searchView = mock(SearchView.class); - final Bundle bundle = new Bundle(); - ReflectionHelpers.setField(mFragment, "mResetAppsHelper", mock(ResetAppsHelper.class)); - ReflectionHelpers.setField(mFragment, "mFilter", mock(AppFilterItem.class)); - ReflectionHelpers.setField(mFragment, "mApplications", - mock(ManageApplications.ApplicationsAdapter.class)); - ReflectionHelpers.setField(mFragment, "mSearchView", searchView); - when(searchView.isIconified()).thenReturn(true); - when(searchView.getQuery()).thenReturn("test"); - - mFragment.onSaveInstanceState(bundle); - - assertThat(bundle.containsKey(ManageApplications.EXTRA_SEARCH_QUERY)).isTrue(); - assertThat(bundle.getCharSequence(ManageApplications.EXTRA_SEARCH_QUERY)) - .isEqualTo("test"); - } - @Test public void createHeader_batteryListType_hasCorrectItems() { ReflectionHelpers.setField(mFragment, "mListType", ManageApplications.LIST_TYPE_HIGH_POWER); diff --git a/tests/robotests/src/com/android/settings/notification/BubbleNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubbleNotificationPreferenceControllerTest.java index 8d643ad4613..3cb3abfc4a0 100644 --- a/tests/robotests/src/com/android/settings/notification/BubbleNotificationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/BubbleNotificationPreferenceControllerTest.java @@ -31,9 +31,11 @@ import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.content.Context; import android.provider.Settings; +import android.widget.Switch; import androidx.preference.PreferenceScreen; +import com.android.settingslib.testutils.shadow.ShadowInteractionJankMonitor; import com.android.settingslib.widget.MainSwitchPreference; import org.junit.Before; @@ -44,16 +46,21 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import org.robolectric.shadow.api.Shadow; import org.robolectric.shadows.ShadowActivityManager; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowInteractionJankMonitor.class}) public class BubbleNotificationPreferenceControllerTest { private Context mContext; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceScreen mScreen; + @Mock + private Switch mSwitch; + private BubbleNotificationPreferenceController mController; private MainSwitchPreference mPreference; @@ -102,7 +109,7 @@ public class BubbleNotificationPreferenceControllerTest { public void onSwitchChanged_true_settingIsOff_flagShouldOn() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, OFF); - mController.onSwitchChanged(null, true); + mController.onSwitchChanged(mSwitch, true); assertThat(Settings.Global.getInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, OFF)).isEqualTo(ON); @@ -112,7 +119,7 @@ public class BubbleNotificationPreferenceControllerTest { public void onSwitchChanged_false_settingIsOn_flagShouldOff() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, ON); - mController.onSwitchChanged(null, false); + mController.onSwitchChanged(mSwitch, false); assertThat(Settings.Global.getInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, ON)).isEqualTo(OFF); diff --git a/tests/robotests/src/com/android/settings/notification/app/BlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/BlockPreferenceControllerTest.java index 0c2eebe8070..9e9e655e3af 100644 --- a/tests/robotests/src/com/android/settings/notification/app/BlockPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/BlockPreferenceControllerTest.java @@ -17,7 +17,6 @@ package com.android.settings.notification.app; import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID; -import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_NONE; @@ -49,6 +48,7 @@ import androidx.preference.PreferenceViewHolder; import com.android.settings.notification.NotificationBackend; import com.android.settings.widget.SettingsMainSwitchPreference; +import com.android.settingslib.testutils.shadow.ShadowInteractionJankMonitor; import org.junit.Before; import org.junit.Test; @@ -57,11 +57,13 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; import java.util.ArrayList; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowInteractionJankMonitor.class}) public class BlockPreferenceControllerTest { private Context mContext; diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInteractionJankMonitor.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInteractionJankMonitor.java index 3ec07c515ce..9eb08d79246 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInteractionJankMonitor.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInteractionJankMonitor.java @@ -23,6 +23,10 @@ import com.android.internal.jank.InteractionJankMonitor; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +/** + * @deprecated use {@link com.android.settingslib.testutils.shadow.ShadowInteractionJankMonitor} + */ +@Deprecated @Implements(InteractionJankMonitor.class) public class ShadowInteractionJankMonitor { diff --git a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java index 8ebd2b5d390..ebcb102e7ab 100644 --- a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java @@ -20,12 +20,14 @@ import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GOOD; import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GREAT; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; +import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq;; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -55,7 +57,6 @@ import android.text.Html; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleRegistry; -import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; @@ -78,12 +79,12 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; @RunWith(AndroidJUnit4.class) public class SubscriptionsPreferenceControllerTest { private static final String KEY = "preference_group"; + private static final int SUB_ID = 1; @Mock private UserManager mUserManager; @@ -105,6 +106,10 @@ public class SubscriptionsPreferenceControllerTest { private WifiPickerTrackerHelper mWifiPickerTrackerHelper; @Mock private WifiManager mWifiManager; + @Mock + private SignalStrength mSignalStrength; + @Mock + private ServiceState mServiceState; private LifecycleRegistry mLifecycleRegistry; private int mOnChildUpdatedCount; @@ -116,6 +121,7 @@ public class SubscriptionsPreferenceControllerTest { private NetworkCapabilities mNetworkCapabilities; private FakeSubscriptionsPreferenceController mController; private static SubsPrefCtrlInjector sInjector; + private NetworkRegistrationInfo mNetworkRegistrationInfo; @Before public void setUp() { @@ -131,6 +137,12 @@ public class SubscriptionsPreferenceControllerTest { when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); + when(mSignalStrength.getLevel()).thenReturn(SIGNAL_STRENGTH_GREAT); + when(mTelephonyManager.getServiceState()).thenReturn(mServiceState); + mNetworkRegistrationInfo = createNetworkRegistrationInfo(false /* dateState */); + when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())) + .thenReturn(mNetworkRegistrationInfo); + when(mTelephonyManager.getSignalStrength()).thenReturn(mSignalStrength); when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork); when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork)) .thenReturn(mNetworkCapabilities); @@ -153,6 +165,7 @@ public class SubscriptionsPreferenceControllerTest { mController = new FakeSubscriptionsPreferenceController(mContext, mLifecycle, mUpdateListener, KEY, 5); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0); + mController.setWifiPickerTrackerHelper(mWifiPickerTrackerHelper); } @After @@ -284,7 +297,6 @@ public class SubscriptionsPreferenceControllerTest { doReturn(networkType) .when(sInjector).getNetworkType(any(), any(), any(), anyInt(), eq(true)); doReturn(true).when(mWifiPickerTrackerHelper).isCarrierNetworkActive(); - mController.setWifiPickerTrackerHelper(mWifiPickerTrackerHelper); mController.onResume(); mController.displayPreference(mPreferenceScreen); @@ -524,12 +536,7 @@ public class SubscriptionsPreferenceControllerTest { mController.displayPreference(mPreferenceScreen); Drawable actualIcon = mPreferenceCategory.getPreference(0).getIcon(); ServiceState ss = mock(ServiceState.class); - NetworkRegistrationInfo regInfo = new NetworkRegistrationInfo.Builder() - .setDomain(NetworkRegistrationInfo.DOMAIN_PS) - .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) - .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME) - .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE) - .build(); + NetworkRegistrationInfo regInfo = createNetworkRegistrationInfo(true /* dataState */); doReturn(ss).when(mTelephonyManagerForSub).getServiceState(); doReturn(regInfo).when(ss).getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, @@ -538,10 +545,43 @@ public class SubscriptionsPreferenceControllerTest { assertThat(icon).isEqualTo(actualIcon); } + @Test + @UiThreadTest + public void getIcon_carrierNetworkIsNotActive_useMobileDataLevel() { + // Fake mobile data active and level is SIGNAL_STRENGTH_GOOD(3) + mNetworkRegistrationInfo = createNetworkRegistrationInfo(true /* dateState */); + when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())) + .thenReturn(mNetworkRegistrationInfo); + when(mSignalStrength.getLevel()).thenReturn(SIGNAL_STRENGTH_GOOD); + // Fake carrier network not active and level is WIFI_LEVEL_MAX(4) + when(mWifiPickerTrackerHelper.isCarrierNetworkActive()).thenReturn(false); + when(mWifiPickerTrackerHelper.getCarrierNetworkLevel()).thenReturn(WIFI_LEVEL_MAX); + + mController.getIcon(SUB_ID); + + verify(sInjector).getIcon(any(), eq(SIGNAL_STRENGTH_GOOD), anyInt(), anyBoolean()); + } + + @Test + @UiThreadTest + public void getIcon_carrierNetworkIsActive_useCarrierNetworkLevel() { + // Fake mobile data not active and level is SIGNAL_STRENGTH_GOOD(3) + mNetworkRegistrationInfo = createNetworkRegistrationInfo(false /* dateState */); + when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())) + .thenReturn(mNetworkRegistrationInfo); + when(mSignalStrength.getLevel()).thenReturn(SIGNAL_STRENGTH_GOOD); + // Fake carrier network active and level is WIFI_LEVEL_MAX(4) + when(mWifiPickerTrackerHelper.isCarrierNetworkActive()).thenReturn(true); + when(mWifiPickerTrackerHelper.getCarrierNetworkLevel()).thenReturn(WIFI_LEVEL_MAX); + + mController.getIcon(SUB_ID); + + verify(sInjector).getIcon(any(), eq(WIFI_LEVEL_MAX), anyInt(), anyBoolean()); + } + @Test public void connectCarrierNetwork_isDataEnabled_helperConnect() { when(mTelephonyManager.isDataEnabled()).thenReturn(true); - mController.setWifiPickerTrackerHelper(mWifiPickerTrackerHelper); mController.connectCarrierNetwork(); @@ -551,7 +591,6 @@ public class SubscriptionsPreferenceControllerTest { @Test public void connectCarrierNetwork_isNotDataEnabled_helperNeverConnect() { when(mTelephonyManager.isDataEnabled()).thenReturn(false); - mController.setWifiPickerTrackerHelper(mWifiPickerTrackerHelper); mController.connectCarrierNetwork(); @@ -564,18 +603,22 @@ public class SubscriptionsPreferenceControllerTest { doReturn(isActiveCellularNetwork).when(sInjector).isActiveCellularNetwork(mContext); doReturn(isDataEnable).when(mTelephonyManagerForSub).isDataEnabled(); ServiceState ss = mock(ServiceState.class); - NetworkRegistrationInfo regInfo = new NetworkRegistrationInfo.Builder() + NetworkRegistrationInfo regInfo = createNetworkRegistrationInfo(dataState); + doReturn(ss).when(mTelephonyManagerForSub).getServiceState(); + doReturn(servicestate).when(ss).getState(); + doReturn(regInfo).when(ss).getNetworkRegistrationInfo( + NetworkRegistrationInfo.DOMAIN_PS, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + } + + private NetworkRegistrationInfo createNetworkRegistrationInfo(boolean dataState) { + return new NetworkRegistrationInfo.Builder() .setDomain(NetworkRegistrationInfo.DOMAIN_PS) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setRegistrationState(dataState ? NetworkRegistrationInfo.REGISTRATION_STATE_HOME : NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING) .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE) .build(); - doReturn(ss).when(mTelephonyManagerForSub).getServiceState(); - doReturn(servicestate).when(ss).getState(); - doReturn(regInfo).when(ss).getNetworkRegistrationInfo( - NetworkRegistrationInfo.DOMAIN_PS, - AccessNetworkConstants.TRANSPORT_TYPE_WWAN); } private List setupMockSubscriptions(int count) { diff --git a/tests/unit/src/com/android/settings/wifi/WifiPickerTrackerHelperTest.java b/tests/unit/src/com/android/settings/wifi/WifiPickerTrackerHelperTest.java index 52724fb3583..1c0cf0429cb 100644 --- a/tests/unit/src/com/android/settings/wifi/WifiPickerTrackerHelperTest.java +++ b/tests/unit/src/com/android/settings/wifi/WifiPickerTrackerHelperTest.java @@ -16,6 +16,10 @@ package com.android.settings.wifi; +import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX; +import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN; +import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -23,7 +27,6 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -48,6 +51,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -58,6 +62,8 @@ public class WifiPickerTrackerHelperTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + Context mContext = ApplicationProvider.getApplicationContext(); @Mock public WifiManager mWifiManager; @Mock @@ -76,11 +82,10 @@ public class WifiPickerTrackerHelperTest { @Before public void setUp() { - final Context context = spy(ApplicationProvider.getApplicationContext()); - when(context.getSystemService(WifiManager.class)).thenReturn(mWifiManager); + when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager); mCarrierConfig = new PersistableBundle(); when(mCarrierConfigCache.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig); - CarrierConfigCache.setTestInstance(context, mCarrierConfigCache); + CarrierConfigCache.setTestInstance(mContext, mCarrierConfigCache); mFeatureFactory = FakeFeatureFactory.setupForTest(); when(mFeatureFactory.wifiTrackerLibProvider @@ -88,7 +93,9 @@ public class WifiPickerTrackerHelperTest { any(), any(), any(), any(), any(), anyLong(), anyLong(), any())) .thenReturn(mWifiPickerTracker); mWifiPickerTrackerHelper = new WifiPickerTrackerHelper(mock(Lifecycle.class), - context, null); + mContext, null); + when(mWifiPickerTracker.getMergedCarrierEntry()).thenReturn(mMergedCarrierEntry); + mWifiPickerTrackerHelper.setWifiPickerTracker(mWifiPickerTracker); } @Test @@ -140,9 +147,6 @@ public class WifiPickerTrackerHelperTest { @Test public void setCarrierNetworkEnabled_shouldSetCorrect() { - mWifiPickerTrackerHelper.setWifiPickerTracker(mWifiPickerTracker); - when(mWifiPickerTracker.getMergedCarrierEntry()).thenReturn(mMergedCarrierEntry); - mWifiPickerTrackerHelper.setCarrierNetworkEnabled(true); verify(mMergedCarrierEntry).setEnabled(true); @@ -154,7 +158,6 @@ public class WifiPickerTrackerHelperTest { @Test public void setCarrierNetworkEnabled_mergedCarrierEntryIsNull_shouldNotSet() { - mWifiPickerTrackerHelper.setWifiPickerTracker(mWifiPickerTracker); when(mWifiPickerTracker.getMergedCarrierEntry()).thenReturn(null); mWifiPickerTrackerHelper.setCarrierNetworkEnabled(true); @@ -168,8 +171,6 @@ public class WifiPickerTrackerHelperTest { @Test public void connectCarrierNetwork_returnTrueAndConnect() { - mWifiPickerTrackerHelper.setWifiPickerTracker(mWifiPickerTracker); - when(mWifiPickerTracker.getMergedCarrierEntry()).thenReturn(mMergedCarrierEntry); when(mMergedCarrierEntry.canConnect()).thenReturn(true); assertThat(mWifiPickerTrackerHelper.connectCarrierNetwork(mConnectCallback)).isTrue(); @@ -178,7 +179,6 @@ public class WifiPickerTrackerHelperTest { @Test public void connectCarrierNetwork_mergedCarrierEntryIsNull_returnFalse() { - mWifiPickerTrackerHelper.setWifiPickerTracker(mWifiPickerTracker); when(mWifiPickerTracker.getMergedCarrierEntry()).thenReturn(null); assertThat(mWifiPickerTrackerHelper.connectCarrierNetwork(mConnectCallback)).isFalse(); @@ -186,11 +186,32 @@ public class WifiPickerTrackerHelperTest { @Test public void connectCarrierNetwork_canConnectIsFalse_returnFalseAndNeverConnect() { - mWifiPickerTrackerHelper.setWifiPickerTracker(mWifiPickerTracker); - when(mWifiPickerTracker.getMergedCarrierEntry()).thenReturn(mMergedCarrierEntry); when(mMergedCarrierEntry.canConnect()).thenReturn(false); assertThat(mWifiPickerTrackerHelper.connectCarrierNetwork(mConnectCallback)).isFalse(); verify(mMergedCarrierEntry, never()).connect(mConnectCallback); } + + @Test + public void getCarrierNetworkLevel_mergedCarrierEntryIsNull_returnMinLevel() { + when(mWifiPickerTracker.getMergedCarrierEntry()).thenReturn(null); + + assertThat(mWifiPickerTrackerHelper.getCarrierNetworkLevel()).isEqualTo(WIFI_LEVEL_MIN); + } + + @Test + public void getCarrierNetworkLevel_getUnreachableLevel_returnMinLevel() { + when(mMergedCarrierEntry.getLevel()).thenReturn(WIFI_LEVEL_UNREACHABLE); + + assertThat(mWifiPickerTrackerHelper.getCarrierNetworkLevel()).isEqualTo(WIFI_LEVEL_MIN); + } + + @Test + public void getCarrierNetworkLevel_getAvailableLevel_returnSameLevel() { + for (int level = WIFI_LEVEL_MIN; level <= WIFI_LEVEL_MAX; level++) { + when(mMergedCarrierEntry.getLevel()).thenReturn(level); + + assertThat(mWifiPickerTrackerHelper.getCarrierNetworkLevel()).isEqualTo(level); + } + } }