diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml index 4f0d8049c6c..f0aafe12dc0 100644 --- a/res/layout/settings_homepage_container.xml +++ b/res/layout/settings_homepage_container.xml @@ -19,7 +19,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/settings_homepage_container" - android:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="match_parent"> diff --git a/res/values/config.xml b/res/values/config.xml index 50eddb528f7..bf78fd7fc98 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -570,7 +570,19 @@ 2 3 - + + + + + + false @@ -596,4 +608,5 @@ false + diff --git a/res/xml/accessibility_system_controls.xml b/res/xml/accessibility_system_controls.xml index 71e11436445..37c4d679022 100644 --- a/res/xml/accessibility_system_controls.xml +++ b/res/xml/accessibility_system_controls.xml @@ -42,9 +42,22 @@ android:title="@string/accessibility_power_button_ends_call_prerefence_title" settings:controller="com.android.settings.accessibility.PowerButtonEndsCallPreferenceController"/> + + + + + diff --git a/res/xml/device_state_auto_rotate_settings.xml b/res/xml/device_state_auto_rotate_settings.xml new file mode 100644 index 00000000000..2ddb4c7d9d5 --- /dev/null +++ b/res/xml/device_state_auto_rotate_settings.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml index 0724eea8255..ba52a301666 100644 --- a/res/xml/display_settings.xml +++ b/res/xml/display_settings.xml @@ -96,12 +96,27 @@ + + + + List useAll(Class clazz) { + return (List) mPreferenceControllers.getOrDefault(clazz, Collections.emptyList()); + } + protected void addPreferenceController(AbstractPreferenceController controller) { if (mPreferenceControllers.get(controller.getClass()) == null) { mPreferenceControllers.put(controller.getClass(), new ArrayList<>()); diff --git a/src/com/android/settings/development/tare/TareFactorController.java b/src/com/android/settings/development/tare/TareFactorController.java index 7e9f3149335..3cabd8d05a4 100644 --- a/src/com/android/settings/development/tare/TareFactorController.java +++ b/src/com/android/settings/development/tare/TareFactorController.java @@ -16,6 +16,10 @@ package com.android.settings.development.tare; +import static android.provider.Settings.Global.TARE_ALARM_MANAGER_CONSTANTS; +import static android.provider.Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS; + +import android.annotation.NonNull; import android.app.tare.EconomyManager; import android.content.ContentResolver; import android.content.Context; @@ -49,11 +53,10 @@ public class TareFactorController { mContentResolver = context.getContentResolver(); mResources = context.getResources(); - mAlarmManagerConstants = Settings.Global - .getString(mContentResolver, Settings.Global.TARE_ALARM_MANAGER_CONSTANTS); - - mJobSchedulerConstants = Settings.Global - .getString(mContentResolver, Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS); + mAlarmManagerConstants = + Settings.Global.getString(mContentResolver, TARE_ALARM_MANAGER_CONSTANTS); + mJobSchedulerConstants = + Settings.Global.getString(mContentResolver, TARE_JOB_SCHEDULER_CONSTANTS); initAlarmManagerMap(); parseAlarmManagerGlobalSettings(); @@ -408,8 +411,7 @@ public class TareFactorController { mJobSchedulerMap.put( EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_low_running), - EconomyManager - .DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE, + EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_min_start), @@ -425,68 +427,50 @@ public class TareFactorController { POLICY_JOB_SCHEDULER)); } - - /** - * Takes a key and factor policy as input and grabs the default value linked to it. - * - * @param key the key of the factor you want to get the default value of - * @param factorPolicy the policy you want the default value of - */ - private int getDefaultValue(String key, int factorPolicy) { - ArrayMap currentMap; - switch (factorPolicy) { - case POLICY_ALARM_MANAGER: - currentMap = mAlarmManagerMap; - break; - case POLICY_JOB_SCHEDULER: - currentMap = mJobSchedulerMap; - break; - default: - throw new IllegalArgumentException("Invalid factor policy given"); - } - return currentMap.get(key).defaultValue; - } - /** * Parses the AM constant from Settings.Global to get to the current value. */ private void parseAlarmManagerGlobalSettings() { - try { - mParser.setString(mAlarmManagerConstants); - } catch (Exception e) { - Slog.e(TAG, "Bad value string constants", e); - } - int size = mParser.size(); - - for (int i = 0; i < size - 1; i++) { - String key = mParser.keyAt(i); - TareFactorData data = mAlarmManagerMap.get(key); - data.currentValue = mParser.getInt(key, getDefaultValue(key, getFactorType(key))); - } + parseSettingsIntoMap(mAlarmManagerConstants, mAlarmManagerMap); } /** * Parses the JS constant from Settings.Global to get to the current value. */ private void parseJobSchedulerGlobalSettings() { - try { - mParser.setString(mJobSchedulerConstants); - } catch (Exception e) { - Slog.e(TAG, "Bad value string constants", e); - } - int size = mParser.size(); + parseSettingsIntoMap(mJobSchedulerConstants, mJobSchedulerMap); + } - for (int i = 0; i < size - 1; i++) { - String key = mParser.keyAt(i); - TareFactorData data = mJobSchedulerMap.get(key); - data.currentValue = mParser.getInt(key, getDefaultValue(key, getFactorType(key))); + private void parseSettingsIntoMap(String constants, ArrayMap map) { + try { + mParser.setString(constants); + } catch (Exception e) { + Slog.e(TAG, "Bad string constants value", e); + } + + for (int i = map.size() - 1; i >= 0; --i) { + final String key = map.keyAt(i); + final TareFactorData data = map.valueAt(i); + data.currentValue = mParser.getInt(key, data.defaultValue); + } + } + + @NonNull + private ArrayMap getMap(int factorPolicy) { + switch (factorPolicy) { + case POLICY_ALARM_MANAGER: + return mAlarmManagerMap; + case POLICY_JOB_SCHEDULER: + return mJobSchedulerMap; + default: + throw new IllegalArgumentException("Invalid factor policy given"); } } /** * Takes a key and factor policy as input and grabs the title linked to it. * - * @param key the key of the factor you want to get the title of + * @param key the key of the factor you want to get the title of * @param factorPolicy the policy you want the title of */ private String getTitle(String key, int factorPolicy) { @@ -507,21 +491,11 @@ public class TareFactorController { /** * Takes a key and factor policy as input and grabs the current value linked to it. * - * @param key the key of the factor you want to get the default value of + * @param key the key of the factor you want to get the default value of * @param factorPolicy the policy you want the current value of */ private int getCurrentValue(String key, int factorPolicy) { - ArrayMap currentMap; - switch (factorPolicy) { - case POLICY_ALARM_MANAGER: - currentMap = mAlarmManagerMap; - break; - case POLICY_JOB_SCHEDULER: - currentMap = mJobSchedulerMap; - break; - default: - throw new IllegalArgumentException("Invalid factor policy given"); - } + final ArrayMap currentMap = getMap(factorPolicy); return currentMap.get(key).currentValue; } @@ -551,18 +525,14 @@ public class TareFactorController { * @param factorPolicy policy being updated */ public void updateValue(String key, int editedValue, int factorPolicy) { - switch (factorPolicy) { - case POLICY_ALARM_MANAGER: - mAlarmManagerMap.get(key).currentValue = editedValue; - rebuildPolicyConstants(factorPolicy); - break; - case POLICY_JOB_SCHEDULER: - mJobSchedulerMap.get(key).currentValue = editedValue; - rebuildPolicyConstants(factorPolicy); - break; - default: - throw new IllegalArgumentException("Invalid factor policy given"); + final ArrayMap map = getMap(factorPolicy); + + final TareFactorData data = map.get(key); + if (data.currentValue == editedValue) { + return; } + data.currentValue = editedValue; + rebuildPolicyConstants(factorPolicy); } /** @@ -574,16 +544,14 @@ public class TareFactorController { private void rebuildPolicyConstants(int factorPolicy) { switch (factorPolicy) { case POLICY_ALARM_MANAGER: - writeConstantsToSettings(mAlarmManagerMap, - Settings.Global.TARE_ALARM_MANAGER_CONSTANTS); + writeConstantsToSettings(mAlarmManagerMap, TARE_ALARM_MANAGER_CONSTANTS); mAlarmManagerConstants = Settings.Global .getString(mContentResolver, Settings.Global .TARE_ALARM_MANAGER_CONSTANTS); break; case POLICY_JOB_SCHEDULER: - writeConstantsToSettings(mJobSchedulerMap, - Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS); + writeConstantsToSettings(mJobSchedulerMap, TARE_JOB_SCHEDULER_CONSTANTS); mJobSchedulerConstants = Settings.Global .getString(mContentResolver, Settings.Global @@ -623,7 +591,7 @@ public class TareFactorController { public TareFactorDialogFragment createDialog(String key) { int policy = getFactorType(key); return new TareFactorDialogFragment(getTitle(key, policy), key, - getCurrentValue(key, policy), policy , this); + getCurrentValue(key, policy), policy, this); } /** diff --git a/src/com/android/settings/development/tare/TareFactorDialogFragment.java b/src/com/android/settings/development/tare/TareFactorDialogFragment.java index ff7f5f9d0a8..8d2f3415651 100644 --- a/src/com/android/settings/development/tare/TareFactorDialogFragment.java +++ b/src/com/android/settings/development/tare/TareFactorDialogFragment.java @@ -16,7 +16,10 @@ package com.android.settings.development.tare; +import android.annotation.NonNull; +import android.app.AlertDialog; import android.app.Dialog; +import android.app.DialogFragment; import android.content.Context; import android.os.Bundle; import android.text.InputType; @@ -25,10 +28,6 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import androidx.fragment.app.DialogFragment; - import com.android.settings.R; import com.android.settings.Utils; diff --git a/src/com/android/settings/development/tare/TareHomePage.java b/src/com/android/settings/development/tare/TareHomePage.java index 38e7ed8d519..cea09540d60 100644 --- a/src/com/android/settings/development/tare/TareHomePage.java +++ b/src/com/android/settings/development/tare/TareHomePage.java @@ -69,11 +69,14 @@ public class TareHomePage extends Activity { } /** Reverts the TARE settings to the original default settings */ - // TODO: Establish default TARE values and make this method revert all settings back to default. public void revertSettings(View v) { Toast.makeText(this, R.string.tare_settings_reverted_toast, Toast.LENGTH_LONG).show(); Settings.Global.putString(getApplicationContext().getContentResolver(), Settings.Global.ENABLE_TARE, null); + Settings.Global.putString(getApplicationContext().getContentResolver(), + Settings.Global.TARE_ALARM_MANAGER_CONSTANTS, null); + Settings.Global.putString(getApplicationContext().getContentResolver(), + Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS, null); setEnabled(Settings.Global.DEFAULT_ENABLE_TARE == SETTING_VALUE_ON); } diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java index 746d2341696..cf31724ad69 100644 --- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java +++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java @@ -47,6 +47,7 @@ import com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchP import com.android.settings.deviceinfo.storage.DiskInitFragment; import com.android.settings.deviceinfo.storage.SecondaryUserController; import com.android.settings.deviceinfo.storage.StorageAsyncLoader; +import com.android.settings.deviceinfo.storage.StorageCacheHelper; import com.android.settings.deviceinfo.storage.StorageEntry; import com.android.settings.deviceinfo.storage.StorageItemPreferenceController; import com.android.settings.deviceinfo.storage.StorageSelectionPreferenceController; @@ -109,6 +110,8 @@ public class StorageDashboardFragment extends DashboardFragment private boolean mIsWorkProfile; private int mUserId; private Preference mFreeUpSpacePreference; + private boolean mIsLoadedFromCache; + private StorageCacheHelper mStorageCacheHelper; private final StorageEventListener mStorageEventListener = new StorageEventListener() { @Override @@ -239,15 +242,27 @@ public class StorageDashboardFragment extends DashboardFragment mPreferenceController.setVolume(null); return; } + + if (mStorageCacheHelper.hasCachedSizeInfo() && mSelectedStorageEntry.isPrivate()) { + StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize(); + mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo()); + mPreferenceController.setUsedSize(cachedData.usedSize); + mPreferenceController.setTotalSize(cachedData.totalSize); + } + if (mSelectedStorageEntry.isPrivate()) { mStorageInfo = null; mAppsResult = null; - maybeSetLoading(isQuotaSupported()); - - // To prevent flicker, sets null volume to hide category preferences. - // onReceivedSizes will setVolume with the volume of selected storage. - mPreferenceController.setVolume(null); - + // Hide the loading spinner if there is cached data. + if (mStorageCacheHelper.hasCachedSizeInfo()) { + //TODO(b/220259287): apply cache mechanism to secondary user + mPreferenceController.onLoadFinished(mAppsResult, mUserId); + } else { + maybeSetLoading(isQuotaSupported()); + // To prevent flicker, sets null volume to hide category preferences. + // onReceivedSizes will setVolume with the volume of selected storage. + mPreferenceController.setVolume(null); + } // Stats data is only available on private volumes. getLoaderManager().restartLoader(STORAGE_JOB_ID, Bundle.EMPTY, this); getLoaderManager() @@ -277,6 +292,16 @@ public class StorageDashboardFragment extends DashboardFragment initializePreference(); initializeOptionsMenu(activity); + + if (mStorageCacheHelper.hasCachedSizeInfo()) { + mIsLoadedFromCache = true; + mStorageEntries.clear(); + mStorageEntries.addAll( + StorageUtils.getAllStorageEntries(getContext(), mStorageManager)); + refreshUi(); + updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); + setSecondaryUsersVisible(true); + } } private void initializePreference() { @@ -291,6 +316,7 @@ public class StorageDashboardFragment extends DashboardFragment mUserManager = context.getSystemService(UserManager.class); mIsWorkProfile = false; mUserId = UserHandle.myUserId(); + mStorageCacheHelper = new StorageCacheHelper(getContext(), mUserId); super.onAttach(context); use(AutomaticStorageManagementSwitchPreferenceController.class).setFragmentManager( @@ -323,9 +349,14 @@ public class StorageDashboardFragment extends DashboardFragment public void onResume() { super.onResume(); - mStorageEntries.clear(); - mStorageEntries.addAll(StorageUtils.getAllStorageEntries(getContext(), mStorageManager)); - refreshUi(); + if (mIsLoadedFromCache) { + mIsLoadedFromCache = false; + } else { + mStorageEntries.clear(); + mStorageEntries.addAll( + StorageUtils.getAllStorageEntries(getContext(), mStorageManager)); + refreshUi(); + } mStorageManager.registerListener(mStorageEventListener); } @@ -333,6 +364,11 @@ public class StorageDashboardFragment extends DashboardFragment public void onPause() { super.onPause(); mStorageManager.unregisterListener(mStorageEventListener); + // Destroy the data loaders to prevent unnecessary data loading when switching back to the + // page. + getLoaderManager().destroyLoader(STORAGE_JOB_ID); + getLoaderManager().destroyLoader(ICON_JOB_ID); + getLoaderManager().destroyLoader(VOLUME_SIZE_JOB_ID); } @Override @@ -359,6 +395,8 @@ public class StorageDashboardFragment extends DashboardFragment mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo()); mPreferenceController.setUsedSize(privateUsedBytes); mPreferenceController.setTotalSize(mStorageInfo.totalBytes); + // Cache total size and used size + mStorageCacheHelper.cacheTotalSizeAndUsedSize(mStorageInfo.totalBytes, privateUsedBytes); for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) { final AbstractPreferenceController controller = mSecondaryUsers.get(i); if (controller instanceof SecondaryUserController) { diff --git a/src/com/android/settings/deviceinfo/StorageItemPreference.java b/src/com/android/settings/deviceinfo/StorageItemPreference.java index 934ff3f603b..d3549d45061 100644 --- a/src/com/android/settings/deviceinfo/StorageItemPreference.java +++ b/src/com/android/settings/deviceinfo/StorageItemPreference.java @@ -66,7 +66,7 @@ public class StorageItemPreference extends Preference { return; mProgressBar.setMax(PROGRESS_MAX); - mProgressBar.setProgress(mProgressPercent); + mProgressBar.setProgress(mProgressPercent, true /* animate */); } @Override diff --git a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java index f87a06a76f0..84cafd40797 100644 --- a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java +++ b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java @@ -183,6 +183,9 @@ public class SecondaryUserController extends AbstractPreferenceController implem @Override public void handleResult(SparseArray stats) { + if (stats == null) { + return; + } final StorageAsyncLoader.StorageResult result = stats.get(getUser().id); if (result != null) { setSize(result.externalStats.totalBytes); diff --git a/src/com/android/settings/deviceinfo/storage/StorageCacheHelper.java b/src/com/android/settings/deviceinfo/storage/StorageCacheHelper.java new file mode 100644 index 00000000000..a868c9f3f6e --- /dev/null +++ b/src/com/android/settings/deviceinfo/storage/StorageCacheHelper.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2022 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.deviceinfo.storage; + +import android.content.Context; +import android.content.SharedPreferences; + +/** + * A utility class to cache and restore the storage size information. + */ +public class StorageCacheHelper { + + private static final String SHARED_PREFERENCE_NAME = "StorageCache"; + private static final String TOTAL_SIZE_KEY = "total_size_key"; + private static final String USED_SIZE_KEY = "used_size_key"; + private static final String IMAGES_SIZE_KEY = "images_size_key"; + private static final String VIDEOS_SIZE_KEY = "videos_size_key"; + private static final String AUDIO_SIZE_KEY = "audio_size_key"; + private static final String APPS_SIZE_KEY = "apps_size_key"; + private static final String GAMES_SIZE_KEY = "games_size_key"; + private static final String DOCUMENTS_AND_OTHER_SIZE_KEY = "documents_and_other_size_key"; + private static final String TRASH_SIZE_KEY = "trash_size_key"; + private static final String SYSTEM_SIZE_KEY = "system_size_key"; + + private final SharedPreferences mSharedPreferences; + + public StorageCacheHelper(Context context, int userId) { + String sharedPrefName = SHARED_PREFERENCE_NAME + userId; + mSharedPreferences = context.getSharedPreferences(sharedPrefName, Context.MODE_PRIVATE); + } + + /** + * Returns true if there's a cached size info. + */ + public boolean hasCachedSizeInfo() { + return mSharedPreferences.getAll().size() > 0; + } + + /** + * Cache the size info + * @param data a data about the file size info. + */ + public void cacheSizeInfo(StorageCache data) { + mSharedPreferences + .edit() + .putLong(IMAGES_SIZE_KEY, data.imagesSize) + .putLong(VIDEOS_SIZE_KEY, data.videosSize) + .putLong(AUDIO_SIZE_KEY, data.audioSize) + .putLong(APPS_SIZE_KEY, data.allAppsExceptGamesSize) + .putLong(GAMES_SIZE_KEY, data.gamesSize) + .putLong(DOCUMENTS_AND_OTHER_SIZE_KEY, data.documentsAndOtherSize) + .putLong(TRASH_SIZE_KEY, data.trashSize) + .putLong(SYSTEM_SIZE_KEY, data.systemSize) + .apply(); + } + + /** + * Cache total size and used size + */ + public void cacheTotalSizeAndUsedSize(long totalSize, long usedSize) { + mSharedPreferences + .edit() + .putLong(TOTAL_SIZE_KEY, totalSize) + .putLong(USED_SIZE_KEY, usedSize) + .apply(); + } + + /** + * Returns a cached data about all file size information. + */ + public StorageCache retrieveCachedSize() { + StorageCache result = new StorageCache(); + result.totalSize = mSharedPreferences.getLong(TOTAL_SIZE_KEY, 0); + result.usedSize = mSharedPreferences.getLong(USED_SIZE_KEY, 0); + result.imagesSize = mSharedPreferences.getLong(IMAGES_SIZE_KEY, 0); + result.videosSize = mSharedPreferences.getLong(VIDEOS_SIZE_KEY, 0); + result.audioSize = mSharedPreferences.getLong(AUDIO_SIZE_KEY, 0); + result.allAppsExceptGamesSize = mSharedPreferences.getLong(APPS_SIZE_KEY, 0); + result.gamesSize = mSharedPreferences.getLong(GAMES_SIZE_KEY, 0); + result.documentsAndOtherSize = mSharedPreferences.getLong(DOCUMENTS_AND_OTHER_SIZE_KEY, 0); + result.trashSize = mSharedPreferences.getLong(TRASH_SIZE_KEY, 0); + result.systemSize = mSharedPreferences.getLong(SYSTEM_SIZE_KEY, 0); + return result; + } + + /** + * All the cached data about the file size information. + */ + public static class StorageCache { + public long totalSize; + public long usedSize; + public long gamesSize; + public long allAppsExceptGamesSize; + public long audioSize; + public long imagesSize; + public long videosSize; + public long documentsAndOtherSize; + public long trashSize; + public long systemSize; + } +} diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java index ee0c9e75435..9813439b235 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java +++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java @@ -34,6 +34,7 @@ import android.util.Log; import android.util.SparseArray; import android.widget.Toast; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.preference.Preference; @@ -135,7 +136,11 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle private boolean mIsWorkProfile; - private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents"; + private StorageCacheHelper mStorageCacheHelper; + // The mIsDocumentsPrefShown being used here is to prevent a flicker problem from displaying + // the Document entry. + private boolean mIsDocumentsPrefShown; + private boolean mIsPreferenceOrderedBySize; public StorageItemPreferenceController(Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) { @@ -148,6 +153,8 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle mIsWorkProfile = isWorkProfile; mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mUserId = getCurrentUserId(); + mIsDocumentsPrefShown = isDocumentsPrefShown(); + mStorageCacheHelper = new StorageCacheHelper(mContext, mUserId); mImagesUri = Uri.parse(context.getResources() .getString(R.string.config_images_storage_category_uri)); @@ -267,14 +274,17 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle // If we don't have a shared volume for our internal storage (or the shared volume isn't // mounted as readable for whatever reason), we should hide the File preference. if (visible) { - final VolumeInfo sharedVolume = mSvp.findEmulatedForPrivate(mVolume); - mDocumentsAndOtherPreference.setVisible(sharedVolume != null - && sharedVolume.isMountedReadable()); + mDocumentsAndOtherPreference.setVisible(mIsDocumentsPrefShown); } else { mDocumentsAndOtherPreference.setVisible(false); } } + private boolean isDocumentsPrefShown() { + VolumeInfo sharedVolume = mSvp.findEmulatedForPrivate(mVolume); + return sharedVolume != null && sharedVolume.isMountedReadable(); + } + private void updatePrivateStorageCategoryPreferencesOrder() { if (mScreen == null || !isValidPrivateVolume()) { return; @@ -360,44 +370,74 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle mTrashPreference = screen.findPreference(TRASH_KEY); } - /** Fragments use it to set storage result and update UI of this controller. */ - public void onLoadFinished(SparseArray result, int userId) { - final StorageAsyncLoader.StorageResult data = result.get(userId); - - mImagesPreference.setStorageSize(data.imagesSize, mTotalSize); - mVideosPreference.setStorageSize(data.videosSize, mTotalSize); - mAudioPreference.setStorageSize(data.audioSize, mTotalSize); - mAppsPreference.setStorageSize(data.allAppsExceptGamesSize, mTotalSize); - mGamesPreference.setStorageSize(data.gamesSize, mTotalSize); - mDocumentsAndOtherPreference.setStorageSize(data.documentsAndOtherSize, mTotalSize); - mTrashPreference.setStorageSize(data.trashSize, mTotalSize); - + /** + * Fragments use it to set storage result and update UI of this controller. + * @param result The StorageResult from StorageAsyncLoader. This allows a nullable result. + * When it's null, the cached storage size info will be used instead. + * @param userId User ID to get the storage size info + */ + public void onLoadFinished(@Nullable SparseArray result, + int userId) { + // Calculate the size info for each category + StorageCacheHelper.StorageCache storageCache = getSizeInfo(result, userId); + // Set size info to each preference + mImagesPreference.setStorageSize(storageCache.imagesSize, mTotalSize); + mVideosPreference.setStorageSize(storageCache.videosSize, mTotalSize); + mAudioPreference.setStorageSize(storageCache.audioSize, mTotalSize); + mAppsPreference.setStorageSize(storageCache.allAppsExceptGamesSize, mTotalSize); + mGamesPreference.setStorageSize(storageCache.gamesSize, mTotalSize); + mDocumentsAndOtherPreference.setStorageSize(storageCache.documentsAndOtherSize, mTotalSize); + mTrashPreference.setStorageSize(storageCache.trashSize, mTotalSize); if (mSystemPreference != null) { - // Everything else that hasn't already been attributed is tracked as - // belonging to system. - long attributedSize = 0; - for (int i = 0; i < result.size(); i++) { - final StorageAsyncLoader.StorageResult otherData = result.valueAt(i); - attributedSize += - otherData.gamesSize - + otherData.audioSize - + otherData.videosSize - + otherData.imagesSize - + otherData.documentsAndOtherSize - + otherData.trashSize - + otherData.allAppsExceptGamesSize; - attributedSize -= otherData.duplicateCodeSize; - } - - final long systemSize = Math.max(DataUnit.GIBIBYTES.toBytes(1), - mUsedBytes - attributedSize); - mSystemPreference.setStorageSize(systemSize, mTotalSize); + mSystemPreference.setStorageSize(storageCache.systemSize, mTotalSize); + } + // Cache the size info + if (result != null) { + mStorageCacheHelper.cacheSizeInfo(storageCache); } - updatePrivateStorageCategoryPreferencesOrder(); + // Sort the preference according to size info in descending order + if (!mIsPreferenceOrderedBySize) { + updatePrivateStorageCategoryPreferencesOrder(); + mIsPreferenceOrderedBySize = true; + } setPrivateStorageCategoryPreferencesVisibility(true); } + private StorageCacheHelper.StorageCache getSizeInfo( + SparseArray result, int userId) { + if (result == null) { + return mStorageCacheHelper.retrieveCachedSize(); + } + StorageAsyncLoader.StorageResult data = result.get(userId); + StorageCacheHelper.StorageCache storageCache = new StorageCacheHelper.StorageCache(); + storageCache.imagesSize = data.imagesSize; + storageCache.videosSize = data.videosSize; + storageCache.audioSize = data.audioSize; + storageCache.allAppsExceptGamesSize = data.allAppsExceptGamesSize; + storageCache.gamesSize = data.gamesSize; + storageCache.documentsAndOtherSize = data.documentsAndOtherSize; + storageCache.trashSize = data.trashSize; + // Everything else that hasn't already been attributed is tracked as + // belonging to system. + long attributedSize = 0; + for (int i = 0; i < result.size(); i++) { + final StorageAsyncLoader.StorageResult otherData = result.valueAt(i); + attributedSize += + otherData.gamesSize + + otherData.audioSize + + otherData.videosSize + + otherData.imagesSize + + otherData.documentsAndOtherSize + + otherData.trashSize + + otherData.allAppsExceptGamesSize; + attributedSize -= otherData.duplicateCodeSize; + } + storageCache.systemSize = Math.max(DataUnit.GIBIBYTES.toBytes(1), + mUsedBytes - attributedSize); + return storageCache; + } + public void setUsedSize(long usedSizeBytes) { mUsedBytes = usedSizeBytes; } diff --git a/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java index 766035307e9..872fa8a462b 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java +++ b/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java @@ -18,6 +18,7 @@ package com.android.settings.deviceinfo.storage; import android.app.usage.StorageStatsManager; import android.content.Context; +import android.os.UserHandle; import android.util.Log; import androidx.annotation.VisibleForTesting; @@ -47,11 +48,13 @@ public class StorageUsageProgressBarPreferenceController extends BasePreferenceC private UsageProgressBarPreference mUsageProgressBarPreference; private StorageEntry mStorageEntry; boolean mIsUpdateStateFromSelectedStorageEntry; + private StorageCacheHelper mStorageCacheHelper; public StorageUsageProgressBarPreferenceController(Context context, String key) { super(context, key); mStorageStatsManager = context.getSystemService(StorageStatsManager.class); + mStorageCacheHelper = new StorageCacheHelper(context, UserHandle.myUserId()); } /** Set StorageEntry to display. */ @@ -71,6 +74,15 @@ public class StorageUsageProgressBarPreferenceController extends BasePreferenceC } private void getStorageStatsAndUpdateUi() { + // Use cached data for both total size and used size. + if (mStorageEntry != null && mStorageEntry.isMounted() && mStorageEntry.isPrivate()) { + StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize(); + mTotalBytes = cachedData.totalSize; + mUsedBytes = cachedData.usedSize; + mIsUpdateStateFromSelectedStorageEntry = true; + updateState(mUsageProgressBarPreference); + } + // Get the latest data from StorageStatsManager. ThreadUtils.postOnBackgroundThread(() -> { try { if (mStorageEntry == null || !mStorageEntry.isMounted()) { diff --git a/src/com/android/settings/display/AutoRotatePreferenceController.java b/src/com/android/settings/display/AutoRotatePreferenceController.java index 5dc228644a9..90423fbea7c 100644 --- a/src/com/android/settings/display/AutoRotatePreferenceController.java +++ b/src/com/android/settings/display/AutoRotatePreferenceController.java @@ -74,6 +74,7 @@ public class AutoRotatePreferenceController extends TogglePreferenceController i @Override public int getAvailabilityStatus() { return RotationPolicy.isRotationLockToggleVisible(mContext) + && !DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } diff --git a/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragment.java b/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragment.java new file mode 100644 index 00000000000..fb6d9f4cab0 --- /dev/null +++ b/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragment.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 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.display; + +import android.app.settings.SettingsEnums; +import android.content.Context; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.search.Indexable; +import com.android.settingslib.search.SearchIndexable; +import com.android.settingslib.search.SearchIndexableRaw; + +import java.util.List; + +/** Fragment that shows all the available device state based auto-rotation preferences. */ +@SearchIndexable +public class DeviceStateAutoRotateDetailsFragment extends DashboardFragment { + + private static final String TAG = "DeviceStateAutoRotateDetailsFragment"; + + @Override + public int getMetricsCategory() { + return SettingsEnums.DISPLAY_AUTO_ROTATE_SETTINGS; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.device_state_auto_rotate_settings; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + DeviceStateAutoRotationHelper.initControllers( + getLifecycle(), + useAll(DeviceStateAutoRotateSettingController.class) + ); + } + + @Override + protected List createPreferenceControllers(Context context) { + return DeviceStateAutoRotationHelper.createPreferenceControllers(context); + } + + @Override + protected String getLogTag() { + return TAG; + } + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.device_state_auto_rotate_settings) { + + @Override + public List getRawDataToIndex(Context context, + boolean enabled) { + return DeviceStateAutoRotationHelper.getRawDataToIndex(context, enabled); + } + }; +} diff --git a/src/com/android/settings/display/DeviceStateAutoRotateOverviewController.java b/src/com/android/settings/display/DeviceStateAutoRotateOverviewController.java new file mode 100644 index 00000000000..5e49bf3e149 --- /dev/null +++ b/src/com/android/settings/display/DeviceStateAutoRotateOverviewController.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 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.display; + +import android.content.Context; +import android.text.TextUtils; + +import com.android.settings.core.BasePreferenceController; + +/** + * The top-level preference controller for device state based auto-rotation settings. + * + * It doesn't do anything on its own besides showing/hiding. The toggling of the settings will + * always be done in the details screen when device state based auto-rotation is enabled. + */ +public class DeviceStateAutoRotateOverviewController extends BasePreferenceController { + + /** Preference key for when it is used in "accessibility_system_controls.xml". */ + private static final String ACCESSIBILITY_PREF_KEY = "device_state_auto_rotate_accessibility"; + + public DeviceStateAutoRotateOverviewController(Context context, String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + return isAvailableInternal() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + private boolean isAvailableInternal() { + return isA11yPage() + ? DeviceStateAutoRotationHelper.isDeviceStateRotationEnabledForA11y(mContext) + : DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext); + } + + private boolean isA11yPage() { + return TextUtils.equals(getPreferenceKey(), ACCESSIBILITY_PREF_KEY); + } +} diff --git a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java new file mode 100644 index 00000000000..c8f6280fe3b --- /dev/null +++ b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2022 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.display; + +import static androidx.lifecycle.Lifecycle.Event.ON_START; +import static androidx.lifecycle.Lifecycle.Event.ON_STOP; + +import android.app.settings.SettingsEnums; +import android.content.Context; + +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; + +import com.android.settings.R; +import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; +import com.android.settingslib.search.SearchIndexableRaw; + +import java.util.List; + +/** Controller for device state based auto rotation preferences. */ +public class DeviceStateAutoRotateSettingController extends TogglePreferenceController implements + LifecycleObserver { + + private SwitchPreference mPreference; + + private final DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager; + private final int mOrder; + private final DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener + mDeviceStateRotationLockSettingsListener = () -> updateState(mPreference); + private final int mDeviceState; + private final String mDeviceStateDescription; + private final MetricsFeatureProvider mMetricsFeatureProvider; + + public DeviceStateAutoRotateSettingController(Context context, int deviceState, + String deviceStateDescription, int order) { + super(context, getPreferenceKeyForDeviceState(deviceState)); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); + mDeviceState = deviceState; + mDeviceStateDescription = deviceStateDescription; + mAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(context); + mOrder = order; + } + + void init(Lifecycle lifecycle) { + lifecycle.addObserver(this); + } + + @OnLifecycleEvent(ON_START) + void onStart() { + mAutoRotateSettingsManager.registerListener(mDeviceStateRotationLockSettingsListener); + } + + @OnLifecycleEvent(ON_STOP) + void onStop() { + mAutoRotateSettingsManager.unregisterListener(mDeviceStateRotationLockSettingsListener); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + mPreference = new SwitchPreference(mContext); + mPreference.setTitle(mDeviceStateDescription); + mPreference.setKey(getPreferenceKey()); + mPreference.setOrder(mOrder); + screen.addPreference(mPreference); + super.displayPreference(screen); + } + + @Override + public int getAvailabilityStatus() { + return DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext) + ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public String getPreferenceKey() { + return getPreferenceKeyForDeviceState(mDeviceState); + } + + private static String getPreferenceKeyForDeviceState(int deviceState) { + return "auto_rotate_device_state_" + deviceState; + } + + @Override + public boolean isChecked() { + return !mAutoRotateSettingsManager.isRotationLocked(mDeviceState); + } + + @Override + public boolean setChecked(boolean isChecked) { + boolean isRotationLocked = !isChecked; + mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK, + isRotationLocked); + mAutoRotateSettingsManager.updateSetting(mDeviceState, isRotationLocked); + return true; + } + + @Override + public void updateRawDataToIndex(List rawData) { + SearchIndexableRaw indexable = new SearchIndexableRaw(mContext); + indexable.key = getPreferenceKey(); + indexable.title = mDeviceStateDescription; + // Maybe pass screen title as param? + indexable.screenTitle = mContext.getString(R.string.accelerometer_title); + rawData.add(indexable); + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_display; + } + + @Override + public boolean isSliceable() { + return true; // Maybe set to false if in accessibility settings screen + } + + @Override + public boolean isPublicSlice() { + return true; + } +} diff --git a/src/com/android/settings/display/DeviceStateAutoRotationHelper.java b/src/com/android/settings/display/DeviceStateAutoRotationHelper.java new file mode 100644 index 00000000000..223ef1aa4fa --- /dev/null +++ b/src/com/android/settings/display/DeviceStateAutoRotationHelper.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2022 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.display; + +import android.content.Context; +import android.util.Log; + +import androidx.lifecycle.Lifecycle; + +import com.android.internal.view.RotationPolicy; +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager.SettableDeviceState; +import com.android.settingslib.search.SearchIndexableRaw; + +import com.google.common.collect.ImmutableList; + +import java.util.ArrayList; +import java.util.List; + +/** + * Helper class with utility methods related to device state auto-rotation that can be used in + * auto-rotation settings fragments and controllers. + */ +public class DeviceStateAutoRotationHelper { + + private static final String TAG = "DeviceStateAutoRotHelpr"; + + static void initControllers(Lifecycle lifecycle, + List controllers) { + for (DeviceStateAutoRotateSettingController controller : controllers) { + controller.init(lifecycle); + } + } + + static ImmutableList createPreferenceControllers( + Context context) { + List settableDeviceStates = DeviceStateRotationLockSettingsManager + .getInstance(context).getSettableDeviceStates(); + int numDeviceStates = settableDeviceStates.size(); + if (numDeviceStates == 0) { + return ImmutableList.of(); + } + String[] deviceStateSettingDescriptions = context.getResources().getStringArray( + R.array.config_settableAutoRotationDeviceStatesDescriptions); + if (numDeviceStates != deviceStateSettingDescriptions.length) { + Log.wtf(TAG, + "Mismatch between number of device states and device states descriptions."); + return ImmutableList.of(); + } + + ImmutableList.Builder controllers = + ImmutableList.builderWithExpectedSize(numDeviceStates); + for (int i = 0; i < numDeviceStates; i++) { + SettableDeviceState settableDeviceState = settableDeviceStates.get(i); + if (!settableDeviceState.isSettable()) { + continue; + } + // Preferences with a lower order will be showed first. Here we go below 0 to make sure + // we are shown before statically declared preferences in XML. + int order = -numDeviceStates + i; + controllers.add(new DeviceStateAutoRotateSettingController( + context, + settableDeviceState.getDeviceState(), + deviceStateSettingDescriptions[i], + order + )); + } + return controllers.build(); + } + + static List getRawDataToIndex( + Context context, boolean enabled) { + // Check what the "enabled" param is for + List controllers = createPreferenceControllers(context); + List rawData = new ArrayList<>(); + for (AbstractPreferenceController controller : controllers) { + ((BasePreferenceController) controller).updateRawDataToIndex(rawData); + } + return rawData; + } + + /** Returns whether the device state based auto-rotation settings are enabled. */ + public static boolean isDeviceStateRotationEnabled(Context context) { + return RotationPolicy.isRotationLockToggleVisible(context) + && DeviceStateRotationLockSettingsManager.isDeviceStateRotationLockEnabled(context); + } + + /** + * Returns whether the device state based auto-rotation settings are enabled for the + * accessibility settings page. + */ + public static boolean isDeviceStateRotationEnabledForA11y(Context context) { + return RotationPolicy.isRotationSupported(context) + && DeviceStateRotationLockSettingsManager.isDeviceStateRotationLockEnabled(context); + } +} diff --git a/src/com/android/settings/display/SmartAutoRotateController.java b/src/com/android/settings/display/SmartAutoRotateController.java index 76a222aac75..d29a64e7d88 100644 --- a/src/com/android/settings/display/SmartAutoRotateController.java +++ b/src/com/android/settings/display/SmartAutoRotateController.java @@ -47,6 +47,7 @@ import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; /** * SmartAutoRotateController controls whether auto rotation is enabled @@ -54,6 +55,8 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class SmartAutoRotateController extends TogglePreferenceController implements Preference.OnPreferenceChangeListener, LifecycleObserver { + protected Preference mPreference; + private final MetricsFeatureProvider mMetricsFeatureProvider; private final SensorPrivacyManager mPrivacyManager; private final PowerManager mPowerManager; @@ -63,7 +66,9 @@ public class SmartAutoRotateController extends TogglePreferenceController implem updateState(mPreference); } }; - protected Preference mPreference; + private final DeviceStateRotationLockSettingsManager mDeviceStateAutoRotateSettingsManager; + private final DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener + mDeviceStateRotationLockSettingsListener = () -> updateState(mPreference); private RotationPolicy.RotationPolicyListener mRotationPolicyListener; public SmartAutoRotateController(Context context, String preferenceKey) { @@ -73,6 +78,8 @@ public class SmartAutoRotateController extends TogglePreferenceController implem mPrivacyManager .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> updateState(mPreference)); mPowerManager = context.getSystemService(PowerManager.class); + mDeviceStateAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance( + context); } public void init(Lifecycle lifecycle) { @@ -89,6 +96,9 @@ public class SmartAutoRotateController extends TogglePreferenceController implem } protected boolean isRotationLocked() { + if (DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext)) { + return mDeviceStateAutoRotateSettingsManager.isRotationLockedForAllStates(); + } return RotationPolicy.isRotationLocked(mContext); } @@ -127,6 +137,8 @@ public class SmartAutoRotateController extends TogglePreferenceController implem }; } RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener); + mDeviceStateAutoRotateSettingsManager.registerListener( + mDeviceStateRotationLockSettingsListener); } @OnLifecycleEvent(ON_STOP) @@ -136,6 +148,8 @@ public class SmartAutoRotateController extends TogglePreferenceController implem RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener); mRotationPolicyListener = null; } + mDeviceStateAutoRotateSettingsManager.unregisterListener( + mDeviceStateRotationLockSettingsListener); } @Override diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java index bd8ee84a2d3..d02e3367692 100644 --- a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java +++ b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java @@ -77,6 +77,7 @@ public class SmartAutoRotatePreferenceController extends TogglePreferenceControl @Override public int getAvailabilityStatus() { return RotationPolicy.isRotationLockToggleVisible(mContext) + && !DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java b/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java index 47373366ebe..9fda03c4d5f 100644 --- a/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java +++ b/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java @@ -34,10 +34,14 @@ import com.android.settings.SettingsActivity; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.widget.SettingsMainSwitchBar; +import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.search.Indexable; import com.android.settingslib.search.SearchIndexable; +import com.android.settingslib.search.SearchIndexableRaw; import com.android.settingslib.widget.FooterPreference; +import java.util.List; + /** * Preference fragment used for auto rotation */ @@ -60,6 +64,15 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment { public void onAttach(Context context) { super.onAttach(context); use(SmartAutoRotateController.class).init(getLifecycle()); + DeviceStateAutoRotationHelper.initControllers( + getLifecycle(), + useAll(DeviceStateAutoRotateSettingController.class) + ); + } + + @Override + protected List createPreferenceControllers(Context context) { + return DeviceStateAutoRotationHelper.createPreferenceControllers(context); } @Override @@ -79,7 +92,9 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment { @VisibleForTesting void createHeader(SettingsActivity activity) { - if (isRotationResolverServiceAvailable(activity)) { + boolean deviceStateRotationEnabled = + DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(activity); + if (isRotationResolverServiceAvailable(activity) && !deviceStateRotationEnabled) { final SettingsMainSwitchBar switchBar = activity.getSwitchBar(); switchBar.setTitle( getContext().getString(R.string.auto_rotate_settings_primary_switch_title)); @@ -127,5 +142,12 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment { } public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(R.xml.auto_rotate_settings); + new BaseSearchIndexProvider(R.xml.auto_rotate_settings) { + + @Override + public List getRawDataToIndex( + Context context, boolean enabled) { + return DeviceStateAutoRotationHelper.getRawDataToIndex(context, enabled); + } + }; } diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index c56d89b1a3a..051a54ad9cc 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -32,12 +32,17 @@ import android.util.ArraySet; import android.util.FeatureFlagUtils; import android.util.Log; import android.view.View; +import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.Toolbar; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; @@ -96,7 +101,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements void onHomepageLoaded(); } - private interface FragmentBuilder { + private interface FragmentBuilder { T build(); } @@ -149,7 +154,9 @@ public class SettingsHomepageActivity extends FragmentActivity implements @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setupEdgeToEdge(); setContentView(R.layout.settings_homepage_container); + mIsEmbeddingActivityEnabled = ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this); mSplitController = SplitController.getInstance(); mIsTwoPane = mSplitController.isActivityEmbedded(this); @@ -224,6 +231,24 @@ public class SettingsHomepageActivity extends FragmentActivity implements } } + private void setupEdgeToEdge() { + WindowCompat.setDecorFitsSystemWindows(getWindow(), false); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content), + (v, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); + // Apply the insets as a margin to the view. Here the system is setting + // only the top dimensions. + ViewGroup.MarginLayoutParams mlp = + (ViewGroup.MarginLayoutParams) v.getLayoutParams(); + mlp.topMargin = insets.top; + v.setLayoutParams(mlp); + + // Return CONSUMED if you don't want the window insets to keep being + // passed down to descendant views. + return WindowInsetsCompat.CONSUMED; + }); + } + private void initSearchBarView() { final Toolbar toolbar = findViewById(R.id.search_action_bar); FeatureFactory.getFactory(this).getSearchFeatureProvider() @@ -265,7 +290,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements // Update status bar color window.setStatusBarColor(color); // Update content background. - findViewById(R.id.settings_homepage_container).setBackgroundColor(color); + findViewById(android.R.id.content).setBackgroundColor(color); } private void showSuggestionFragment(boolean scrollNeeded) { diff --git a/src/com/android/settings/privacy/PrivacyDashboardFragment.java b/src/com/android/settings/privacy/PrivacyDashboardFragment.java index 0638c60c94c..df59bd5f119 100644 --- a/src/com/android/settings/privacy/PrivacyDashboardFragment.java +++ b/src/com/android/settings/privacy/PrivacyDashboardFragment.java @@ -29,7 +29,7 @@ import android.os.Bundle; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.notification.LockScreenNotificationPreferenceController; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -118,7 +118,7 @@ public class PrivacyDashboardFragment extends DashboardFragment { @Override protected boolean isPageSearchEnabled(Context context) { - return !SafetyCenterStatusHolder.get().isEnabled(context); + return !SafetyCenterManagerWrapper.get().isEnabled(context); } }; } diff --git a/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceController.java b/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceController.java index 87daf7fe7ba..b5532394aa2 100644 --- a/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceController.java +++ b/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceController.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.content.Context; import com.android.settings.core.BasePreferenceController; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; /** The preference controller for the top level privacy tile. */ public class TopLevelPrivacyEntryPreferenceController extends BasePreferenceController { @@ -31,7 +31,7 @@ public class TopLevelPrivacyEntryPreferenceController extends BasePreferenceCon @Override public int getAvailabilityStatus() { - if (!SafetyCenterStatusHolder.get().isEnabled(mContext)) { + if (!SafetyCenterManagerWrapper.get().isEnabled(mContext)) { return AVAILABLE; } return CONDITIONALLY_UNAVAILABLE; diff --git a/src/com/android/settings/safetycenter/BiometricsSafetySource.java b/src/com/android/settings/safetycenter/BiometricsSafetySource.java index f37ea0361ae..296ca73daa8 100644 --- a/src/com/android/settings/safetycenter/BiometricsSafetySource.java +++ b/src/com/android/settings/safetycenter/BiometricsSafetySource.java @@ -27,7 +27,7 @@ public final class BiometricsSafetySource { /** Sends biometric safety data to Safety Center. */ public static void sendSafetyData(Context context) { - if (!SafetyCenterStatusHolder.get().isEnabled(context)) { + if (!SafetyCenterManagerWrapper.get().isEnabled(context)) { return; } diff --git a/src/com/android/settings/safetycenter/LockScreenSafetySource.java b/src/com/android/settings/safetycenter/LockScreenSafetySource.java index c9c1cd49a43..f059920aa73 100644 --- a/src/com/android/settings/safetycenter/LockScreenSafetySource.java +++ b/src/com/android/settings/safetycenter/LockScreenSafetySource.java @@ -40,7 +40,7 @@ public final class LockScreenSafetySource { /** Sends lock screen safety data to Safety Center. */ public static void sendSafetyData(Context context, ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils) { - if (!SafetyCenterStatusHolder.get().isEnabled(context)) { + if (!SafetyCenterManagerWrapper.get().isEnabled(context)) { return; } @@ -57,7 +57,7 @@ public final class LockScreenSafetySource { screenLockPreferenceDetailsUtils); final SafetySourceStatus status = new SafetySourceStatus.Builder( - context.getString(R.string.unlock_set_unlock_launch_picker_title_profile), + context.getString(R.string.unlock_set_unlock_launch_picker_title), screenLockPreferenceDetailsUtils.getSummary(UserHandle.myUserId()), screenLockPreferenceDetailsUtils.isLockPatternSecure() ? SafetySourceStatus.STATUS_LEVEL_OK diff --git a/src/com/android/settings/safetycenter/SafetyCenterManagerWrapper.java b/src/com/android/settings/safetycenter/SafetyCenterManagerWrapper.java index 7e47f239f93..e4a1d673c4d 100644 --- a/src/com/android/settings/safetycenter/SafetyCenterManagerWrapper.java +++ b/src/com/android/settings/safetycenter/SafetyCenterManagerWrapper.java @@ -58,4 +58,24 @@ public class SafetyCenterManagerWrapper { return; } } + + /** Returns true is SafetyCenter page is enabled, false otherwise. */ + public boolean isEnabled(Context context) { + if (context == null) { + Log.e(TAG, "Context is null at SafetyCenterManagerWrapper#isEnabled"); + return false; + } + SafetyCenterManager safetyCenterManager = + context.getSystemService(SafetyCenterManager.class); + if (safetyCenterManager == null) { + Log.w(TAG, "System service SAFETY_CENTER_SERVICE (SafetyCenterManager) is null"); + return false; + } + try { + return safetyCenterManager.isSafetyCenterEnabled(); + } catch (RuntimeException e) { + Log.e(TAG, "Calling isSafetyCenterEnabled failed.", e); + return false; + } + } } diff --git a/src/com/android/settings/safetycenter/SafetyCenterStatusHolder.java b/src/com/android/settings/safetycenter/SafetyCenterStatusHolder.java deleted file mode 100644 index 014c600d487..00000000000 --- a/src/com/android/settings/safetycenter/SafetyCenterStatusHolder.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2022 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.safetycenter; - -import android.content.Context; -import android.safetycenter.SafetyCenterManager; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -/** Knows whether safety center is enabled or disabled. */ -public class SafetyCenterStatusHolder { - - private static final String TAG = "SafetyCenterStatusHolder"; - - @VisibleForTesting - public static SafetyCenterStatusHolder sInstance; - - private SafetyCenterStatusHolder() {} - - /** Returns an instance of {@link SafetyCenterStatusHolder}. */ - public static SafetyCenterStatusHolder get() { - if (sInstance == null) { - sInstance = new SafetyCenterStatusHolder(); - } - return sInstance; - } - - /** Returns true is SafetyCenter page is enabled, false otherwise. */ - public boolean isEnabled(Context context) { - if (context == null) { - Log.e(TAG, "Context is null at SafetyCenterStatusHolder#isEnabled"); - return false; - } - SafetyCenterManager safetyCenterManager = - context.getSystemService(SafetyCenterManager.class); - if (safetyCenterManager == null) { - Log.w(TAG, "System service SAFETY_CENTER_SERVICE (SafetyCenterManager) is null"); - return false; - } - try { - return safetyCenterManager.isSafetyCenterEnabled(); - } catch (RuntimeException e) { - Log.e(TAG, "Calling isSafetyCenterEnabled failed.", e); - return false; - } - } -} diff --git a/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java b/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java index 558a8b9f519..a0d18c7d09f 100644 --- a/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java +++ b/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java @@ -36,7 +36,7 @@ public class SafetySourceBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if (!SafetyCenterStatusHolder.get().isEnabled(context)) { + if (!SafetyCenterManagerWrapper.get().isEnabled(context)) { return; } diff --git a/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceController.java b/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceController.java index b00c084e6cb..af9509bf7cc 100644 --- a/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceController.java +++ b/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceController.java @@ -37,7 +37,7 @@ public class TopLevelSafetyCenterEntryPreferenceController extends BasePreferenc @Override public int getAvailabilityStatus() { - if (SafetyCenterStatusHolder.get().isEnabled(mContext)) { + if (SafetyCenterManagerWrapper.get().isEnabled(mContext)) { return AVAILABLE; } return CONDITIONALLY_UNAVAILABLE; diff --git a/src/com/android/settings/security/SecurityAdvancedSettings.java b/src/com/android/settings/security/SecurityAdvancedSettings.java index e5f494507a0..f716064a6ae 100644 --- a/src/com/android/settings/security/SecurityAdvancedSettings.java +++ b/src/com/android/settings/security/SecurityAdvancedSettings.java @@ -34,7 +34,7 @@ import com.android.settings.biometrics.face.FaceProfileStatusPreferenceControlle import com.android.settings.biometrics.fingerprint.FingerprintProfileStatusPreferenceController; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.security.trustagent.TrustAgentListPreferenceController; import com.android.settings.widget.PreferenceCategoryController; @@ -92,7 +92,7 @@ public class SecurityAdvancedSettings extends DashboardFragment { final Context context = getContext(); if (context == null) { return CATEGORY_SECURITY_LEGACY_ADVANCED_SETTINGS; - } else if (SafetyCenterStatusHolder.get().isEnabled(context)) { + } else if (SafetyCenterManagerWrapper.get().isEnabled(context)) { return CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS; } else { final SecuritySettingsFeatureProvider securitySettingsFeatureProvider = diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java index 6bfbf6cc3f3..6aadee6aad5 100644 --- a/src/com/android/settings/security/SecuritySettings.java +++ b/src/com/android/settings/security/SecuritySettings.java @@ -25,7 +25,7 @@ import com.android.settings.biometrics.face.FaceStatusPreferenceController; import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.security.trustagent.TrustAgentListPreferenceController; import com.android.settings.widget.PreferenceCategoryController; @@ -129,7 +129,7 @@ public class SecuritySettings extends DashboardFragment { protected boolean isPageSearchEnabled(Context context) { return !FeatureFactory.getFactory(context).getSecuritySettingsFeatureProvider() .hasAlternativeSecuritySettingsFragment() - && !SafetyCenterStatusHolder.get().isEnabled(context); + && !SafetyCenterManagerWrapper.get().isEnabled(context); } }; } diff --git a/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java b/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java index 11d1dc32da7..3cf40a0e907 100644 --- a/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java +++ b/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java @@ -24,7 +24,7 @@ import androidx.preference.Preference; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.SubSettingLauncher; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; public class TopLevelSecurityEntryPreferenceController extends BasePreferenceController { @@ -38,7 +38,7 @@ public class TopLevelSecurityEntryPreferenceController extends BasePreferenceCon @Override public int getAvailabilityStatus() { - if (!SafetyCenterStatusHolder.get().isEnabled(mContext)) { + if (!SafetyCenterManagerWrapper.get().isEnabled(mContext)) { return AVAILABLE; } return CONDITIONALLY_UNAVAILABLE; diff --git a/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java index ef8f569e4fd..f908b8aee61 100644 --- a/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java @@ -26,6 +26,7 @@ import androidx.preference.SwitchPreference; import com.android.internal.view.RotationPolicy; import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; import com.android.settings.testutils.shadow.ShadowRotationPolicy; import org.junit.Before; @@ -50,7 +51,10 @@ public class LockScreenRotationPreferenceControllerTest { } @Test - @Config(shadows = {ShadowRotationPolicy.class}) + @Config(shadows = { + ShadowRotationPolicy.class, + ShadowDeviceStateRotationLockSettingsManager.class + }) public void getAvailabilityStatus_supportedRotation_shouldReturnAvailable() { ShadowRotationPolicy.setRotationSupported(true /* supported */); @@ -59,8 +63,23 @@ public class LockScreenRotationPreferenceControllerTest { } @Test - @Config(shadows = {ShadowRotationPolicy.class}) - public void getAvailabilityStatus_unsupportedRotation_shouldReturnUnsupportedOnDevice() { + @Config(shadows = { + ShadowRotationPolicy.class, + ShadowDeviceStateRotationLockSettingsManager.class + }) + public void getAvailabilityStatus_deviceStateRotationEnabled_returnsUnsupported() { + ShadowRotationPolicy.setRotationSupported(true /* supported */); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + + @Test + @Config(shadows = { + ShadowRotationPolicy.class, + ShadowDeviceStateRotationLockSettingsManager.class + }) public void getAvailabilityStatus_unsupportedRotation_shouldReturnUnsupportedOnDevice() { ShadowRotationPolicy.setRotationSupported(false /* supported */); assertThat(mController.getAvailabilityStatus()).isEqualTo( diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java index fd1c8ff528b..aa5f980f8d0 100644 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java @@ -143,6 +143,21 @@ public class DashboardFragmentTest { assertThat(controller1).isSameInstanceAs(retrievedController); } + @Test + public void useAll_returnsAllControllersOfType() { + final TestPreferenceController controller1 = new TestPreferenceController(mContext); + final TestPreferenceController controller2 = new TestPreferenceController(mContext); + final SubTestPreferenceController controller3 = new SubTestPreferenceController(mContext); + mTestFragment.addPreferenceController(controller1); + mTestFragment.addPreferenceController(controller2); + mTestFragment.addPreferenceController(controller3); + + final List retrievedControllers = mTestFragment.useAll( + TestPreferenceController.class); + + assertThat(retrievedControllers).containsExactly(controller1, controller2); + } + @Test public void displayTilesAsPreference_shouldAddTilesWithIntent() { when(mFakeFeatureFactory.dashboardFeatureProvider @@ -360,6 +375,13 @@ public class DashboardFragmentTest { } } + public static class SubTestPreferenceController extends TestPreferenceController { + + private SubTestPreferenceController(Context context) { + super(context); + } + } + private static class TestFragment extends DashboardFragment { private final PreferenceManager mPreferenceManager; diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageCacheHelperTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageCacheHelperTest.java new file mode 100644 index 00000000000..1956b09a95d --- /dev/null +++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageCacheHelperTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 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.deviceinfo.storage; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.os.UserHandle; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class StorageCacheHelperTest { + private static final long FAKE_IMAGES_SIZE = 7000L; + private static final long FAKE_VIDEOS_SIZE = 8900L; + private static final long FAKE_AUDIO_SIZE = 3500L; + private static final long FAKE_APPS_SIZE = 4000L; + private static final long FAKE_GAMES_SIZE = 5000L; + private static final long FAKE_DOCS_SIZE = 1500L; + private static final long FAKE_TRASH_SIZE = 500L; + private static final long FAKE_SYSTEM_SIZE = 2300L; + private static final long FAKE_TOTAL_SIZE = 256000L; + private static final long FAKE_USED_SIZE = 50000L; + + private Context mContext; + private StorageCacheHelper mHelper; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mHelper = new StorageCacheHelper(mContext, UserHandle.myUserId()); + } + + @Test + public void hasCachedSizeInfo_noCacheData_shouldReturnFalse() { + assertThat(mHelper.hasCachedSizeInfo()).isFalse(); + } + + @Test + public void hasCachedSizeInfo_hasCacheData_shouldReturnTrue() { + mHelper.cacheSizeInfo(getFakeStorageCache()); + + assertThat(mHelper.hasCachedSizeInfo()).isTrue(); + } + + @Test + public void cacheSizeInfo_shouldSaveToSharedPreference() { + mHelper.cacheSizeInfo(getFakeStorageCache()); + + StorageCacheHelper.StorageCache storageCache = mHelper.retrieveCachedSize(); + + assertThat(storageCache.imagesSize).isEqualTo(FAKE_IMAGES_SIZE); + assertThat(storageCache.totalSize).isEqualTo(0); + } + + @Test + public void cacheTotalSizeAndUsedSize_shouldSaveToSharedPreference() { + mHelper.cacheTotalSizeAndUsedSize(FAKE_TOTAL_SIZE, FAKE_USED_SIZE); + + StorageCacheHelper.StorageCache storageCache = mHelper.retrieveCachedSize(); + + assertThat(storageCache.totalSize).isEqualTo(FAKE_TOTAL_SIZE); + assertThat(storageCache.usedSize).isEqualTo(FAKE_USED_SIZE); + } + + private StorageCacheHelper.StorageCache getFakeStorageCache() { + StorageCacheHelper.StorageCache result = new StorageCacheHelper.StorageCache(); + result.trashSize = FAKE_TRASH_SIZE; + result.systemSize = FAKE_SYSTEM_SIZE; + result.imagesSize = FAKE_IMAGES_SIZE; + result.documentsAndOtherSize = FAKE_DOCS_SIZE; + result.audioSize = FAKE_AUDIO_SIZE; + result.gamesSize = FAKE_GAMES_SIZE; + result.videosSize = FAKE_VIDEOS_SIZE; + result.allAppsExceptGamesSize = FAKE_APPS_SIZE; + return result; + } +} diff --git a/tests/robotests/src/com/android/settings/display/AutoRotatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AutoRotatePreferenceControllerTest.java index 1d175def202..54e6b991108 100644 --- a/tests/robotests/src/com/android/settings/display/AutoRotatePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/AutoRotatePreferenceControllerTest.java @@ -30,6 +30,7 @@ import android.provider.Settings; import androidx.preference.SwitchPreference; +import com.android.internal.R; import com.android.internal.view.RotationPolicy; import com.android.settings.core.BasePreferenceController; import com.android.settings.testutils.FakeFeatureFactory; @@ -64,6 +65,7 @@ public class AutoRotatePreferenceControllerTest { mPreference = new SwitchPreference(RuntimeEnvironment.application); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getContentResolver()).thenReturn(mContentResolver); + disableDeviceStateRotation(); mController = new AutoRotatePreferenceController(mContext, "auto_rotate"); } @@ -111,6 +113,26 @@ public class AutoRotatePreferenceControllerTest { .UNSUPPORTED_ON_DEVICE); } + @Test + public void getAvailabilityStatus_deviceRotationDisabled_returnsAvailable() { + enableAutoRotationPreference(); + disableDeviceStateRotation(); + + int availability = mController.getAvailabilityStatus(); + + assertThat(availability).isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void getAvailabilityStatus_deviceRotationEnabled_returnsUnsupported() { + enableAutoRotationPreference(); + enableDeviceStateRotation(); + + int availability = mController.getAvailabilityStatus(); + + assertThat(availability).isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + @Test public void testIsCheck() { assertThat(mController.isChecked()).isFalse(); @@ -180,4 +202,15 @@ public class AutoRotatePreferenceControllerTest { Settings.System.putIntForUser(mContentResolver, Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT); } + + private void enableDeviceStateRotation() { + when(mContext.getResources().getStringArray( + R.array.config_perDeviceStateRotationLockDefaults)).thenReturn( + new String[]{"0:0", "1:1", "2:2"}); + } + + private void disableDeviceStateRotation() { + when(mContext.getResources().getStringArray( + R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(new String[]{}); + } } diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragmentTest.java b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragmentTest.java new file mode 100644 index 00000000000..b773657e686 --- /dev/null +++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragmentTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2022 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.display; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.content.res.Resources; + +import com.android.settings.R; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class DeviceStateAutoRotateDetailsFragmentTest { + + private final DeviceStateAutoRotateDetailsFragment mFragment = + spy(new DeviceStateAutoRotateDetailsFragment()); + private final Context mContext = spy(RuntimeEnvironment.application); + private final Resources mResources = spy(mContext.getResources()); + + @Before + public void setUp() throws Exception { + when(mContext.getResources()).thenReturn(mResources); + when(mContext.getApplicationContext()).thenReturn(mContext); + when(mFragment.getContext()).thenReturn(mContext); + when(mFragment.getResources()).thenReturn(mResources); + } + + @Test + public void getMetricsCategory_returnsAutoRotateSettings() { + assertThat(mFragment.getMetricsCategory()).isEqualTo( + SettingsEnums.DISPLAY_AUTO_ROTATE_SETTINGS); + } + + @Test + public void getPreferenceScreenResId_returnsDeviceStateAutoRotationSettings() { + assertThat(mFragment.getPreferenceScreenResId()).isEqualTo( + R.xml.device_state_auto_rotate_settings); + } + + @Test + public void createPreferenceControllers_settableDeviceStates_returnsDeviceStateControllers() { + enableDeviceStateSettableRotationStates(new String[]{"0:1", "1:1"}, + new String[]{"Folded", "Unfolded"}); + + List preferenceControllers = + mFragment.createPreferenceControllers(mContext); + + assertThat(preferenceControllers).hasSize(2); + assertThat(preferenceControllers.get(0)).isInstanceOf( + DeviceStateAutoRotateSettingController.class); + assertThat(preferenceControllers.get(1)).isInstanceOf( + DeviceStateAutoRotateSettingController.class); + } + + @Test + public void createPreferenceControllers_noSettableDeviceStates_returnsEmptyList() { + enableDeviceStateSettableRotationStates(new String[]{}, new String[]{}); + + List preferenceControllers = + mFragment.createPreferenceControllers(mContext); + + assertThat(preferenceControllers).isEmpty(); + } + + private void enableDeviceStateSettableRotationStates(String[] settableStates, + String[] settableStatesDescriptions) { + when(mResources.getStringArray( + com.android.internal.R.array.config_perDeviceStateRotationLockDefaults)).thenReturn( + settableStates); + when(mResources.getStringArray( + R.array.config_settableAutoRotationDeviceStatesDescriptions)).thenReturn( + settableStatesDescriptions); + DeviceStateRotationLockSettingsManager.resetInstance(); + DeviceStateRotationLockSettingsManager.getInstance(mContext) + .resetStateForTesting(mResources); + } +} diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateOverviewControllerTest.java b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateOverviewControllerTest.java new file mode 100644 index 00000000000..a5416e70413 --- /dev/null +++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateOverviewControllerTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 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.display; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; + +import static com.google.common.truth.Truth.assertThat; + +import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; +import com.android.settings.testutils.shadow.ShadowRotationPolicy; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowRotationPolicy.class, ShadowDeviceStateRotationLockSettingsManager.class}) +public class DeviceStateAutoRotateOverviewControllerTest { + + private final DeviceStateAutoRotateOverviewController mController = + new DeviceStateAutoRotateOverviewController( + RuntimeEnvironment.application, "device_state_auto_rotate"); + + @Test + public void getAvailabilityStatus_rotationAndDeviceStateRotationEnabled_returnsAvailable() { + ShadowRotationPolicy.setRotationSupported(true); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + + int availability = mController.getAvailabilityStatus(); + + assertThat(availability).isEqualTo(AVAILABLE); + } + + @Test + public void getAvailabilityStatus_rotationNotSupported_returnsUnsupportedOnDevice() { + ShadowRotationPolicy.setRotationSupported(false); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + + int availability = mController.getAvailabilityStatus(); + + assertThat(availability).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_deviceStateRotationNotSupported_returnsUnsupportedOnDevice() { + ShadowRotationPolicy.setRotationSupported(true); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false); + + int availability = mController.getAvailabilityStatus(); + + assertThat(availability).isEqualTo(UNSUPPORTED_ON_DEVICE); + } +} diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java new file mode 100644 index 00000000000..28a071aca02 --- /dev/null +++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2022 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.display; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.preference.Preference; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; +import com.android.settings.testutils.shadow.ShadowRotationPolicy; +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; +import com.android.settingslib.search.SearchIndexableRaw; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = { + ShadowRotationPolicy.class, + ShadowDeviceStateRotationLockSettingsManager.class +}) +public class DeviceStateAutoRotateSettingControllerTest { + + private static final int DEFAULT_DEVICE_STATE = 1; + private static final String DEFAULT_DEVICE_STATE_DESCRIPTION = "Device state description"; + private static final int DEFAULT_ORDER = -10; + + private final Context mContext = RuntimeEnvironment.application; + private final DeviceStateAutoRotateSettingController mController = + new DeviceStateAutoRotateSettingController(mContext, DEFAULT_DEVICE_STATE, + DEFAULT_DEVICE_STATE_DESCRIPTION, DEFAULT_ORDER); + private final DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager = + DeviceStateRotationLockSettingsManager.getInstance(mContext); + + @Test + public void displayPreference_addsPreferenceToPreferenceScreen() { + PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext); + + mController.displayPreference(screen); + + assertThat(screen.getPreferenceCount()).isEqualTo(1); + Preference preference = screen.getPreference(0); + assertThat(preference.getTitle().toString()).isEqualTo(DEFAULT_DEVICE_STATE_DESCRIPTION); + assertThat(preference.getOrder()).isEqualTo(DEFAULT_ORDER); + assertThat(preference.getKey()).isEqualTo(mController.getPreferenceKey()); + } + + @Test + public void getAvailabilityStatus_rotationAndDeviceStateRotationEnabled_returnsAvailable() { + ShadowRotationPolicy.setRotationSupported(true); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + + int availability = mController.getAvailabilityStatus(); + + assertThat(availability).isEqualTo(AVAILABLE); + } + + @Test + public void getAvailabilityStatus_deviceStateRotationDisabled_returnsUnsupported() { + ShadowRotationPolicy.setRotationSupported(true); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false); + + int availability = mController.getAvailabilityStatus(); + + assertThat(availability).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_rotationDisabled_returnsUnsupported() { + ShadowRotationPolicy.setRotationSupported(false); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + + int availability = mController.getAvailabilityStatus(); + + assertThat(availability).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getPreferenceKey_returnsKeyBasedOnDeviceState() { + String key = mController.getPreferenceKey(); + + String expectedKey = "auto_rotate_device_state_" + DEFAULT_DEVICE_STATE; + assertThat(key).isEqualTo(expectedKey); + } + + @Test + public void isChecked_settingForStateIsUnlocked_returnsTrue() { + mAutoRotateSettingsManager.updateSetting(DEFAULT_DEVICE_STATE, /* rotationLocked= */ false); + + assertThat(mController.isChecked()).isTrue(); + } + + @Test + public void isChecked_settingForStateIsLocked_returnsFalse() { + mAutoRotateSettingsManager.updateSetting(DEFAULT_DEVICE_STATE, /* rotationLocked= */ true); + + assertThat(mController.isChecked()).isFalse(); + } + + @Test + public void setChecked_true_deviceStateSettingIsUnlocked() { + mController.setChecked(true); + + boolean rotationLocked = mAutoRotateSettingsManager.isRotationLocked(DEFAULT_DEVICE_STATE); + + assertThat(rotationLocked).isFalse(); + } + + @Test + public void setChecked_false_deviceStateSettingIsLocked() { + mController.setChecked(false); + + boolean rotationLocked = mAutoRotateSettingsManager.isRotationLocked(DEFAULT_DEVICE_STATE); + + assertThat(rotationLocked).isTrue(); + } + + @Test + public void updateRawDataToIndex_addsItemToList() { + List rawData = new ArrayList<>(); + + mController.updateRawDataToIndex(rawData); + + assertThat(rawData).hasSize(1); + SearchIndexableRaw item = rawData.get(0); + assertThat(item.key).isEqualTo(mController.getPreferenceKey()); + assertThat(item.title).isEqualTo(DEFAULT_DEVICE_STATE_DESCRIPTION); + assertThat(item.screenTitle).isEqualTo(mContext.getString(R.string.accelerometer_title)); + } + + @Test + public void getSliceHighlightMenuRes_returnsMenuKeyDisplay() { + int sliceHighlightMenuRes = mController.getSliceHighlightMenuRes(); + + assertThat(sliceHighlightMenuRes).isEqualTo(R.string.menu_key_display); + } + + @Test + public void isSliceable_returnsTrue() { + assertThat(mController.isSliceable()).isTrue(); + } + + @Test + public void isPublicSlice_returnsTrue() { + assertThat(mController.isPublicSlice()).isTrue(); + } +} diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java index 778721a163c..4fec38b762d 100644 --- a/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java @@ -39,7 +39,10 @@ import android.provider.Settings; import androidx.preference.Preference; import com.android.settings.testutils.ResolveInfoBuilder; +import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; +import com.android.settings.testutils.shadow.ShadowRotationPolicy; import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager; +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; import org.junit.Before; import org.junit.Test; @@ -63,6 +66,8 @@ public class SmartAutoRotateControllerTest { @Mock private Preference mPreference; private ContentResolver mContentResolver; + private final DeviceStateRotationLockSettingsManager mDeviceStateAutoRotateSettingsManager = + DeviceStateRotationLockSettingsManager.getInstance(RuntimeEnvironment.application); @Before public void setUp() { @@ -122,6 +127,34 @@ public class SmartAutoRotateControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); } + @Test + @Config(shadows = { + ShadowDeviceStateRotationLockSettingsManager.class, + ShadowRotationPolicy.class + }) + public void getAvailabilityStatus_deviceStateRotationLocked_returnDisableDependentSetting() { + enableDeviceStateRotation(); + lockDeviceStateRotation(); + + int availabilityStatus = mController.getAvailabilityStatus(); + + assertThat(availabilityStatus).isEqualTo(DISABLED_DEPENDENT_SETTING); + } + + @Test + @Config(shadows = { + ShadowDeviceStateRotationLockSettingsManager.class, + ShadowRotationPolicy.class + }) + public void getAvailabilityStatus_deviceStateRotationUnlocked_returnAvailable() { + enableDeviceStateRotation(); + unlockDeviceStateRotation(); + + int availabilityStatus = mController.getAvailabilityStatus(); + + assertThat(availabilityStatus).isEqualTo(AVAILABLE); + } + private void enableAutoRotation() { Settings.System.putIntForUser(mContentResolver, Settings.System.ACCELEROMETER_ROTATION, 1, UserHandle.USER_CURRENT); @@ -131,4 +164,23 @@ public class SmartAutoRotateControllerTest { Settings.System.putIntForUser(mContentResolver, Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT); } + + private void enableDeviceStateRotation() { + ShadowRotationPolicy.setRotationSupported(true); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + } + + private void lockDeviceStateRotation() { + mDeviceStateAutoRotateSettingsManager.updateSetting( + /* deviceState= */0, /* rotationLocked= */ true); + mDeviceStateAutoRotateSettingsManager.updateSetting( + /* deviceState= */1, /* rotationLocked= */ true); + } + + private void unlockDeviceStateRotation() { + mDeviceStateAutoRotateSettingsManager.updateSetting( + /* deviceState= */0, /* rotationLocked= */ false); + mDeviceStateAutoRotateSettingsManager.updateSetting( + /* deviceState= */1, /* rotationLocked= */ true); + } } diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java index 068de3472b5..39fdb049228 100644 --- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java @@ -40,6 +40,7 @@ import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.ResolveInfoBuilder; +import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager; import org.junit.Before; @@ -53,7 +54,10 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) -@Config(shadows = ShadowSensorPrivacyManager.class) +@Config(shadows = { + ShadowSensorPrivacyManager.class, + ShadowDeviceStateRotationLockSettingsManager.class +}) public class SmartAutoRotatePreferenceControllerTest { private static final String PACKAGE_NAME = "package_name"; @@ -95,6 +99,7 @@ public class SmartAutoRotatePreferenceControllerTest { new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate")); when(mController.isCameraLocked()).thenReturn(false); when(mController.isPowerSaveMode()).thenReturn(false); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false); } @Test @@ -199,6 +204,16 @@ public class SmartAutoRotatePreferenceControllerTest { .UNSUPPORTED_ON_DEVICE); } + + @Test + public void getAvailabilityStatus_deviceStateRotationEnabled_returnsUnsupported() { + enableAutoRotationPreference(); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + @Test public void isSliceableCorrectKey_returnsTrue() { final AutoRotatePreferenceController controller = diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java index 877d2c11e77..942fed6f619 100644 --- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java @@ -18,6 +18,8 @@ package com.android.settings.display; import static com.android.settings.display.SmartAutoRotatePreferenceFragment.AUTO_ROTATE_SWITCH_PREFERENCE_ID; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; @@ -33,6 +35,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.res.Resources; import android.view.View; import androidx.preference.Preference; @@ -40,7 +43,11 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.testutils.ResolveInfoBuilder; +import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; +import com.android.settings.testutils.shadow.ShadowRotationPolicy; import com.android.settings.widget.SettingsMainSwitchBar; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; import org.junit.Before; import org.junit.Test; @@ -49,8 +56,15 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.List; @RunWith(RobolectricTestRunner.class) +@Config(shadows = { + ShadowDeviceStateRotationLockSettingsManager.class, + ShadowRotationPolicy.class +}) public class SmartAutoRotatePreferenceFragmentTest { private static final String PACKAGE_NAME = "package_name"; @@ -70,19 +84,24 @@ public class SmartAutoRotatePreferenceFragmentTest { @Mock private Preference mRotateSwitchPreference; + private Resources mResources; + private Context mContext; @Before public void setUp() { MockitoAnnotations.initMocks(this); - final Context context = spy(RuntimeEnvironment.application); + mContext = spy(RuntimeEnvironment.application); ContentResolver mContentResolver = RuntimeEnvironment.application.getContentResolver(); - when(context.getPackageManager()).thenReturn(mPackageManager); - when(context.getContentResolver()).thenReturn(mContentResolver); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mContext.getContentResolver()).thenReturn(mContentResolver); doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName(); doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( Manifest.permission.CAMERA, PACKAGE_NAME); + mResources = spy(mContext.getResources()); + when(mContext.getResources()).thenReturn(mResources); + final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build(); resolveInfo.serviceInfo = new ServiceInfo(); when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo); @@ -90,15 +109,16 @@ public class SmartAutoRotatePreferenceFragmentTest { mFragment = spy(new SmartAutoRotatePreferenceFragment()); when(mActivity.getPackageManager()).thenReturn(mPackageManager); when(mFragment.getActivity()).thenReturn(mActivity); - when(mFragment.getContext()).thenReturn(context); + when(mFragment.getContext()).thenReturn(mContext); doReturn(mView).when(mFragment).getView(); when(mFragment.findPreference(AUTO_ROTATE_SWITCH_PREFERENCE_ID)).thenReturn( mRotateSwitchPreference); - mSwitchBar = spy(new SettingsMainSwitchBar(context)); + mSwitchBar = spy(new SettingsMainSwitchBar(mContext)); when(mActivity.getSwitchBar()).thenReturn(mSwitchBar); doReturn(mSwitchBar).when(mView).findViewById(R.id.switch_bar); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false); } @@ -110,6 +130,17 @@ public class SmartAutoRotatePreferenceFragmentTest { verify(mRotateSwitchPreference, times(1)).setVisible(false); } + @Test + public void createHeader_deviceStateRotationSupported_switchBarIsDisabled() { + ShadowRotationPolicy.setRotationSupported(true); + ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + + mFragment.createHeader(mActivity); + + verify(mSwitchBar, never()).show(); + verify(mRotateSwitchPreference, never()).setVisible(false); + } + @Test public void createHeader_faceDetectionUnSupported_switchBarIsDisabled() { doReturn(null).when(mPackageManager).getRotationResolverPackageName(); @@ -120,4 +151,41 @@ public class SmartAutoRotatePreferenceFragmentTest { verify(mRotateSwitchPreference, never()).setVisible(false); } + @Test + public void createPreferenceControllers_noSettableDeviceStates_returnsEmptyList() { + enableDeviceStateSettableRotationStates(new String[]{}, new String[]{}); + + List preferenceControllers = + mFragment.createPreferenceControllers(mContext); + + assertThat(preferenceControllers).isEmpty(); + } + + @Test + public void createPreferenceControllers_settableDeviceStates_returnsDeviceStateControllers() { + enableDeviceStateSettableRotationStates(new String[]{"0:1", "1:1"}, + new String[]{"Folded", "Unfolded"}); + + List preferenceControllers = + mFragment.createPreferenceControllers(mContext); + + assertThat(preferenceControllers).hasSize(2); + assertThat(preferenceControllers.get(0)).isInstanceOf( + DeviceStateAutoRotateSettingController.class); + assertThat(preferenceControllers.get(1)).isInstanceOf( + DeviceStateAutoRotateSettingController.class); + } + + private void enableDeviceStateSettableRotationStates(String[] settableStates, + String[] settableStatesDescriptions) { + when(mResources.getStringArray( + com.android.internal.R.array.config_perDeviceStateRotationLockDefaults)).thenReturn( + settableStates); + when(mResources.getStringArray( + R.array.config_settableAutoRotationDeviceStatesDescriptions)).thenReturn( + settableStatesDescriptions); + DeviceStateRotationLockSettingsManager.resetInstance(); + DeviceStateRotationLockSettingsManager.getInstance(mContext) + .resetStateForTesting(mResources); + } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateRotationLockSettingsManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateRotationLockSettingsManager.java new file mode 100644 index 00000000000..72df3cc94b3 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateRotationLockSettingsManager.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 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.testutils.shadow; + +import android.content.Context; + +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(DeviceStateRotationLockSettingsManager.class) +public class ShadowDeviceStateRotationLockSettingsManager { + + private static boolean sDeviceStateRotationLockEnabled; + + @Implementation + public static boolean isDeviceStateRotationLockEnabled(Context context) { + return sDeviceStateRotationLockEnabled; + } + + public static void setDeviceStateRotationLockEnabled(boolean enabled) { + sDeviceStateRotationLockEnabled = enabled; + } +} diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceControllerTest.java index 90b89278762..38c605c930d 100644 --- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceControllerTest.java @@ -30,7 +30,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.VersionedPackage; -import android.graphics.drawable.Drawable; import android.os.Looper; import android.service.notification.NotificationListenerFilter; import android.util.ArraySet; @@ -65,6 +64,7 @@ public class BridgedAppsPreferenceControllerTest { PreferenceScreen mScreen; @Mock ApplicationsState mAppState; + private ApplicationsState.AppEntry mAppEntry; private ApplicationsState.AppEntry mAppEntry2; @@ -92,8 +92,6 @@ public class BridgedAppsPreferenceControllerTest { mAppEntry.info = ai; mAppEntry.label = "hi"; - Drawable icon = mock(Drawable.class); - mAppEntry.icon = icon; mController = new BridgedAppsPreferenceController(mContext, "key"); mController.setCn(mCn); @@ -167,7 +165,7 @@ public class BridgedAppsPreferenceControllerTest { assertThat(actual.isChecked()).isTrue(); assertThat(actual.getTitle()).isEqualTo("hi"); - assertThat(actual.getIcon()).isEqualTo(mAppEntry.icon); + assertThat(actual.getIcon()).isNotNull(); } @Test diff --git a/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java b/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java index d4df97ff77e..1cfee0f377a 100644 --- a/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java +++ b/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java @@ -33,7 +33,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.settings.Settings; import com.android.settings.SettingsActivity; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import org.junit.Before; import org.junit.Test; @@ -48,14 +48,14 @@ public class PrivacyDashboardActivityTest { private static final String DEFAULT_FRAGMENT_CLASSNAME = "DefaultFragmentClassname"; @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; + private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; private Settings.PrivacyDashboardActivity mActivity; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; + SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; final Intent intent = new Intent(); intent.setAction(android.provider.Settings.ACTION_PRIVACY_SETTINGS); intent.setClass(InstrumentationRegistry.getInstrumentation().getTargetContext(), @@ -78,7 +78,7 @@ public class PrivacyDashboardActivityTest { @Test public void onCreate_whenSafetyCenterEnabled_redirectsToSafetyCenter() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true); final ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); mActivity.handleSafetyCenterRedirection(); @@ -89,7 +89,7 @@ public class PrivacyDashboardActivityTest { @Test public void onCreate_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false); mActivity.handleSafetyCenterRedirection(); verify(mActivity, times(0)).startActivity(any()); diff --git a/tests/unit/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceControllerTest.java b/tests/unit/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceControllerTest.java index 495700a10dd..bc6be2eaf80 100644 --- a/tests/unit/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceControllerTest.java @@ -26,7 +26,7 @@ import android.content.Context; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import com.android.settings.security.TopLevelSecurityEntryPreferenceController; import org.junit.Before; @@ -43,12 +43,12 @@ public class TopLevelPrivacyEntryPreferenceControllerTest { private TopLevelPrivacyEntryPreferenceController mTopLevelPrivacyEntryPreferenceController; @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; + private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; @Before public void setUp() { MockitoAnnotations.initMocks(this); - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; + SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; mTopLevelPrivacyEntryPreferenceController = new TopLevelPrivacyEntryPreferenceController( @@ -57,7 +57,7 @@ public class TopLevelPrivacyEntryPreferenceControllerTest { @Test public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsUnavailable() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true); assertThat(mTopLevelPrivacyEntryPreferenceController.getAvailabilityStatus()) .isEqualTo(TopLevelSecurityEntryPreferenceController.CONDITIONALLY_UNAVAILABLE); @@ -65,7 +65,7 @@ public class TopLevelPrivacyEntryPreferenceControllerTest { @Test public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsAvailable() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false); assertThat(mTopLevelPrivacyEntryPreferenceController.getAvailabilityStatus()) .isEqualTo(TopLevelSecurityEntryPreferenceController.AVAILABLE); diff --git a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java index f53d3366474..2627d245d96 100644 --- a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java @@ -41,26 +41,21 @@ public class BiometricsSafetySourceTest { @Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; - @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; - @Before public void setUp() { MockitoAnnotations.initMocks(this); mApplicationContext = ApplicationProvider.getApplicationContext(); SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; } @After public void tearDown() { SafetyCenterManagerWrapper.sInstance = null; - SafetyCenterStatusHolder.sInstance = null; } @Test public void sendSafetyData_whenSafetyCenterIsDisabled_sendsNoData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false); BiometricsSafetySource.sendSafetyData(mApplicationContext); @@ -70,7 +65,7 @@ public class BiometricsSafetySourceTest { @Test // TODO(b/215517420): Adapt this test when method is implemented. public void sendSafetyData_whenSafetyCenterIsEnabled_sendsNoData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); BiometricsSafetySource.sendSafetyData(mApplicationContext); diff --git a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java index 4a58b4c2f04..64b96928de9 100644 --- a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java @@ -56,9 +56,6 @@ public class LockScreenSafetySourceTest { @Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; - @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; - @Mock private ScreenLockPreferenceDetailsUtils mScreenLockPreferenceDetailsUtils; @@ -67,18 +64,16 @@ public class LockScreenSafetySourceTest { MockitoAnnotations.initMocks(this); mApplicationContext = ApplicationProvider.getApplicationContext(); SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; } @After public void tearDown() { SafetyCenterManagerWrapper.sInstance = null; - SafetyCenterStatusHolder.sInstance = null; } @Test public void sendSafetyData_whenSafetyCenterIsDisabled_sendsNoData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false); LockScreenSafetySource.sendSafetyData(mApplicationContext, mScreenLockPreferenceDetailsUtils); @@ -88,7 +83,7 @@ public class LockScreenSafetySourceTest { @Test public void sendSafetyData_whenScreenLockIsDisabled_sendsNoData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isAvailable()).thenReturn(false); LockScreenSafetySource.sendSafetyData(mApplicationContext, @@ -113,7 +108,7 @@ public class LockScreenSafetySourceTest { assertThat(safetySourceStatus.getTitle().toString()) .isEqualTo(ResourcesUtils.getResourcesString( mApplicationContext, - "unlock_set_unlock_launch_picker_title_profile")); + "unlock_set_unlock_launch_picker_title")); assertThat(safetySourceStatus.getSummary().toString()) .isEqualTo(SUMMARY); assertThat(safetySourceStatus.getPendingIntent().getIntent()).isNotNull(); @@ -227,7 +222,7 @@ public class LockScreenSafetySourceTest { } private void whenScreenLockIsEnabled() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isAvailable()).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.getSummary(anyInt())).thenReturn(SUMMARY); diff --git a/tests/unit/src/com/android/settings/safetycenter/SafetyCenterStatusHolderTest.java b/tests/unit/src/com/android/settings/safetycenter/SafetyCenterManagerWrapperTest.java similarity index 87% rename from tests/unit/src/com/android/settings/safetycenter/SafetyCenterStatusHolderTest.java rename to tests/unit/src/com/android/settings/safetycenter/SafetyCenterManagerWrapperTest.java index 2a31eb8e14a..432a5d67e98 100644 --- a/tests/unit/src/com/android/settings/safetycenter/SafetyCenterStatusHolderTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/SafetyCenterManagerWrapperTest.java @@ -32,7 +32,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) -public class SafetyCenterStatusHolderTest { +public class SafetyCenterManagerWrapperTest { @Mock private Context mContext; @@ -44,13 +44,13 @@ public class SafetyCenterStatusHolderTest { @Test public void isEnabled_whenContextNull_returnsFalse() { - assertThat(SafetyCenterStatusHolder.get().isEnabled(null)).isFalse(); + assertThat(SafetyCenterManagerWrapper.get().isEnabled(null)).isFalse(); } @Test public void isEnabled_whenSystemServiceNull_returnsFalse() { when(mContext.getSystemService(SafetyCenterManager.class)).thenReturn(null); - assertThat(SafetyCenterStatusHolder.get().isEnabled(mContext)).isFalse(); + assertThat(SafetyCenterManagerWrapper.get().isEnabled(mContext)).isFalse(); } } diff --git a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java index 6c9addd6a3e..d81e8afed3a 100644 --- a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java @@ -50,26 +50,21 @@ public class SafetySourceBroadcastReceiverTest { @Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; - @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; - @Before public void setUp() { MockitoAnnotations.initMocks(this); mApplicationContext = ApplicationProvider.getApplicationContext(); SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; } @After public void tearDown() { SafetyCenterManagerWrapper.sInstance = null; - SafetyCenterStatusHolder.sInstance = null; } @Test public void sendSafetyData_whenSafetyCenterIsEnabled_withNoIntentAction_sendsNoData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent().putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[]{}); new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); @@ -79,7 +74,7 @@ public class SafetySourceBroadcastReceiverTest { @Test public void sendSafetyData_whenSafetyCenterIsDisabled_sendsNoData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false); Intent intent = new Intent() .setAction(ACTION_REFRESH_SAFETY_SOURCES) @@ -94,7 +89,7 @@ public class SafetySourceBroadcastReceiverTest { @Test public void sendSafetyData_whenSafetyCenterIsEnabled_withNullSourceIds_sendsNoData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent().setAction(ACTION_REFRESH_SAFETY_SOURCES); new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); @@ -104,7 +99,7 @@ public class SafetySourceBroadcastReceiverTest { @Test public void sendSafetyData_whenSafetyCenterIsEnabled_withNoSourceIds_sendsNoData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent() .setAction(ACTION_REFRESH_SAFETY_SOURCES) @@ -117,7 +112,7 @@ public class SafetySourceBroadcastReceiverTest { @Test public void sendSafetyData_withLockscreenSourceId_sendsLockscreenData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent() .setAction(ACTION_REFRESH_SAFETY_SOURCES) @@ -136,7 +131,7 @@ public class SafetySourceBroadcastReceiverTest { @Test public void sendSafetyData_withBiometricsSourceId_sendsBiometricData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent() .setAction(ACTION_REFRESH_SAFETY_SOURCES) @@ -152,7 +147,7 @@ public class SafetySourceBroadcastReceiverTest { @Test public void sendSafetyData_onBootCompleted_sendsBiometricAndLockscreenData() { - when(mSafetyCenterStatusHolder.isEnabled(mApplicationContext)).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent().setAction(Intent.ACTION_BOOT_COMPLETED); // TODO(b/215517420): Update this test when BiometricSafetySource is implemented to test diff --git a/tests/unit/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceControllerTest.java b/tests/unit/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceControllerTest.java index e9c451e4c31..25cd774ea05 100644 --- a/tests/unit/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceControllerTest.java @@ -32,6 +32,7 @@ import androidx.preference.Preference; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,7 +50,7 @@ public class TopLevelSafetyCenterEntryPreferenceControllerTest { private Preference mPreference; @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; + private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; @Mock private Context mContext; @@ -57,7 +58,7 @@ public class TopLevelSafetyCenterEntryPreferenceControllerTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; + SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; mPreference = new Preference(ApplicationProvider.getApplicationContext()); mPreference.setKey(PREFERENCE_KEY); @@ -67,6 +68,11 @@ public class TopLevelSafetyCenterEntryPreferenceControllerTest { new TopLevelSafetyCenterEntryPreferenceController(mContext, PREFERENCE_KEY); } + @After + public void tearDown() { + SafetyCenterManagerWrapper.sInstance = null; + } + @Test public void handlePreferenceTreeClick_forDifferentPreferenceKey_isNotHandled() { Preference preference = new Preference(ApplicationProvider.getApplicationContext()); @@ -104,7 +110,7 @@ public class TopLevelSafetyCenterEntryPreferenceControllerTest { @Test public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsUnavailable() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false); assertThat(mTopLevelSafetyCenterEntryPreferenceController.getAvailabilityStatus()) .isEqualTo(TopLevelSafetyCenterEntryPreferenceController.CONDITIONALLY_UNAVAILABLE); @@ -112,7 +118,7 @@ public class TopLevelSafetyCenterEntryPreferenceControllerTest { @Test public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsAvailable() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true); assertThat(mTopLevelSafetyCenterEntryPreferenceController.getAvailabilityStatus()) .isEqualTo(TopLevelSafetyCenterEntryPreferenceController.AVAILABLE); diff --git a/tests/unit/src/com/android/settings/security/SecurityAdvancedSettingsTest.java b/tests/unit/src/com/android/settings/security/SecurityAdvancedSettingsTest.java index ac91abba547..2efb357b869 100644 --- a/tests/unit/src/com/android/settings/security/SecurityAdvancedSettingsTest.java +++ b/tests/unit/src/com/android/settings/security/SecurityAdvancedSettingsTest.java @@ -29,7 +29,7 @@ import androidx.test.annotation.UiThreadTest; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.ResourcesUtils; import com.android.settingslib.drawer.CategoryKey; @@ -51,7 +51,7 @@ public class SecurityAdvancedSettingsTest { private SecurityAdvancedSettings mSecurityAdvancedSettings; @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; + private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; @Before @UiThreadTest @@ -61,7 +61,7 @@ public class SecurityAdvancedSettingsTest { Looper.prepare(); } - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; + SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; mContext = ApplicationProvider.getApplicationContext(); mSecurityAdvancedSettings = spy(new SecurityAdvancedSettings()); @@ -76,7 +76,7 @@ public class SecurityAdvancedSettingsTest { @Test public void getCategoryKey_whenSafetyCenterIsEnabled_returnsSecurity() { - when(mSafetyCenterStatusHolder.isEnabled(any())).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(any())).thenReturn(true); assertThat(mSecurityAdvancedSettings.getCategoryKey()) .isEqualTo(CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS); @@ -84,7 +84,7 @@ public class SecurityAdvancedSettingsTest { @Test public void getCategoryKey_whenAlternativeFragmentPresented_returnsAlternative() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false); setupAlternativeFragment(true, ALTERNATIVE_CATEGORY_KEY); assertThat(mSecurityAdvancedSettings.getCategoryKey()) @@ -93,7 +93,7 @@ public class SecurityAdvancedSettingsTest { @Test public void getCategoryKey_whenNoAlternativeFragmentPresented_returnsLegacy() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false); setupAlternativeFragment(false, null); assertThat(mSecurityAdvancedSettings.getCategoryKey()) diff --git a/tests/unit/src/com/android/settings/security/SecurityDashboardActivityTest.java b/tests/unit/src/com/android/settings/security/SecurityDashboardActivityTest.java index 33486638bd9..82112c96807 100644 --- a/tests/unit/src/com/android/settings/security/SecurityDashboardActivityTest.java +++ b/tests/unit/src/com/android/settings/security/SecurityDashboardActivityTest.java @@ -33,7 +33,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.settings.Settings; import com.android.settings.SettingsActivity; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; @@ -53,14 +53,14 @@ public class SecurityDashboardActivityTest { private Intent mDefaultIntent; @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; + private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; @Before public void setUp() { MockitoAnnotations.initMocks(this); FakeFeatureFactory mFeatureFactory = FakeFeatureFactory.setupForTest(); mSecuritySettingsFeatureProvider = mFeatureFactory.getSecuritySettingsFeatureProvider(); - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; + SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; mDefaultIntent = new Intent(); mDefaultIntent.setAction(android.provider.Settings.ACTION_SECURITY_SETTINGS); @@ -122,7 +122,7 @@ public class SecurityDashboardActivityTest { @Test public void onCreate_whenSafetyCenterEnabled_redirectsToSafetyCenter() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true); final ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); mActivity.handleSafetyCenterRedirection(); @@ -133,7 +133,7 @@ public class SecurityDashboardActivityTest { @Test public void onCreate_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false); mActivity.handleSafetyCenterRedirection(); diff --git a/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java b/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java index 81ebda6f4ac..eb8fa17807b 100644 --- a/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java @@ -31,7 +31,7 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.SettingsActivity; -import com.android.settings.safetycenter.SafetyCenterStatusHolder; +import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; @@ -55,14 +55,14 @@ public class TopLevelSecurityEntryPreferenceControllerTest { @Mock private Context mContext; @Mock - private SafetyCenterStatusHolder mSafetyCenterStatusHolder; + private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; @Before public void setUp() { MockitoAnnotations.initMocks(this); mFeatureFactory = FakeFeatureFactory.setupForTest(); mSecuritySettingsFeatureProvider = mFeatureFactory.getSecuritySettingsFeatureProvider(); - SafetyCenterStatusHolder.sInstance = mSafetyCenterStatusHolder; + SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; mPreference = new Preference(ApplicationProvider.getApplicationContext()); mPreference.setKey(PREFERENCE_KEY); @@ -128,7 +128,7 @@ public class TopLevelSecurityEntryPreferenceControllerTest { @Test public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsUnavailable() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(true); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true); assertThat(mTopLevelSecurityEntryPreferenceController.getAvailabilityStatus()) .isEqualTo(TopLevelSecurityEntryPreferenceController.CONDITIONALLY_UNAVAILABLE); @@ -136,7 +136,7 @@ public class TopLevelSecurityEntryPreferenceControllerTest { @Test public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsAvailable() { - when(mSafetyCenterStatusHolder.isEnabled(any(Context.class))).thenReturn(false); + when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false); assertThat(mTopLevelSecurityEntryPreferenceController.getAvailabilityStatus()) .isEqualTo(TopLevelSecurityEntryPreferenceController.AVAILABLE);