diff --git a/Android.bp b/Android.bp index 79df743c573..8353634e312 100644 --- a/Android.bp +++ b/Android.bp @@ -104,6 +104,7 @@ android_library { "settings-telephony-protos-lite", "statslog-settings", "androidx.test.rules", + "telephony_flags_core_java_lib", ], plugins: ["androidx.room_room-compiler-plugin"], diff --git a/res/values/strings.xml b/res/values/strings.xml index f53af71d0fc..257d9522796 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1938,6 +1938,12 @@ Notify for public networks Notify when a high\u2011quality public network is available + + Allow WEP networks + + WEP is an older security protocol that\u0027s less secure + + Your carrier doesn\u0027t allow WEP networks because they\u0027re less secure Turn on Wi\u2011Fi automatically @@ -1987,6 +1993,18 @@ Turn on Wi\u2011Fi scanning turned on + + This network uses an older security protocol that\u0027s less secure + + %1$s is blocked + + This network uses an older security protocol called WEP, which is less secure. To connect anyway, you can allow WEP networks. + + Your carrier doesn\u0027t allow you to connect to this network because it uses an older security protocol that’s less secure + + Allow WEP + + Close @@ -9464,6 +9482,13 @@ other {# apps used memory in the last {time}} } + + Enable memory usage profiling + + Memory usage profiling requires additional system resources. + + Memory profiling disabled + Frequency diff --git a/res/xml/process_stats_summary.xml b/res/xml/process_stats_summary.xml index 3b3271d769a..9def18fa7b8 100644 --- a/res/xml/process_stats_summary.xml +++ b/res/xml/process_stats_summary.xml @@ -19,45 +19,52 @@ android:title="@string/app_memory_use" android:key="app_list"> + + + android:title="@string/average_memory_use" + android:key="memory_info"> - + - + - + - + - + - + - + - + + diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java index 80f5962d92a..8e59a7fac82 100644 --- a/src/com/android/settings/ResetNetwork.java +++ b/src/com/android/settings/ResetNetwork.java @@ -44,6 +44,7 @@ import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import com.android.internal.telephony.flags.Flags; import com.android.settings.core.InstrumentedFragment; import com.android.settings.core.SubSettingLauncher; import com.android.settings.network.ResetNetworkRestrictionViewBuilder; @@ -121,16 +122,22 @@ public class ResetNetwork extends InstrumentedFragment { void showFinalConfirmation() { Bundle args = new Bundle(); - ResetNetworkRequest request = new ResetNetworkRequest( - ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER | - ResetNetworkRequest.RESET_VPN_MANAGER - ); + // TODO(b/317276437) Simplify the logic once flag is released + int resetOptions = ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER + | ResetNetworkRequest.RESET_VPN_MANAGER; + if (Flags.resetMobileNetworkSettings()) { + resetOptions |= ResetNetworkRequest.RESET_IMS_STACK; + } + ResetNetworkRequest request = new ResetNetworkRequest(resetOptions); if (mSubscriptions != null && mSubscriptions.size() > 0) { int selectedIndex = mSubscriptionSpinner.getSelectedItemPosition(); SubscriptionInfo subscription = mSubscriptions.get(selectedIndex); int subId = subscription.getSubscriptionId(); request.setResetTelephonyAndNetworkPolicyManager(subId) .setResetApn(subId); + if (Flags.resetMobileNetworkSettings()) { + request.setResetImsSubId(subId); + } } if (mEsimContainer.getVisibility() == View.VISIBLE && mEsimCheckbox.isChecked()) { request.setResetEsim(getContext().getPackageName()) diff --git a/src/com/android/settings/ResetNetworkRequest.java b/src/com/android/settings/ResetNetworkRequest.java index 40eebb0eb29..71c12b1932e 100644 --- a/src/com/android/settings/ResetNetworkRequest.java +++ b/src/com/android/settings/ResetNetworkRequest.java @@ -48,11 +48,23 @@ public class ResetNetworkRequest { /* Reset option - reset BluetoothManager */ public static final int RESET_BLUETOOTH_MANAGER = 0x10; - /* Subscription ID for not performing reset TelephonyAndNetworkPolicy or reset APN */ + /* Reset option - reset IMS stack */ + public static final int RESET_IMS_STACK = 0x20; + + /** + * Subscription ID indicates NOT resetting any of the components below: + * - TelephonyAndNetworkPolicy + * - APN + * - IMS + */ public static final int INVALID_SUBSCRIPTION_ID = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - /* Subscription ID for performing reset TelephonyAndNetworkPolicy or reset APN - on all subscriptions */ + /** + * Subscription ID indicates resetting components below for ALL subscriptions: + * - TelephonyAndNetworkPolicy + * - APN + * - IMS + */ public static final int ALL_SUBSCRIPTION_ID = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; /* Key within Bundle. To store some connectivity options for reset */ @@ -75,10 +87,14 @@ public class ResetNetworkRequest { @VisibleForTesting protected static final String KEY_APN_SUBID = "resetApnSubId"; + /** Key within Bundle. To store subscription ID for resetting IMS. */ + protected static final String KEY_RESET_IMS_SUBID = "resetImsSubId"; + private int mResetOptions = RESET_NONE; private String mResetEsimPackageName; private int mResetTelephonyManager = INVALID_SUBSCRIPTION_ID; private int mResetApn = INVALID_SUBSCRIPTION_ID; + private int mSubscriptionIdToResetIms = INVALID_SUBSCRIPTION_ID; /** * Reconstruct based on keys stored within Bundle. @@ -93,6 +109,8 @@ public class ResetNetworkRequest { mResetTelephonyManager = optionsFromBundle.getInt( KEY_TELEPHONY_NET_POLICY_MANAGER_SUBID, INVALID_SUBSCRIPTION_ID); mResetApn = optionsFromBundle.getInt(KEY_APN_SUBID, INVALID_SUBSCRIPTION_ID); + mSubscriptionIdToResetIms = optionsFromBundle.getInt(KEY_RESET_IMS_SUBID, + INVALID_SUBSCRIPTION_ID); } /** @@ -172,6 +190,29 @@ public class ResetNetworkRequest { return this; } + /** + * Get the subscription ID applied for resetting IMS. + * @return subscription ID. + * {@code ALL_SUBSCRIPTION_ID} for applying to all subscriptions. + * {@code INVALID_SUBSCRIPTION_ID} means resetting IMS + * is not part of the option within this request. + */ + public int getResetImsSubId() { + return mSubscriptionIdToResetIms; + } + + /** + * Set the subscription ID applied for resetting APN. + * @param subId is the subscription ID referenced from SubscriptionManager. + * {@code ALL_SUBSCRIPTION_ID} for applying to all subscriptions. + * {@code INVALID_SUBSCRIPTION_ID} means resetting IMS will not take place. + * @return this + */ + public ResetNetworkRequest setResetImsSubId(int subId) { + mSubscriptionIdToResetIms = subId; + return this; + } + /** * Store a copy of this request into Bundle given. * @param writeToBundle is a Bundle for storing configurations of this request. @@ -182,6 +223,7 @@ public class ResetNetworkRequest { writeToBundle.putString(KEY_ESIM_PACKAGE, mResetEsimPackageName); writeToBundle.putInt(KEY_TELEPHONY_NET_POLICY_MANAGER_SUBID, mResetTelephonyManager); writeToBundle.putInt(KEY_APN_SUBID, mResetApn); + writeToBundle.putInt(KEY_RESET_IMS_SUBID, mSubscriptionIdToResetIms); return this; } @@ -219,6 +261,9 @@ public class ResetNetworkRequest { if (mResetApn != INVALID_SUBSCRIPTION_ID) { builder.resetApn(mResetApn); } + if ((mResetOptions & RESET_IMS_STACK) != 0) { + builder.resetIms(mSubscriptionIdToResetIms); + } return builder; } } diff --git a/src/com/android/settings/ResetSubscriptionContract.java b/src/com/android/settings/ResetSubscriptionContract.java index 580e907707b..528a16def5a 100644 --- a/src/com/android/settings/ResetSubscriptionContract.java +++ b/src/com/android/settings/ResetSubscriptionContract.java @@ -23,8 +23,8 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; -import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.IntStream; @@ -53,8 +53,8 @@ public class ResetSubscriptionContract implements AutoCloseable { mContext = context; // Only keeps specific subscription ID required to perform reset operation IntStream subIdStream = IntStream.of( - resetRequest.getResetTelephonyAndNetworkPolicyManager() - , resetRequest.getResetApnSubId()); + resetRequest.getResetTelephonyAndNetworkPolicyManager(), + resetRequest.getResetApnSubId(), resetRequest.getResetImsSubId()); mResetSubscriptionIds = subIdStream.sorted().distinct() .filter(id -> SubscriptionManager.isUsableSubscriptionId(id)) .toArray(); diff --git a/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java index f0764721dcd..53d9c55fad9 100644 --- a/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java +++ b/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java @@ -17,12 +17,16 @@ package com.android.settings.accessibility; import android.content.Context; +import android.content.res.Resources; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.search.SearchIndexableRaw; + +import java.util.List; /** * Preference controller for accessibility button preference. @@ -41,10 +45,23 @@ public class AccessibilityButtonPreferenceController extends BasePreferenceContr @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - final int titleResource = AccessibilityUtil.isGestureNavigateEnabled(mContext) - ? R.string.accessibility_button_gesture_title : R.string.accessibility_button_title; final Preference preference = screen.findPreference(getPreferenceKey()); - preference.setTitle(titleResource); + preference.setTitle(getPreferenceTitleResource()); } + + @Override + public void updateDynamicRawDataToIndex(List rawData) { + SearchIndexableRaw data = new SearchIndexableRaw(mContext); + data.key = getPreferenceKey(); + final Resources res = mContext.getResources(); + data.title = res.getString(getPreferenceTitleResource()); + data.screenTitle = res.getString(R.string.accessibility_shortcuts_settings_title); + rawData.add(data); + } + + private int getPreferenceTitleResource() { + return AccessibilityUtil.isGestureNavigateEnabled(mContext) + ? R.string.accessibility_button_gesture_title : R.string.accessibility_button_title; + } } diff --git a/src/com/android/settings/applications/ProcessStatsSummary.java b/src/com/android/settings/applications/ProcessStatsSummary.java index 4044794e719..ef76cd5840b 100644 --- a/src/com/android/settings/applications/ProcessStatsSummary.java +++ b/src/com/android/settings/applications/ProcessStatsSummary.java @@ -16,20 +16,26 @@ package com.android.settings.applications; import android.app.settings.SettingsEnums; +import android.content.ContentResolver; import android.content.Context; import android.icu.text.MessageFormat; import android.os.Bundle; +import android.os.Flags; +import android.provider.Settings; import android.text.format.Formatter; import android.text.format.Formatter.BytesResult; import androidx.preference.Preference; import androidx.preference.Preference.OnPreferenceClickListener; +import androidx.preference.PreferenceCategory; +import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settings.SummaryPreference; import com.android.settings.Utils; import com.android.settings.applications.ProcStatsData.MemInfo; import com.android.settings.core.SubSettingLauncher; +import com.android.settings.development.DisableDevSettingsDialogFragment; import java.util.HashMap; import java.util.Locale; @@ -37,6 +43,8 @@ import java.util.Map; public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenceClickListener { + private static final String KEY_PREF_SCREEN = "app_list"; + private static final String KEY_MEMORY_INFO_PREF_GROUP = "memory_info"; private static final String KEY_STATUS_HEADER = "status_header"; private static final String KEY_PERFORMANCE = "performance"; @@ -44,7 +52,9 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc private static final String KEY_AVERAGY_USED = "average_used"; private static final String KEY_FREE = "free"; private static final String KEY_APP_LIST = "apps_list"; + private static final String KEY_FORCE_ENABLE_PSS_PROFILING = "force_enable_pss_profiling"; + private PreferenceCategory mMemoryInfoPrefCategory; private SummaryPreference mSummaryPref; private Preference mPerformance; @@ -52,12 +62,14 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc private Preference mAverageUsed; private Preference mFree; private Preference mAppListPreference; + private SwitchPreference mForceEnablePssProfiling; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.process_stats_summary); + mMemoryInfoPrefCategory = (PreferenceCategory) findPreference(KEY_MEMORY_INFO_PREF_GROUP); mSummaryPref = (SummaryPreference) findPreference(KEY_STATUS_HEADER); mPerformance = findPreference(KEY_PERFORMANCE); mTotalMemory = findPreference(KEY_TOTAL_MEMORY); @@ -65,11 +77,37 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc mFree = findPreference(KEY_FREE); mAppListPreference = findPreference(KEY_APP_LIST); mAppListPreference.setOnPreferenceClickListener(this); + + // This preference is only applicable if the flag for PSS deprecation in AppProfiler is + // enabled. Otherwise, it can immediately be hidden. + mForceEnablePssProfiling = + (SwitchPreference) findPreference(KEY_FORCE_ENABLE_PSS_PROFILING); + if (Flags.removeAppProfilerPssCollection()) { + mForceEnablePssProfiling.setOnPreferenceClickListener(this); + // Make the toggle reflect the current state of the global setting. + mForceEnablePssProfiling.setChecked(isPssProfilingForceEnabled(getContext())); + } else { + mForceEnablePssProfiling.setVisible(false); + } + } + + private void refreshPreferences() { + // The memory fields should be static if the flag is not enabled. + if (!Flags.removeAppProfilerPssCollection()) { + return; + } + mMemoryInfoPrefCategory.setVisible(mForceEnablePssProfiling.isChecked()); } @Override public void refreshUi() { Context context = getContext(); + refreshPreferences(); + + // If PSS collection is not enabled, none of the following work needs to be done. + if (Flags.removeAppProfilerPssCollection() && !isPssProfilingForceEnabled(context)) { + return; + } MemInfo memInfo = mStatsManager.getMemInfo(); @@ -100,7 +138,8 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc String durationString = getString(sDurationLabels[mDurationIndex]); int numApps = mStatsManager.getEntries().size(); MessageFormat msgFormat = new MessageFormat( - getResources().getString(R.string.memory_usage_apps_summary), Locale.getDefault()); + getResources().getString(R.string.memory_usage_apps_summary), + Locale.getDefault()); Map arguments = new HashMap<>(); arguments.put("count", numApps); arguments.put("time", durationString); @@ -131,7 +170,34 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc .setSourceMetricsCategory(getMetricsCategory()) .launch(); return true; + } else if (preference == mForceEnablePssProfiling) { + DisableDevSettingsDialogFragment.show(this); } return false; } + + private boolean isPssProfilingForceEnabled(Context context) { + ContentResolver cr = context.getContentResolver(); + return Settings.Global.getInt(cr, Settings.Global.FORCE_ENABLE_PSS_PROFILING, 0) == 1; + } + + /** + * Called when the reboot confirmation button is clicked. + */ + public void onRebootDialogConfirmed() { + Context context = getContext(); + ContentResolver cr = context.getContentResolver(); + Settings.Global.putInt(cr, Settings.Global.FORCE_ENABLE_PSS_PROFILING, + mForceEnablePssProfiling.isChecked() ? 1 : 0); + refreshPreferences(); + } + + /** + * Called when the reboot deny button is clicked. + */ + public void onRebootDialogCanceled() { + // Set the toggle to reflect the state of the setting, which should not have changed. + mForceEnablePssProfiling.setChecked(isPssProfilingForceEnabled(getContext())); + } + } diff --git a/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java b/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java index 02d5c27e5c6..ef054dfa405 100644 --- a/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java +++ b/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java @@ -21,6 +21,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN; @@ -51,6 +52,9 @@ import com.android.settingslib.applications.AppUtils; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.widget.ActionButtonsPreference; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + import java.util.ArrayList; import java.util.List; @@ -63,29 +67,41 @@ public class UserAspectRatioDetails extends AppInfoBase implements private static final String KEY_HEADER_SUMMARY = "app_aspect_ratio_summary"; private static final String KEY_HEADER_BUTTONS = "header_view"; - private static final String KEY_PREF_FULLSCREEN = "fullscreen_pref"; + private static final String KEY_PREF_HALF_SCREEN = "half_screen_pref"; private static final String KEY_PREF_DISPLAY_SIZE = "display_size_pref"; private static final String KEY_PREF_16_9 = "16_9_pref"; private static final String KEY_PREF_4_3 = "4_3_pref"; @VisibleForTesting + static final String KEY_PREF_FULLSCREEN = "fullscreen_pref"; + @VisibleForTesting static final String KEY_PREF_DEFAULT = "app_default_pref"; @VisibleForTesting static final String KEY_PREF_3_2 = "3_2_pref"; + @VisibleForTesting + @NonNull String mSelectedKey = KEY_PREF_DEFAULT; + + /** Radio button preference key mapped to {@link PackageManager.UserMinAspectRatio} value */ + @VisibleForTesting + final BiMap mKeyToAspectRatioMap = HashBiMap.create(); + private final List mAspectRatioPreferences = new ArrayList<>(); @NonNull private UserAspectRatioManager mUserAspectRatioManager; - @NonNull private String mSelectedKey = KEY_PREF_DEFAULT; + private boolean mIsOverrideToFullscreenEnabled; @Override public void onCreate(@NonNull Bundle savedInstanceState) { super.onCreate(savedInstanceState); mUserAspectRatioManager = new UserAspectRatioManager(getContext()); + mIsOverrideToFullscreenEnabled = getAspectRatioManager() + .isOverrideToFullscreenEnabled(mPackageName, mUserId); + initPreferences(); try { - final int userAspectRatio = mUserAspectRatioManager + final int userAspectRatio = getAspectRatioManager() .getUserMinAspectRatioValue(mPackageName, mUserId); mSelectedKey = getSelectedKey(userAspectRatio); } catch (RemoteException e) { @@ -148,43 +164,23 @@ public class UserAspectRatioDetails extends AppInfoBase implements } @PackageManager.UserMinAspectRatio - private int getSelectedUserMinAspectRatio(@NonNull String selectedKey) { - switch (selectedKey) { - case KEY_PREF_FULLSCREEN: - return USER_MIN_ASPECT_RATIO_FULLSCREEN; - case KEY_PREF_HALF_SCREEN: - return USER_MIN_ASPECT_RATIO_SPLIT_SCREEN; - case KEY_PREF_DISPLAY_SIZE: - return USER_MIN_ASPECT_RATIO_DISPLAY_SIZE; - case KEY_PREF_3_2: - return USER_MIN_ASPECT_RATIO_3_2; - case KEY_PREF_4_3: - return USER_MIN_ASPECT_RATIO_4_3; - case KEY_PREF_16_9: - return USER_MIN_ASPECT_RATIO_16_9; - default: - return USER_MIN_ASPECT_RATIO_UNSET; - } + @VisibleForTesting + int getSelectedUserMinAspectRatio(@NonNull String selectedKey) { + final int appDefault = mKeyToAspectRatioMap + .getOrDefault(KEY_PREF_DEFAULT, USER_MIN_ASPECT_RATIO_UNSET); + return mKeyToAspectRatioMap.getOrDefault(selectedKey, appDefault); } @NonNull private String getSelectedKey(@PackageManager.UserMinAspectRatio int userMinAspectRatio) { - switch (userMinAspectRatio) { - case USER_MIN_ASPECT_RATIO_FULLSCREEN: - return KEY_PREF_FULLSCREEN; - case USER_MIN_ASPECT_RATIO_SPLIT_SCREEN: - return KEY_PREF_HALF_SCREEN; - case USER_MIN_ASPECT_RATIO_DISPLAY_SIZE: - return KEY_PREF_DISPLAY_SIZE; - case USER_MIN_ASPECT_RATIO_3_2: - return KEY_PREF_3_2; - case USER_MIN_ASPECT_RATIO_4_3: - return KEY_PREF_4_3; - case USER_MIN_ASPECT_RATIO_16_9: - return KEY_PREF_16_9; - default: - return KEY_PREF_DEFAULT; + final String appDefault = mKeyToAspectRatioMap.inverse() + .getOrDefault(USER_MIN_ASPECT_RATIO_UNSET, KEY_PREF_DEFAULT); + + if (userMinAspectRatio == USER_MIN_ASPECT_RATIO_UNSET && mIsOverrideToFullscreenEnabled) { + // Pre-select fullscreen option if device manufacturer has overridden app to fullscreen + userMinAspectRatio = USER_MIN_ASPECT_RATIO_FULLSCREEN; } + return mKeyToAspectRatioMap.inverse().getOrDefault(userMinAspectRatio, appDefault); } @Override @@ -217,7 +213,11 @@ public class UserAspectRatioDetails extends AppInfoBase implements .setButton1Icon(R.drawable.ic_settings_open) .setButton1OnClickListener(v -> launchApplication()); - addPreference(KEY_PREF_DEFAULT, USER_MIN_ASPECT_RATIO_UNSET); + if (mIsOverrideToFullscreenEnabled) { + addPreference(KEY_PREF_DEFAULT, USER_MIN_ASPECT_RATIO_APP_DEFAULT); + } else { + addPreference(KEY_PREF_DEFAULT, USER_MIN_ASPECT_RATIO_UNSET); + } addPreference(KEY_PREF_FULLSCREEN, USER_MIN_ASPECT_RATIO_FULLSCREEN); addPreference(KEY_PREF_DISPLAY_SIZE, USER_MIN_ASPECT_RATIO_DISPLAY_SIZE); addPreference(KEY_PREF_HALF_SCREEN, USER_MIN_ASPECT_RATIO_SPLIT_SCREEN); @@ -232,12 +232,13 @@ public class UserAspectRatioDetails extends AppInfoBase implements if (pref == null) { return; } - if (!mUserAspectRatioManager.hasAspectRatioOption(aspectRatio, mPackageName)) { + if (!getAspectRatioManager().hasAspectRatioOption(aspectRatio, mPackageName)) { pref.setVisible(false); return; } pref.setTitle(mUserAspectRatioManager.getAccessibleEntry(aspectRatio, mPackageName)); pref.setOnClickListener(this); + mKeyToAspectRatioMap.put(key, aspectRatio); mAspectRatioPreferences.add(pref); } diff --git a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java index 3cca5f6771e..3bf61099f13 100644 --- a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java +++ b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java @@ -16,19 +16,32 @@ package com.android.settings.applications.appcompat; +import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION_TO_USER; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET; import static android.os.UserHandle.getUserHandleForUid; +import static android.os.UserHandle.getUserId; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE; import static java.lang.Boolean.FALSE; import android.app.AppGlobals; +import android.app.compat.CompatChanges; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.os.RemoteException; +import android.os.UserHandle; import android.provider.DeviceConfig; import android.util.ArrayMap; @@ -37,6 +50,7 @@ import androidx.annotation.Nullable; import com.android.settings.R; import com.android.settings.Utils; +import com.android.window.flags.Flags; import com.google.common.annotations.VisibleForTesting; @@ -55,6 +69,8 @@ public class UserAspectRatioManager { "enable_app_compat_user_aspect_ratio_fullscreen"; private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_FULLSCREEN = true; + final boolean mIsUserMinAspectRatioAppDefaultFlagEnabled = Flags.userMinAspectRatioAppDefault(); + private final Context mContext; private final IPackageManager mIPm; /** Apps that have launcher entry defined in manifest */ @@ -62,8 +78,13 @@ public class UserAspectRatioManager { private final Map mUserAspectRatioA11yMap; public UserAspectRatioManager(@NonNull Context context) { + this(context, AppGlobals.getPackageManager()); + } + + @VisibleForTesting + UserAspectRatioManager(@NonNull Context context, @NonNull IPackageManager pm) { mContext = context; - mIPm = AppGlobals.getPackageManager(); + mIPm = pm; mUserAspectRatioA11yMap = new ArrayMap<>(); mUserAspectRatioMap = getUserMinAspectRatioMapping(); } @@ -86,7 +107,7 @@ public class UserAspectRatioManager { throws RemoteException { final int aspectRatio = mIPm.getUserMinAspectRatio(packageName, uid); return hasAspectRatioOption(aspectRatio, packageName) - ? aspectRatio : PackageManager.USER_MIN_ASPECT_RATIO_UNSET; + ? aspectRatio : USER_MIN_ASPECT_RATIO_UNSET; } /** @@ -94,11 +115,18 @@ public class UserAspectRatioManager { */ @NonNull public String getUserMinAspectRatioEntry(@PackageManager.UserMinAspectRatio int aspectRatio, - String packageName) { - if (!hasAspectRatioOption(aspectRatio, packageName)) { - return mUserAspectRatioMap.get(PackageManager.USER_MIN_ASPECT_RATIO_UNSET); + @NonNull String packageName, int userId) { + final String appDefault = getAspectRatioStringOrDefault( + mUserAspectRatioMap.get(USER_MIN_ASPECT_RATIO_UNSET), + USER_MIN_ASPECT_RATIO_UNSET); + + if (!hasAspectRatioOption(aspectRatio, packageName)) { + return appDefault; } - return mUserAspectRatioMap.get(aspectRatio); + + return isCurrentSelectionFromManufacturerOverride(packageName, userId, aspectRatio) + ? getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN, packageName, userId) + : mUserAspectRatioMap.getOrDefault(aspectRatio, appDefault); } /** @@ -106,19 +134,22 @@ public class UserAspectRatioManager { */ @NonNull public CharSequence getAccessibleEntry(@PackageManager.UserMinAspectRatio int aspectRatio, - String packageName) { - return mUserAspectRatioA11yMap.getOrDefault(aspectRatio, - getUserMinAspectRatioEntry(aspectRatio, packageName)); + @NonNull String packageName) { + final int userId = mContext.getUserId(); + return isCurrentSelectionFromManufacturerOverride(packageName, userId, aspectRatio) + ? getAccessibleEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN, packageName) + : mUserAspectRatioA11yMap.getOrDefault(aspectRatio, + getUserMinAspectRatioEntry(aspectRatio, packageName, userId)); } /** * @return corresponding aspect ratio string for package name and user */ @NonNull - public String getUserMinAspectRatioEntry(@NonNull String packageName, int uid) + public String getUserMinAspectRatioEntry(@NonNull String packageName, int userId) throws RemoteException { - final int aspectRatio = getUserMinAspectRatioValue(packageName, uid); - return getUserMinAspectRatioEntry(aspectRatio, packageName); + final int aspectRatio = getUserMinAspectRatioValue(packageName, userId); + return getUserMinAspectRatioEntry(aspectRatio, packageName, userId); } /** @@ -128,8 +159,7 @@ public class UserAspectRatioManager { */ public boolean hasAspectRatioOption(@PackageManager.UserMinAspectRatio int option, String packageName) { - if (option == PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN - && !isFullscreenOptionEnabled(packageName)) { + if (option == USER_MIN_ASPECT_RATIO_FULLSCREEN && !isFullscreenOptionEnabled(packageName)) { return false; } return mUserAspectRatioMap.containsKey(option); @@ -154,6 +184,18 @@ public class UserAspectRatioManager { return !FALSE.equals(appAllowsUserAspectRatioOverride) && hasLauncherEntry(app); } + /** + * Whether the app has been overridden to fullscreen by device manufacturer or + * whether the app's aspect ratio has been overridden by the user. + */ + public boolean isAppOverridden(@NonNull ApplicationInfo app, + @PackageManager.UserMinAspectRatio int userOverride) { + return (userOverride != USER_MIN_ASPECT_RATIO_UNSET + && userOverride != USER_MIN_ASPECT_RATIO_APP_DEFAULT) + || isCurrentSelectionFromManufacturerOverride(app.packageName, getUserId(app.uid), + userOverride); + } + /** * Whether fullscreen option in per-app user aspect ratio settings is enabled */ @@ -168,6 +210,32 @@ public class UserAspectRatioManager { DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_FULLSCREEN); } + /** + * Whether the device manufacturer has overridden app's orientation to + * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_USER} to force app to fullscreen + * and app has not opted-out from the treatment + */ + boolean isOverrideToFullscreenEnabled(String pkgName, int userId) { + Boolean appAllowsOrientationOverride = readComponentProperty(mContext.getPackageManager(), + pkgName, PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE); + return mIsUserMinAspectRatioAppDefaultFlagEnabled + && hasAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN, pkgName) + && !FALSE.equals(appAllowsOrientationOverride) + && isFullscreenCompatChangeEnabled(pkgName, userId); + } + + @VisibleForTesting + boolean isFullscreenCompatChangeEnabled(String pkgName, int userId) { + return CompatChanges.isChangeEnabled( + OVERRIDE_ANY_ORIENTATION_TO_USER, pkgName, UserHandle.of(userId)); + } + + private boolean isCurrentSelectionFromManufacturerOverride(String pkgName, int userId, + @PackageManager.UserMinAspectRatio int aspectRatio) { + return aspectRatio == USER_MIN_ASPECT_RATIO_UNSET + && isOverrideToFullscreenEnabled(pkgName, userId); + } + private boolean hasLauncherEntry(@NonNull ApplicationInfo app) { return !mContext.getSystemService(LauncherApps.class) .getActivityList(app.packageName, getUserHandleForUid(app.uid)) @@ -197,13 +265,13 @@ public class UserAspectRatioManager { boolean containsColon = aspectRatioString.contains(":"); switch (aspectRatioVal) { // Only map known values of UserMinAspectRatio and ignore unknown entries - case PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN: - case PackageManager.USER_MIN_ASPECT_RATIO_UNSET: - case PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN: - case PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE: - case PackageManager.USER_MIN_ASPECT_RATIO_4_3: - case PackageManager.USER_MIN_ASPECT_RATIO_16_9: - case PackageManager.USER_MIN_ASPECT_RATIO_3_2: + case USER_MIN_ASPECT_RATIO_FULLSCREEN: + case USER_MIN_ASPECT_RATIO_UNSET: + case USER_MIN_ASPECT_RATIO_SPLIT_SCREEN: + case USER_MIN_ASPECT_RATIO_DISPLAY_SIZE: + case USER_MIN_ASPECT_RATIO_4_3: + case USER_MIN_ASPECT_RATIO_16_9: + case USER_MIN_ASPECT_RATIO_3_2: if (containsColon) { String[] aspectRatioDigits = aspectRatioString.split(":"); String accessibleString = getAccessibleOption(aspectRatioDigits[0], @@ -215,10 +283,18 @@ public class UserAspectRatioManager { userMinAspectRatioMap.put(aspectRatioVal, aspectRatioString); } } - if (!userMinAspectRatioMap.containsKey(PackageManager.USER_MIN_ASPECT_RATIO_UNSET)) { + if (!userMinAspectRatioMap.containsKey(USER_MIN_ASPECT_RATIO_UNSET)) { throw new RuntimeException("config_userAspectRatioOverrideValues options must have" + " USER_MIN_ASPECT_RATIO_UNSET value"); } + if (mIsUserMinAspectRatioAppDefaultFlagEnabled) { + userMinAspectRatioMap.put(USER_MIN_ASPECT_RATIO_APP_DEFAULT, + userMinAspectRatioMap.get(USER_MIN_ASPECT_RATIO_UNSET)); + if (mUserAspectRatioA11yMap.containsKey(USER_MIN_ASPECT_RATIO_UNSET)) { + mUserAspectRatioA11yMap.put(USER_MIN_ASPECT_RATIO_APP_DEFAULT, + mUserAspectRatioA11yMap.get(USER_MIN_ASPECT_RATIO_UNSET)); + } + } return userMinAspectRatioMap; } @@ -236,17 +312,17 @@ public class UserAspectRatioManager { } // Options are customized per device and if strings are set to @null, use default switch (aspectRatioVal) { - case PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN: + case USER_MIN_ASPECT_RATIO_FULLSCREEN: return mContext.getString(R.string.user_aspect_ratio_fullscreen); - case PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN: + case USER_MIN_ASPECT_RATIO_SPLIT_SCREEN: return mContext.getString(R.string.user_aspect_ratio_half_screen); - case PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE: + case USER_MIN_ASPECT_RATIO_DISPLAY_SIZE: return mContext.getString(R.string.user_aspect_ratio_device_size); - case PackageManager.USER_MIN_ASPECT_RATIO_4_3: + case USER_MIN_ASPECT_RATIO_4_3: return mContext.getString(R.string.user_aspect_ratio_4_3); - case PackageManager.USER_MIN_ASPECT_RATIO_16_9: + case USER_MIN_ASPECT_RATIO_16_9: return mContext.getString(R.string.user_aspect_ratio_16_9); - case PackageManager.USER_MIN_ASPECT_RATIO_3_2: + case USER_MIN_ASPECT_RATIO_3_2: return mContext.getString(R.string.user_aspect_ratio_3_2); default: return mContext.getString(R.string.user_aspect_ratio_app_default); diff --git a/src/com/android/settings/development/DisableDevSettingsDialogFragment.java b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java index 224768b0561..4355f277cb3 100644 --- a/src/com/android/settings/development/DisableDevSettingsDialogFragment.java +++ b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java @@ -29,6 +29,8 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.applications.ProcessStatsSummary; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment @@ -42,7 +44,7 @@ public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment return dialog; } - public static void show(DevelopmentSettingsDashboardFragment host) { + public static void show(SettingsPreferenceFragment host) { final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment(); dialog.setTargetFragment(host, 0 /* requestCode */); // We need to handle data changes and switch state based on which button user clicks, @@ -75,18 +77,31 @@ public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment @Override public void onClick(DialogInterface dialog, int which) { Fragment fragment = getTargetFragment(); - if (!(fragment instanceof DevelopmentSettingsDashboardFragment)){ + if (!(fragment instanceof DevelopmentSettingsDashboardFragment) + && !(fragment instanceof ProcessStatsSummary)) { Log.e(TAG, "getTargetFragment return unexpected type"); } - final DevelopmentSettingsDashboardFragment host = - (DevelopmentSettingsDashboardFragment) fragment; - if (which == DialogInterface.BUTTON_POSITIVE) { - host.onDisableDevelopmentOptionsConfirmed(); - PowerManager pm = getContext().getSystemService(PowerManager.class); - pm.reboot(null); - } else { - host.onDisableDevelopmentOptionsRejected(); + if (fragment instanceof DevelopmentSettingsDashboardFragment) { + final DevelopmentSettingsDashboardFragment host = + (DevelopmentSettingsDashboardFragment) fragment; + if (which == DialogInterface.BUTTON_POSITIVE) { + host.onDisableDevelopmentOptionsConfirmed(); + PowerManager pm = getContext().getSystemService(PowerManager.class); + pm.reboot(null); + } else { + host.onDisableDevelopmentOptionsRejected(); + } + } else if (fragment instanceof ProcessStatsSummary) { + final ProcessStatsSummary host = + (ProcessStatsSummary) fragment; + if (which == DialogInterface.BUTTON_POSITIVE) { + host.onRebootDialogConfirmed(); + PowerManager pm = getContext().getSystemService(PowerManager.class); + pm.reboot(null); + } else { + host.onRebootDialogCanceled(); + } } } } diff --git a/src/com/android/settings/development/MemoryUsagePreferenceController.java b/src/com/android/settings/development/MemoryUsagePreferenceController.java index 1b20e70a578..ca8effa4a32 100644 --- a/src/com/android/settings/development/MemoryUsagePreferenceController.java +++ b/src/com/android/settings/development/MemoryUsagePreferenceController.java @@ -17,6 +17,8 @@ package com.android.settings.development; import android.content.Context; +import android.os.Flags; +import android.provider.Settings; import android.text.format.Formatter; import androidx.annotation.VisibleForTesting; @@ -65,9 +67,13 @@ public class MemoryUsagePreferenceController extends DeveloperOptionsPreferenceC (long) memInfo.realUsedRam); final String totalResult = Formatter.formatShortFileSize(mContext, (long) memInfo.realTotalRam); - ThreadUtils.postOnMainThread( - () -> mPreference.setSummary(mContext.getString(R.string.memory_summary, - usedResult, totalResult))); + boolean displayMemorySummary = !Flags.removeAppProfilerPssCollection(); + displayMemorySummary |= Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.FORCE_ENABLE_PSS_PROFILING, 0) == 1; + String summary = displayMemorySummary + ? mContext.getString(R.string.memory_summary, usedResult, totalResult) + : mContext.getString(R.string.pss_profiling_disabled); + ThreadUtils.postOnMainThread(() -> mPreference.setSummary(summary)); }); } diff --git a/src/com/android/settings/network/ResetNetworkOperationBuilder.java b/src/com/android/settings/network/ResetNetworkOperationBuilder.java index 3583d06b2b4..61f57f949df 100644 --- a/src/com/android/settings/network/ResetNetworkOperationBuilder.java +++ b/src/com/android/settings/network/ResetNetworkOperationBuilder.java @@ -33,6 +33,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; +import com.android.settings.ResetNetworkRequest; import com.android.settings.network.apn.ApnSettings; import java.util.ArrayList; @@ -212,6 +213,32 @@ public class ResetNetworkOperationBuilder { return this; } + /** + * Append a step of resetting IMS stack. + * + * @return this + */ + public ResetNetworkOperationBuilder resetIms(int subId) { + attachSystemServiceWork(Context.TELEPHONY_SERVICE, + (Consumer) tm -> { + if (subId == ResetNetworkRequest.INVALID_SUBSCRIPTION_ID) { + // Do nothing + return; + } + if (subId == ResetNetworkRequest.ALL_SUBSCRIPTION_ID) { + // Reset IMS for all slots + for (int slotIndex = 0; slotIndex < tm.getActiveModemCount(); slotIndex++) { + tm.resetIms(slotIndex); + } + } else { + // Reset IMS for the slot specified by the sucriptionId. + final int slotIndex = SubscriptionManager.getSlotIndex(subId); + tm.resetIms(slotIndex); + } + }); + return this; + } + /** * Construct a Runnable containing all operations appended. * @return Runnable diff --git a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt index 4e41038f068..bf954753922 100644 --- a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt +++ b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt @@ -29,8 +29,13 @@ import kotlinx.coroutines.flow.combine /** * Preference controller for "MMS messages" */ -class MmsMessagePreferenceController(context: Context, key: String) : - TelephonyTogglePreferenceController(context, key) { +class MmsMessagePreferenceController @JvmOverloads constructor( + context: Context, + key: String, + private val getDefaultDataSubId: () -> Int = { + SubscriptionManager.getDefaultDataSubscriptionId() + }, +) : TelephonyTogglePreferenceController(context, key) { private lateinit var telephonyManager: TelephonyManager @@ -46,10 +51,17 @@ class MmsMessagePreferenceController(context: Context, key: String) : if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && !telephonyManager.isDataEnabled && telephonyManager.isApnMetered(ApnSetting.TYPE_MMS) && - !telephonyManager.isMobileDataPolicyEnabled( + !isFallbackDataEnabled() + ) AVAILABLE else CONDITIONALLY_UNAVAILABLE + + private fun isFallbackDataEnabled(): Boolean { + val defaultDataSubId = getDefaultDataSubId() + return defaultDataSubId != mSubId && + telephonyManager.createForSubscriptionId(defaultDataSubId).isDataEnabled && + telephonyManager.isMobileDataPolicyEnabled( TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH ) - ) AVAILABLE else CONDITIONALLY_UNAVAILABLE + } override fun displayPreference(screen: PreferenceScreen) { super.displayPreference(screen) @@ -61,7 +73,8 @@ class MmsMessagePreferenceController(context: Context, key: String) : mContext.mobileDataEnabledFlow(mSubId), mContext.subscriptionsChangedFlow(), // Capture isMobileDataPolicyEnabled() changes ) { _, _ -> }.collectLatestWithLifecycle(viewLifecycleOwner) { - preferenceScreen?.let { super.displayPreference(it) } } + preferenceScreen?.let { super.displayPreference(it) } + } } override fun isChecked(): Boolean = telephonyManager.isMobileDataPolicyEnabled( diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java index 76e342e095c..663b4e5d090 100644 --- a/src/com/android/settings/password/ChooseLockGeneric.java +++ b/src/com/android/settings/password/ChooseLockGeneric.java @@ -162,6 +162,7 @@ public class ChooseLockGeneric extends SettingsActivity { private boolean mRequestGatekeeperPasswordHandle = false; private boolean mPasswordConfirmed = false; private boolean mWaitingForConfirmation = false; + private boolean mWaitingForActivityResult = false; private LockscreenCredential mUserPassword; private FingerprintManager mFingerprintManager; private FaceManager mFaceManager; @@ -470,6 +471,7 @@ public class ChooseLockGeneric extends SettingsActivity { public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mWaitingForConfirmation = false; + mWaitingForActivityResult = false; if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) { mPasswordConfirmed = true; mUserPassword = data != null @@ -479,7 +481,6 @@ public class ChooseLockGeneric extends SettingsActivity { } else if (requestCode == CHOOSE_LOCK_REQUEST) { if (resultCode != RESULT_CANCELED) { getActivity().setResult(resultCode, data); - finish(); } else { // If PASSWORD_TYPE_KEY is set, this activity is used as a trampoline to start // the actual password enrollment. If the result is canceled, which means the @@ -487,9 +488,9 @@ public class ChooseLockGeneric extends SettingsActivity { int quality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1); if (quality != -1) { getActivity().setResult(RESULT_CANCELED, data); - finish(); } } + finish(); } else if (requestCode == CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST && resultCode == BiometricEnrollBase.RESULT_FINISHED) { Intent intent = getBiometricEnrollIntent(getActivity()); @@ -821,6 +822,7 @@ public class ChooseLockGeneric extends SettingsActivity { } if (getIntent().getBooleanExtra(EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW, false)) { intent.putExtra(EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW, true); + mWaitingForActivityResult = true; } intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras()); // If the caller requested Gatekeeper Password Handle to be returned, we assume it @@ -871,7 +873,7 @@ public class ChooseLockGeneric extends SettingsActivity { // Otherwise, bugs would be caused. (e.g. b/278488549, b/278530059) final boolean hasCredential = mLockPatternUtils.isSecure(mUserId); if (!getActivity().isChangingConfigurations() - && !mWaitingForConfirmation && hasCredential) { + && !mWaitingForConfirmation && !mWaitingForActivityResult && hasCredential) { getActivity().finish(); } } diff --git a/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt b/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt index 7368750fce5..15cd1bab5f6 100644 --- a/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt +++ b/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt @@ -22,6 +22,7 @@ import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.content.pm.PackageManager.GET_ACTIVITIES +import android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT import android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET import android.os.Build import android.os.Bundle @@ -139,7 +140,9 @@ class UserAspectRatioAppListModel(private val context: Context) recordList: List ): List { val hasSuggested = recordList.any { it.suggested } - val hasOverride = recordList.any { it.userOverride != USER_MIN_ASPECT_RATIO_UNSET } + val hasOverride = recordList.any { + userAspectRatioManager.isAppOverridden(it.app, it.userOverride) + } val options = mutableListOf(SpinnerItem.All) // Add suggested filter first as default if (hasSuggested) options.add(0, SpinnerItem.Suggested) @@ -187,7 +190,9 @@ class UserAspectRatioAppListModel(private val context: Context) ): Flow> = recordListFlow.filterItem( when (SpinnerItem.entries.getOrNull(option)) { SpinnerItem.Suggested -> ({ it.canDisplay && it.suggested }) - SpinnerItem.Overridden -> ({ it.userOverride != USER_MIN_ASPECT_RATIO_UNSET }) + SpinnerItem.Overridden -> ({ + userAspectRatioManager.isAppOverridden(it.app, it.userOverride) + }) else -> ({ it.canDisplay }) } ) @@ -197,7 +202,7 @@ class UserAspectRatioAppListModel(private val context: Context) val summary by remember(record.userOverride) { flow { emit(userAspectRatioManager.getUserMinAspectRatioEntry(record.userOverride, - record.app.packageName)) + record.app.packageName, record.app.userId)) }.flowOn(Dispatchers.IO) }.collectAsStateWithLifecycle(initialValue = stringResource(R.string.summary_placeholder)) return { summary } diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java index 03f7887b9d0..ded9bcc96e3 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java @@ -31,6 +31,7 @@ import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; +import com.android.settingslib.search.SearchIndexableRaw; import org.junit.Before; import org.junit.Rule; @@ -42,6 +43,9 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; +import java.util.ArrayList; +import java.util.List; + /** Tests for {@link AccessibilityButtonPreferenceController}. */ @RunWith(RobolectricTestRunner.class) public class AccessibilityButtonPreferenceControllerTest { @@ -88,4 +92,36 @@ public class AccessibilityButtonPreferenceControllerTest { assertThat(mPreference.getTitle()).isEqualTo( mContext.getText(R.string.accessibility_button_title)); } + + @Test + public void updateDynamicRawDataToIndex_navigationGestureEnabled_setCorrectIndex() { + when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode)) + .thenReturn(NAV_BAR_MODE_GESTURAL); + List rawDataList = new ArrayList<>(); + + mController.updateDynamicRawDataToIndex(rawDataList); + + assertThat(rawDataList).hasSize(1); + SearchIndexableRaw raw = rawDataList.get(0); + assertThat(raw.title).isEqualTo( + mResources.getString(R.string.accessibility_button_gesture_title)); + assertThat(raw.screenTitle).isEqualTo( + mResources.getString(R.string.accessibility_shortcuts_settings_title)); + } + + @Test + public void updateDynamicRawDataToIndex_navigationGestureDisabled_setCorrectIndex() { + when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode)) + .thenReturn(NAV_BAR_MODE_2BUTTON); + List rawDataList = new ArrayList<>(); + + mController.updateDynamicRawDataToIndex(rawDataList); + + assertThat(rawDataList).hasSize(1); + SearchIndexableRaw raw = rawDataList.get(0); + assertThat(raw.title).isEqualTo( + mResources.getString(R.string.accessibility_button_title)); + assertThat(raw.screenTitle).isEqualTo( + mResources.getString(R.string.accessibility_shortcuts_settings_title)); + } } diff --git a/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java index b615163fbc7..f3b105bc3d6 100644 --- a/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java @@ -16,12 +16,21 @@ package com.android.settings.applications.appcompat; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET; + +import static com.android.settings.applications.AppInfoBase.ARG_PACKAGE_NAME; import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_3_2; import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_DEFAULT; +import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_FULLSCREEN; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -30,15 +39,20 @@ import static org.mockito.Mockito.when; import android.app.IActivityManager; import android.app.settings.SettingsEnums; import android.content.Context; +import android.os.Bundle; import android.os.RemoteException; +import androidx.fragment.app.testing.EmptyFragmentActivity; import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.rules.ActivityScenarioRule; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowActivityManager; +import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; @@ -51,9 +65,13 @@ import org.robolectric.annotation.Config; * To run test: atest SettingsRoboTests:UserAspectRatioDetailsTest */ @RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowActivityManager.class}) +@Config(shadows = {ShadowActivityManager.class, ShadowFragment.class}) public class UserAspectRatioDetailsTest { + @Rule + public ActivityScenarioRule rule = + new ActivityScenarioRule<>(EmptyFragmentActivity.class); + @Mock private UserAspectRatioManager mUserAspectRatioManager; @Mock @@ -72,6 +90,8 @@ public class UserAspectRatioDetailsTest { mFragment = spy(new UserAspectRatioDetails()); when(mFragment.getContext()).thenReturn(mContext); when(mFragment.getAspectRatioManager()).thenReturn(mUserAspectRatioManager); + when(mUserAspectRatioManager.isOverrideToFullscreenEnabled(anyString(), anyInt())) + .thenReturn(false); ShadowActivityManager.setService(mAm); mRadioButtonPref = new RadioWithImagePreference(mContext); final FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest(); @@ -80,6 +100,8 @@ public class UserAspectRatioDetailsTest { @Test public void onRadioButtonClicked_prefChange_shouldStopActivity() throws RemoteException { + doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mFragment) + .getSelectedUserMinAspectRatio(anyString()); // Default was already selected mRadioButtonPref.setKey(KEY_PREF_DEFAULT); mFragment.onRadioButtonClicked(mRadioButtonPref); @@ -92,6 +114,8 @@ public class UserAspectRatioDetailsTest { @Test public void onRadioButtonClicked_prefChange_shouldSetAspectRatio() throws RemoteException { + doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mFragment) + .getSelectedUserMinAspectRatio(anyString()); // Default was already selected mRadioButtonPref.setKey(KEY_PREF_DEFAULT); mFragment.onRadioButtonClicked(mRadioButtonPref); @@ -105,6 +129,8 @@ public class UserAspectRatioDetailsTest { @Test public void onRadioButtonClicked_prefChange_logMetrics() throws NullPointerException { + doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mFragment) + .getSelectedUserMinAspectRatio(anyString()); // Default was already selected mRadioButtonPref.setKey(KEY_PREF_DEFAULT); mFragment.onRadioButtonClicked(mRadioButtonPref); @@ -129,4 +155,47 @@ public class UserAspectRatioDetailsTest { any(), anyInt()); } + + @Test + public void onButtonClicked_overrideEnabled_fullscreenPreselected() + throws RemoteException { + doReturn(true).when(mUserAspectRatioManager) + .isOverrideToFullscreenEnabled(anyString(), anyInt()); + doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mUserAspectRatioManager) + .getUserMinAspectRatioValue(anyString(), anyInt()); + doReturn(mRadioButtonPref).when(mFragment).findPreference(KEY_PREF_DEFAULT); + doReturn(mRadioButtonPref).when(mFragment).findPreference(KEY_PREF_FULLSCREEN); + doReturn(true).when(mUserAspectRatioManager) + .hasAspectRatioOption(anyInt(), anyString()); + + rule.getScenario().onActivity(a -> doReturn(a).when(mFragment).getActivity()); + final Bundle args = new Bundle(); + args.putString(ARG_PACKAGE_NAME, anyString()); + mFragment.setArguments(args); + mFragment.onCreate(Bundle.EMPTY); + + // Fullscreen should be pre-selected + assertEquals(KEY_PREF_FULLSCREEN, mFragment.mSelectedKey); + assertEquals(USER_MIN_ASPECT_RATIO_FULLSCREEN, + mFragment.getSelectedUserMinAspectRatio(mFragment.mSelectedKey)); + + // Revert to app default, should be set to app default from unset + mRadioButtonPref.setKey(KEY_PREF_DEFAULT); + mFragment.onRadioButtonClicked(mRadioButtonPref); + verify(mUserAspectRatioManager).setUserMinAspectRatio( + any(), anyInt(), anyInt()); + assertEquals(USER_MIN_ASPECT_RATIO_APP_DEFAULT, + mFragment.getSelectedUserMinAspectRatio(mFragment.mSelectedKey)); + assertEquals(KEY_PREF_DEFAULT, mFragment.mSelectedKey); + + // Fullscreen override disabled, should be changed to unset from app default + when(mUserAspectRatioManager.isOverrideToFullscreenEnabled(anyString(), anyInt())) + .thenReturn(false); + mFragment.mKeyToAspectRatioMap.clear(); + mFragment.onCreate(Bundle.EMPTY); + + assertEquals(KEY_PREF_DEFAULT, mFragment.mSelectedKey); + assertEquals(USER_MIN_ASPECT_RATIO_UNSET, + mFragment.getSelectedUserMinAspectRatio(mFragment.mSelectedKey)); + } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java index 49777bc7644..d24a83b9c4a 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java @@ -59,7 +59,6 @@ import org.robolectric.annotation.Config; import java.util.HashSet; import java.util.Set; -@Ignore("b/313014781") @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class}) public class AdvancedBluetoothDetailsHeaderControllerTest { @@ -386,6 +385,9 @@ public class AdvancedBluetoothDetailsHeaderControllerTest { .thenReturn("true".getBytes()); Set cacheBluetoothDevices = new HashSet<>(); when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices); + when(mBluetoothAdapter.addOnMetadataChangedListener( + mBluetoothDevice, mContext.getMainExecutor(), mController.mMetadataListener)) + .thenReturn(true); mController.onStart(); diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java index ca1ab542c11..e7e0b921ad7 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java @@ -304,6 +304,16 @@ public class ChooseLockGenericTest { assertThat(mActivity.isFinishing()).isTrue(); } + @Test + public void onActivityResult_requestcode102_resultCancel_shouldFinish() { + initActivity(null); + + mFragment.onActivityResult(ChooseLockGenericFragment.CHOOSE_LOCK_REQUEST, + Activity.RESULT_CANCELED, null /* data */); + + assertThat(mActivity.isFinishing()).isTrue(); + } + @Test public void onActivityResult_requestcode103_shouldFinish() { initActivity(null); diff --git a/tests/spa_unit/AndroidManifest.xml b/tests/spa_unit/AndroidManifest.xml index 5a7f5659ce6..51ac1b740e9 100644 --- a/tests/spa_unit/AndroidManifest.xml +++ b/tests/spa_unit/AndroidManifest.xml @@ -22,6 +22,8 @@ + + { + on { isApnMetered(ApnSetting.TYPE_MMS) } doReturn true + } + + private val mockTelephonyManager2: TelephonyManager = mock { + on { createForSubscriptionId(SUB_1_ID) } doReturn mockTelephonyManager1 + on { isApnMetered(ApnSetting.TYPE_MMS) } doReturn true + } + private val mockTelephonyManager: TelephonyManager = mock { - on { createForSubscriptionId(any()) } doReturn mock + on { createForSubscriptionId(SUB_1_ID) } doReturn mockTelephonyManager1 + on { createForSubscriptionId(SUB_2_ID) } doReturn mockTelephonyManager2 + on { createForSubscriptionId(INVALID_SUBSCRIPTION_ID) } doReturn mock } private var context: Context = spy(ApplicationProvider.getApplicationContext()) { on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager } - private val controller = MmsMessagePreferenceController(context, KEY).apply { - init(SUB_ID) - } + private var defaultDataSubId = SUB_1_ID + + private val controller = MmsMessagePreferenceController( + context = context, + key = KEY, + getDefaultDataSubId = { defaultDataSubId }, + ).apply { init(SUB_2_ID) } @Test - fun getAvailabilityStatus_invalidSubscription_returnUnavailable() { + fun getAvailabilityStatus_invalidSubscription_unavailable() { controller.init(INVALID_SUBSCRIPTION_ID) val availabilityStatus = controller.getAvailabilityStatus(INVALID_SUBSCRIPTION_ID) @@ -58,56 +72,92 @@ class MmsMessagePreferenceControllerTest { } @Test - fun getAvailabilityStatus_mobileDataOn_returnUnavailable() { - mockTelephonyManager.stub { + fun getAvailabilityStatus_mobileDataOn_unavailable() { + mockTelephonyManager2.stub { on { isDataEnabled } doReturn true } - val availabilityStatus = controller.getAvailabilityStatus(SUB_ID) + val availabilityStatus = controller.getAvailabilityStatus(SUB_2_ID) assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE) } @Test - fun getAvailabilityStatus_meteredOff_returnUnavailable() { - mockTelephonyManager.stub { + fun getAvailabilityStatus_meteredOff_unavailable() { + mockTelephonyManager2.stub { on { isApnMetered(ApnSetting.TYPE_MMS) } doReturn false } - val availabilityStatus = controller.getAvailabilityStatus(SUB_ID) + val availabilityStatus = controller.getAvailabilityStatus(SUB_2_ID) assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE) } @Test - fun getAvailabilityStatus_autoDataSwitch_returnUnavailable() { - mockTelephonyManager.stub { - on { isApnMetered(ApnSetting.TYPE_MMS) } doReturn true + fun getAvailabilityStatus_isDefaultDataAndDataOnAndAutoDataSwitchOn_unavailable() { + defaultDataSubId = SUB_2_ID + mockTelephonyManager2.stub { + on { isDataEnabled } doReturn true on { isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH) } doReturn true } - val availabilityStatus = controller.getAvailabilityStatus(SUB_ID) + val availabilityStatus = controller.getAvailabilityStatus(SUB_2_ID) assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE) } @Test - fun getAvailabilityStatus_mobileDataOffWithValidSubId_returnAvailable() { - mockTelephonyManager.stub { + fun getAvailabilityStatus_isDefaultDataAndDataOffAndAutoDataSwitchOn_available() { + defaultDataSubId = SUB_2_ID + mockTelephonyManager2.stub { on { isDataEnabled } doReturn false - on { isApnMetered(ApnSetting.TYPE_MMS) } doReturn true + on { + isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH) + } doReturn true } - val availabilityStatus = controller.getAvailabilityStatus(SUB_ID) + val availabilityStatus = controller.getAvailabilityStatus(SUB_2_ID) + + assertThat(availabilityStatus).isEqualTo(AVAILABLE) + } + + @Test + fun getAvailabilityStatus_defaultDataOnAndAutoDataSwitchOn_unavailable() { + mockTelephonyManager1.stub { + on { isDataEnabled } doReturn true + } + mockTelephonyManager2.stub { + on { + isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH) + } doReturn true + } + + val availabilityStatus = controller.getAvailabilityStatus(SUB_2_ID) + + assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE) + } + + @Test + fun getAvailabilityStatus_defaultDataOffAndAutoDataSwitchOn_available() { + mockTelephonyManager1.stub { + on { isDataEnabled } doReturn false + } + mockTelephonyManager2.stub { + on { + isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH) + } doReturn true + } + + val availabilityStatus = controller.getAvailabilityStatus(SUB_2_ID) assertThat(availabilityStatus).isEqualTo(AVAILABLE) } @Test fun isChecked_whenMmsNotAlwaysAllowed_returnFalse() { - mockTelephonyManager.stub { + mockTelephonyManager2.stub { on { isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED) } doReturn false @@ -120,7 +170,7 @@ class MmsMessagePreferenceControllerTest { @Test fun isChecked_whenMmsAlwaysAllowed_returnTrue() { - mockTelephonyManager.stub { + mockTelephonyManager2.stub { on { isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED) } doReturn true @@ -135,7 +185,7 @@ class MmsMessagePreferenceControllerTest { fun setChecked_setTrue_setDataIntoSubscriptionManager() { controller.setChecked(true) - verify(mockTelephonyManager).setMobileDataPolicyEnabled( + verify(mockTelephonyManager2).setMobileDataPolicyEnabled( TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, true ) } @@ -144,13 +194,14 @@ class MmsMessagePreferenceControllerTest { fun setChecked_setFalse_setDataIntoSubscriptionManager() { controller.setChecked(false) - verify(mockTelephonyManager).setMobileDataPolicyEnabled( + verify(mockTelephonyManager2).setMobileDataPolicyEnabled( TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, false ) } private companion object { const val KEY = "mms_message" - const val SUB_ID = 2 + const val SUB_1_ID = 1 + const val SUB_2_ID = 2 } } diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppPreferenceTest.kt index dd5b929ea3c..15fe091ef43 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppPreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppPreferenceTest.kt @@ -22,6 +22,8 @@ import android.content.pm.LauncherActivityInfo import android.content.pm.LauncherApps import android.content.pm.PackageManager import android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER +import android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE +import android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE import android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalContext @@ -96,6 +98,8 @@ class UserAspectRatioAppPreferenceTest { whenever(launcherApps.getActivityList(anyString(), any())).thenReturn(launcherActivities) // True is ignored but need this here or getBoolean will complain null object mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, true) + mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE, true) + mockProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, true) } @After diff --git a/tests/uitests/src/com/android/settings/ui/MemorySettingsTest.kt b/tests/uitests/src/com/android/settings/ui/MemorySettingsTest.kt new file mode 100644 index 00000000000..312e2c62bf2 --- /dev/null +++ b/tests/uitests/src/com/android/settings/ui/MemorySettingsTest.kt @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.ui + +import android.os.Flags +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.provider.Settings +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiDevice +import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts +import com.android.settings.ui.testutils.SettingsTestUtils.clickObject +import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +@SmallTest +class MemorySettingsTest { + private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Before + fun setUp() { + device.startMainActivityFromHomeScreen(Settings.ACTION_DEVICE_INFO_SETTINGS) + device.assertHasTexts(listOf(BUILD_NUMBER)) + repeat(7) { // Enable development mode + device.clickObject(By.text(BUILD_NUMBER)) + } + device.startMainActivityFromHomeScreen(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS) + device.clickObject(By.text(MEMORY_PAGE)) + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_REMOVE_APP_PROFILER_PSS_COLLECTION) + fun memoryPageIfPssFlagDisabled() { + device.assertHasTexts(ON_SCREEN_TEXTS_DEFAULT) + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_REMOVE_APP_PROFILER_PSS_COLLECTION) + fun memoryPageIfPssFlagEnabled() { + device.assertHasTexts(ON_SCREEN_TEXTS_PSS_PROFILING_DISABLED) + } + + private companion object { + private const val BUILD_NUMBER = "Build number" + private const val MEMORY_PAGE = "Memory" + val ON_SCREEN_TEXTS_DEFAULT = listOf( + "Performance", + "Total memory", + "Average used (%)", + "Free", + ) + val ON_SCREEN_TEXTS_PSS_PROFILING_DISABLED = listOf( + "Enable memory usage profiling", + ) + } +} diff --git a/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java b/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java index 3783b8a945a..342212afc7b 100644 --- a/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java +++ b/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java @@ -19,15 +19,19 @@ package com.android.settings.applications.appcompat; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET; +import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE; import static com.android.settings.applications.appcompat.UserAspectRatioManager.KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN; import static com.android.settings.applications.appcompat.UserAspectRatioManager.KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS; +import static com.android.window.flags.Flags.FLAG_USER_MIN_ASPECT_RATIO_APP_DEFAULT; import static com.google.common.truth.Truth.assertThat; @@ -44,12 +48,16 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.res.Resources; +import android.os.RemoteException; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.DeviceConfig; +import androidx.annotation.NonNull; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -58,6 +66,7 @@ import com.android.settings.testutils.ResourcesUtils; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,30 +77,36 @@ import java.util.List; */ @RunWith(AndroidJUnit4.class) public class UserAspectRatioManagerTest { - + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); + private final String mPackageName = "com.test.mypackage"; private Context mContext; private Resources mResources; - private UserAspectRatioManager mUtils; + private FakeUserAspectRatioManager mUtils; private String mOriginalSettingsFlag; private String mOriginalFullscreenFlag; - private String mPackageName = "com.test.mypackage"; - private LauncherApps mLauncherApps; + private IPackageManager mIPm; + private PackageManager mPm; private List mLauncherActivities; @Before - public void setUp() { + public void setUp() throws RemoteException, PackageManager.NameNotFoundException { mContext = spy(ApplicationProvider.getApplicationContext()); mResources = mock(Resources.class); - mLauncherApps = mock(LauncherApps.class); + final LauncherApps launcherApps = mock(LauncherApps.class); mLauncherActivities = mock(List.class); + mIPm = mock(IPackageManager.class); + mPm = mock(PackageManager.class); + when(mContext.getPackageManager()).thenReturn(mPm); when(mContext.getResources()).thenReturn(mResources); - when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps); + when(mContext.getSystemService(LauncherApps.class)).thenReturn(launcherApps); enableAllDefaultAspectRatioOptions(); + mSetFlagsRule.disableFlags(FLAG_USER_MIN_ASPECT_RATIO_APP_DEFAULT); - mUtils = new UserAspectRatioManager(mContext); + mUtils = new FakeUserAspectRatioManager(mContext, mIPm); - doReturn(mLauncherActivities).when(mLauncherApps).getActivityList(anyString(), any()); + doReturn(mLauncherActivities).when(launcherApps).getActivityList(anyString(), any()); mOriginalSettingsFlag = DeviceConfig.getProperty( DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS); @@ -102,6 +117,10 @@ public class UserAspectRatioManagerTest { DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN); setAspectRatioFullscreenBuildTimeFlagEnabled(true); setAspectRatioFullscreenDeviceConfigEnabled("true" /* enabled */, false /* makeDefault */); + + mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE, true); + mockProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, true); + mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, true); } @After @@ -114,13 +133,13 @@ public class UserAspectRatioManagerTest { @Test public void testCanDisplayAspectRatioUi() { final ApplicationInfo canDisplay = new ApplicationInfo(); - canDisplay.packageName = "com.app.candisplay"; + canDisplay.packageName = mPackageName; doReturn(false).when(mLauncherActivities).isEmpty(); assertTrue(mUtils.canDisplayAspectRatioUi(canDisplay)); final ApplicationInfo noLauncherEntry = new ApplicationInfo(); - noLauncherEntry.packageName = "com.app.nolauncherentry"; + noLauncherEntry.packageName = mPackageName; doReturn(true).when(mLauncherActivities).isEmpty(); assertFalse(mUtils.canDisplayAspectRatioUi(noLauncherEntry)); @@ -221,36 +240,40 @@ public class UserAspectRatioManagerTest { mPackageName)); } + private String getUserMinAspectRatioEntry(int aspectRatio, String packageName) { + return mUtils.getUserMinAspectRatioEntry(aspectRatio, packageName, mContext.getUserId()); + } + @Test public void testGetUserMinAspectRatioEntry() { final Context context = ApplicationProvider.getApplicationContext(); // R.string.user_aspect_ratio_app_default final String appDefault = ResourcesUtils.getResourcesString(context, "user_aspect_ratio_app_default"); - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName)) + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName)) .isEqualTo(appDefault); // should always return default if value does not correspond to anything - assertThat(mUtils.getUserMinAspectRatioEntry(-1, mPackageName)) + assertThat(getUserMinAspectRatioEntry(-1, mPackageName)) .isEqualTo(appDefault); // R.string.user_aspect_ratio_half_screen - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN, + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN, mPackageName)).isEqualTo(ResourcesUtils.getResourcesString(context, "user_aspect_ratio_half_screen")); // R.string.user_aspect_ratio_display_size - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_DISPLAY_SIZE, + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_DISPLAY_SIZE, mPackageName)).isEqualTo(ResourcesUtils.getResourcesString(context, "user_aspect_ratio_device_size")); // R.string.user_aspect_ratio_16_9 - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_16_9, mPackageName)) + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_16_9, mPackageName)) .isEqualTo(ResourcesUtils.getResourcesString(context, "user_aspect_ratio_16_9")); // R.string.user_aspect_ratio_4_3 - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_4_3, mPackageName)) + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_4_3, mPackageName)) .isEqualTo(ResourcesUtils.getResourcesString(context, "user_aspect_ratio_4_3")); // R.string.user_aspect_ratio_3_2 - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_3_2, mPackageName)) + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_3_2, mPackageName)) .isEqualTo(ResourcesUtils.getResourcesString(context, "user_aspect_ratio_3_2")); // R.string.user_aspect_ratio_fullscreen - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN, + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN, mPackageName)).isEqualTo(ResourcesUtils.getResourcesString(context, "user_aspect_ratio_fullscreen")); } @@ -258,7 +281,7 @@ public class UserAspectRatioManagerTest { @Test public void testGetUserMinAspectRatioEntry_fullscreenDisabled_shouldReturnDefault() { setAspectRatioFullscreenBuildTimeFlagEnabled(false); - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN, + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN, mPackageName)).isEqualTo(ResourcesUtils.getResourcesString( ApplicationProvider.getApplicationContext(), "user_aspect_ratio_app_default")); @@ -270,9 +293,9 @@ public class UserAspectRatioManagerTest { when(mResources.getIntArray(anyInt())).thenReturn(new int[] {USER_MIN_ASPECT_RATIO_UNSET}); when(mResources.getStringArray(anyInt())).thenReturn(new String[] {newOptionName}); - mUtils = new UserAspectRatioManager(mContext); + mUtils = new FakeUserAspectRatioManager(mContext, mIPm); - assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName)) + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName)) .isEqualTo(newOptionName); } @@ -282,7 +305,7 @@ public class UserAspectRatioManagerTest { when(mResources.getIntArray(anyInt())).thenReturn(new int[] {USER_MIN_ASPECT_RATIO_4_3}); when(mResources.getStringArray(anyInt())).thenReturn(new String[] {"4:3"}); - assertThrows(RuntimeException.class, () -> new UserAspectRatioManager(mContext)); + assertThrows(RuntimeException.class, () -> new FakeUserAspectRatioManager(mContext, mIPm)); } @Test @@ -292,7 +315,88 @@ public class UserAspectRatioManagerTest { USER_MIN_ASPECT_RATIO_4_3}); when(mResources.getStringArray(anyInt())).thenReturn(new String[] {"4:3"}); - assertThrows(RuntimeException.class, () -> new UserAspectRatioManager(mContext)); + assertThrows(RuntimeException.class, () -> new FakeUserAspectRatioManager(mContext, mIPm)); + } + + @Test + public void testGetUserMinAspectRatioMapping_appDefaultFlagEnabled() { + // Flag is disabled by default, app default not loaded + assertFalse(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_APP_DEFAULT, mPackageName)); + + mSetFlagsRule.enableFlags(FLAG_USER_MIN_ASPECT_RATIO_APP_DEFAULT); + mUtils = new FakeUserAspectRatioManager(mContext, mIPm); + + assertTrue(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_APP_DEFAULT, mPackageName)); + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_APP_DEFAULT, mPackageName)) + .isEqualTo(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName)); + } + + @Test + public void testGetUserMinAspectRatioEntry_enabledFullscreenOverride_returnsFullscreen() { + setIsOverrideToFullscreenEnabled(true); + // Fullscreen option is pre-selected + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName)) + .isEqualTo(ResourcesUtils.getResourcesString( + ApplicationProvider.getApplicationContext(), + "user_aspect_ratio_fullscreen")); + + // App default exists + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_APP_DEFAULT, mPackageName)) + .isEqualTo(ResourcesUtils.getResourcesString( + ApplicationProvider.getApplicationContext(), + "user_aspect_ratio_app_default")); + } + + @Test + public void testGetUserMinAspectRatioEntry_disabledFullscreenOverride_returnsUnchanged() { + setIsOverrideToFullscreenEnabled(false); + // Fullscreen option is not pre-selected + assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName)) + .isEqualTo(ResourcesUtils.getResourcesString( + ApplicationProvider.getApplicationContext(), + "user_aspect_ratio_app_default")); + } + + @Test + public void testIsOverrideToFullscreenEnabled_returnsTrue() + throws PackageManager.NameNotFoundException { + setIsOverrideToFullscreenEnabled(true); + assertTrue(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId())); + + mockProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, true); + assertTrue(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId())); + } + + @Test + public void testIsOverrideToFullscreenEnabled_optOut_returnsFalse() + throws PackageManager.NameNotFoundException { + setIsOverrideToFullscreenEnabled(true); + mockProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, false); + assertFalse(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId())); + } + + @Test + public void testIsOverrideToFullscreenEnabled_flagDisabled_returnsFalse() { + mUtils.setFullscreenCompatChange(true); + assertFalse(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId())); + } + + @Test + public void testIsOverrideToFullscreenEnabled_optionDisabled_returnsFalse() { + mUtils.setFullscreenCompatChange(true); + when(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN, mPackageName)) + .thenReturn(false); + assertFalse(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId())); + } + + private void setIsOverrideToFullscreenEnabled(boolean enabled) { + if (enabled) { + mSetFlagsRule.enableFlags(FLAG_USER_MIN_ASPECT_RATIO_APP_DEFAULT); + mUtils = new FakeUserAspectRatioManager(mContext, mIPm); + } + mUtils.setFullscreenCompatChange(enabled); + when(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN, mPackageName)) + .thenReturn(enabled); } private void enableAllDefaultAspectRatioOptions() { @@ -328,9 +432,7 @@ public class UserAspectRatioManagerTest { throws PackageManager.NameNotFoundException { PackageManager.Property prop = new PackageManager.Property( propertyName, value, mPackageName, "" /* className */); - PackageManager pm = mock(PackageManager.class); - when(mContext.getPackageManager()).thenReturn(pm); - when(pm.getProperty(propertyName, mPackageName)).thenReturn(prop); + when(mPm.getProperty(propertyName, mPackageName)).thenReturn(prop); } private void setAspectRatioSettingsBuildTimeFlagEnabled(boolean enabled) { @@ -352,4 +454,21 @@ public class UserAspectRatioManagerTest { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN, enabled, makeDefault); } + + private static class FakeUserAspectRatioManager extends UserAspectRatioManager { + private boolean mFullscreenCompatChange = false; + + private FakeUserAspectRatioManager(@NonNull Context context, IPackageManager pm) { + super(context, pm); + } + + @Override + boolean isFullscreenCompatChangeEnabled(String pkgName, int userId) { + return mFullscreenCompatChange; + } + + void setFullscreenCompatChange(boolean enabled) { + mFullscreenCompatChange = enabled; + } + } } diff --git a/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java b/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java index 6f5440ba5a7..41b6b27471b 100644 --- a/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java +++ b/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java @@ -16,12 +16,12 @@ package com.android.settings.network; -import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.content.Context; import android.net.ConnectivityManager; @@ -34,6 +34,8 @@ import android.telephony.TelephonyManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.android.settings.ResetNetworkRequest; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -129,4 +131,44 @@ public class ResetNetworkOperationBuilderTest { verify(mTelephonyManager).resetSettings(); verify(mNetworkPolicyManager).factoryReset(imsi); } + + @Test + public void resetIms_performReset_whenBuildAndRun_withSingleValidSubId() { + final int subId = 1; + doReturn(mTelephonyManager).when(mTelephonyManager) + .createForSubscriptionId(anyInt()); + doReturn(mTelephonyManager).when(mContext) + .getSystemService(Context.TELEPHONY_SERVICE); + + mBuilder.resetIms(subId).build().run(); + + verify(mTelephonyManager).resetIms(anyInt()); + } + + @Test + public void resetIms_performReset_whenBuildAndRun_withInvalidSubId() { + final int subId = ResetNetworkRequest.INVALID_SUBSCRIPTION_ID; + doReturn(mTelephonyManager).when(mTelephonyManager) + .createForSubscriptionId(anyInt()); + doReturn(mTelephonyManager).when(mContext) + .getSystemService(Context.TELEPHONY_SERVICE); + + mBuilder.resetIms(subId).build().run(); + + verify(mTelephonyManager, never()).resetIms(anyInt()); + } + + @Test + public void resetIms_performReset_whenBuildAndRun_withAllValidSubId() { + final int subId = ResetNetworkRequest.ALL_SUBSCRIPTION_ID; + doReturn(mTelephonyManager).when(mTelephonyManager) + .createForSubscriptionId(anyInt()); + doReturn(mTelephonyManager).when(mContext) + .getSystemService(Context.TELEPHONY_SERVICE); + doReturn(2).when(mTelephonyManager).getActiveModemCount(); + + mBuilder.resetIms(subId).build().run(); + + verify(mTelephonyManager, times(2)).resetIms(anyInt()); + } }