Merge "Merge SafetyCenterStatusHolder into SafetyCenterManagerWrapper" into tm-dev
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 4f0d804..f0aafe1 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 50eddb5..bf78fd7 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -570,7 +570,19 @@
<item>2</item>
<item>3</item>
</integer-array>
-
+
+ <!-- The settings/preference description for each settable device state defined in the array
+ "config_perDeviceStateRotationLockDefaults".
+ The item in position "i" describes the auto-rotation setting for the device state also in
+ position "i" in the array "config_perDeviceStateRotationLockDefaults". -->
+ <string-array name="config_settableAutoRotationDeviceStatesDescriptions">
+ <!-- Example:
+ <item>Auto-rotate when folded</item>
+ <item>@null</item> No description for state in position 1
+ <item>Auto-rotate when unfolded</item>
+ -->
+ </string-array>
+
<!-- Whether to aggregate for network selection list-->
<bool name="config_network_selection_list_aggregation_enabled">false</bool>
@@ -596,4 +608,5 @@
<!-- Whether the dream setup activity should be enabled as part of setupwizard -->
<bool name="dream_setup_supported">false</bool>
+
</resources>
diff --git a/res/xml/accessibility_system_controls.xml b/res/xml/accessibility_system_controls.xml
index 71e1143..37c4d67 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"/>
+ <!-- Standard auto-rotation preference that will be shown when device state based auto-rotation
+ settings are NOT available. -->
<SwitchPreference
android:key="toggle_lock_screen_rotation_preference"
android:persistent="false"
android:title="@string/accelerometer_title"
settings:controller="com.android.settings.accessibility.LockScreenRotationPreferenceController"/>
+
+ <!-- Auto-rotation preference that will be shown when device state based auto-rotation settings
+ are available. -->
+ <Preference
+ android:key="device_state_auto_rotate_accessibility"
+ android:persistent="false"
+ android:title="@string/accelerometer_title"
+ android:fragment="com.android.settings.display.DeviceStateAutoRotateDetailsFragment"
+ settings:keywords="@string/keywords_auto_rotate"
+ settings:controller="com.android.settings.display.DeviceStateAutoRotateOverviewController"/>
+
</PreferenceScreen>
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 0000000..2ddb4c7
--- /dev/null
+++ b/res/xml/device_state_auto_rotate_settings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/accelerometer_title" >
+
+ <!-- Device state based auto-rotation preferences will be added programmatically here. -->
+
+</PreferenceScreen>
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 0724eea..ba52a30 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -96,12 +96,27 @@
<PreferenceCategory
android:title="@string/category_name_display_controls">
+ <!--
+ Standard auto-rotation preference that will be shown when device state based
+ auto-rotation settings are NOT available.
+ -->
<SwitchPreference
android:key="auto_rotate"
android:title="@string/accelerometer_title"
settings:keywords="@string/keywords_auto_rotate"
settings:controller="com.android.settings.display.AutoRotatePreferenceController"/>
+ <!--
+ Auto-rotation preference that will be shown when device state based auto-rotation
+ settings are available.
+ -->
+ <Preference
+ android:key="device_state_auto_rotate"
+ android:title="@string/accelerometer_title"
+ android:fragment="com.android.settings.display.DeviceStateAutoRotateDetailsFragment"
+ settings:keywords="@string/keywords_auto_rotate"
+ settings:controller="com.android.settings.display.DeviceStateAutoRotateOverviewController"/>
+
<SwitchPreference
android:key="display_white_balance"
android:title="@string/display_white_balance_title"
diff --git a/src/com/android/settings/accessibility/LockScreenRotationPreferenceController.java b/src/com/android/settings/accessibility/LockScreenRotationPreferenceController.java
index 5ed4b5c..a1c292a 100644
--- a/src/com/android/settings/accessibility/LockScreenRotationPreferenceController.java
+++ b/src/com/android/settings/accessibility/LockScreenRotationPreferenceController.java
@@ -25,6 +25,7 @@
import com.android.internal.view.RotationPolicy.RotationPolicyListener;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.display.DeviceStateAutoRotationHelper;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -59,7 +60,9 @@
@Override
public int getAvailabilityStatus() {
- return RotationPolicy.isRotationSupported(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ return RotationPolicy.isRotationSupported(mContext)
+ && !DeviceStateAutoRotationHelper.isDeviceStateRotationEnabledForA11y(mContext)
+ ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index cfdfdaa..8b1d633 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -53,6 +53,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -280,6 +281,11 @@
return null;
}
+ /** Returns all controllers of type T. */
+ protected <T extends AbstractPreferenceController> List<T> useAll(Class<T> clazz) {
+ return (List<T>) 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 c05abdb..7e9f314 100644
--- a/src/com/android/settings/development/tare/TareFactorController.java
+++ b/src/com/android/settings/development/tare/TareFactorController.java
@@ -565,7 +565,6 @@
}
}
-
/**
* Iterates through the factor policy map for keys and current values to
* rebuild a current string that is then assigned to be the new global settings string.
@@ -573,50 +572,18 @@
* @param factorPolicy policy being updated
*/
private void rebuildPolicyConstants(int factorPolicy) {
- StringBuilder newConstantsStringBuilder = new StringBuilder();
-
switch (factorPolicy) {
case POLICY_ALARM_MANAGER:
- int sizeAM = mAlarmManagerMap.size();
-
- for (int i = 0; i < sizeAM; i++) {
- if (i > 0) {
- newConstantsStringBuilder.append(",");
- }
-
- String key = mAlarmManagerMap.keyAt(i);
- newConstantsStringBuilder.append(key + "=" + mAlarmManagerMap.get(key)
- .currentValue);
- }
-
- String newAMConstantsString = newConstantsStringBuilder.toString();
-
- Settings.Global.putString(mContentResolver, Settings.Global
- .TARE_ALARM_MANAGER_CONSTANTS,
- newAMConstantsString);
+ writeConstantsToSettings(mAlarmManagerMap,
+ Settings.Global.TARE_ALARM_MANAGER_CONSTANTS);
mAlarmManagerConstants = Settings.Global
.getString(mContentResolver, Settings.Global
.TARE_ALARM_MANAGER_CONSTANTS);
break;
case POLICY_JOB_SCHEDULER:
- int sizeJS = mJobSchedulerMap.size();
-
- for (int i = 0; i < sizeJS; i++) {
- if (i > 0) {
- newConstantsStringBuilder.append(",");
- }
-
- String key = mJobSchedulerMap.keyAt(i);
- newConstantsStringBuilder.append(key + "=" + mJobSchedulerMap.get(key)
- .currentValue);
- }
-
- String newJSConstantsString = newConstantsStringBuilder.toString();
-
- Settings.Global.putString(mContentResolver, Settings.Global
- .TARE_JOB_SCHEDULER_CONSTANTS,
- newJSConstantsString);
+ writeConstantsToSettings(mJobSchedulerMap,
+ Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS);
mJobSchedulerConstants = Settings.Global
.getString(mContentResolver, Settings.Global
@@ -625,6 +592,29 @@
}
}
+ private void writeConstantsToSettings(ArrayMap<String, TareFactorData> factorMap,
+ String settingsKey) {
+ final StringBuilder constantsStringBuilder = new StringBuilder();
+
+ for (int i = 0, size = factorMap.size(); i < size; ++i) {
+ final TareFactorData factor = factorMap.valueAt(i);
+ if (factor.currentValue == factor.defaultValue) {
+ continue;
+ }
+
+ if (constantsStringBuilder.length() > 0) {
+ constantsStringBuilder.append(",");
+ }
+
+ constantsStringBuilder
+ .append(factorMap.keyAt(i))
+ .append("=")
+ .append(factor.currentValue);
+ }
+
+ Settings.Global.putString(mContentResolver, settingsKey, constantsStringBuilder.toString());
+ }
+
/**
* Creates a dialog with the values linked to the key.
*
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 746d234..cf31724 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.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 @@
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 @@
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 @@
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 @@
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 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 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 @@
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 934ff3f..d3549d4 100644
--- a/src/com/android/settings/deviceinfo/StorageItemPreference.java
+++ b/src/com/android/settings/deviceinfo/StorageItemPreference.java
@@ -66,7 +66,7 @@
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 f87a06a..84cafd4 100644
--- a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
+++ b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
@@ -183,6 +183,9 @@
@Override
public void handleResult(SparseArray<StorageAsyncLoader.StorageResult> 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 0000000..a868c9f
--- /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 ee0c9e7..9813439 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.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 @@
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 @@
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 @@
// 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 @@
mTrashPreference = screen.findPreference(TRASH_KEY);
}
- /** Fragments use it to set storage result and update UI of this controller. */
- public void onLoadFinished(SparseArray<StorageAsyncLoader.StorageResult> 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<StorageAsyncLoader.StorageResult> 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<StorageAsyncLoader.StorageResult> 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 7660353..872fa8a 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java
@@ -18,6 +18,7 @@
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 @@
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 @@
}
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 5dc2286..90423fb 100644
--- a/src/com/android/settings/display/AutoRotatePreferenceController.java
+++ b/src/com/android/settings/display/AutoRotatePreferenceController.java
@@ -74,6 +74,7 @@
@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 0000000..fb6d9f4
--- /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<AbstractPreferenceController> 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<SearchIndexableRaw> 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 0000000..5e49bf3
--- /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 0000000..c8f6280
--- /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<SearchIndexableRaw> 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 0000000..223ef1a
--- /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<DeviceStateAutoRotateSettingController> controllers) {
+ for (DeviceStateAutoRotateSettingController controller : controllers) {
+ controller.init(lifecycle);
+ }
+ }
+
+ static ImmutableList<AbstractPreferenceController> createPreferenceControllers(
+ Context context) {
+ List<SettableDeviceState> 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<AbstractPreferenceController> 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<SearchIndexableRaw> getRawDataToIndex(
+ Context context, boolean enabled) {
+ // Check what the "enabled" param is for
+ List<AbstractPreferenceController> controllers = createPreferenceControllers(context);
+ List<SearchIndexableRaw> 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 76a222a..d29a64e 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.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 @@
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 @@
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 @@
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 @@
}
protected boolean isRotationLocked() {
+ if (DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext)) {
+ return mDeviceStateAutoRotateSettingsManager.isRotationLockedForAllStates();
+ }
return RotationPolicy.isRotationLocked(mContext);
}
@@ -127,6 +137,8 @@
};
}
RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener);
+ mDeviceStateAutoRotateSettingsManager.registerListener(
+ mDeviceStateRotationLockSettingsListener);
}
@OnLifecycleEvent(ON_STOP)
@@ -136,6 +148,8 @@
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 bd8ee84..d02e336 100644
--- a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
+++ b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
@@ -77,6 +77,7 @@
@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 4737336..9fda03c 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.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 void onAttach(Context context) {
super.onAttach(context);
use(SmartAutoRotateController.class).init(getLifecycle());
+ DeviceStateAutoRotationHelper.initControllers(
+ getLifecycle(),
+ useAll(DeviceStateAutoRotateSettingController.class)
+ );
+ }
+
+ @Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ return DeviceStateAutoRotationHelper.createPreferenceControllers(context);
}
@Override
@@ -79,7 +92,9 @@
@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 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<SearchIndexableRaw> 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 c56d89b..051a54a 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -32,12 +32,17 @@
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 @@
void onHomepageLoaded();
}
- private interface FragmentBuilder<T extends Fragment> {
+ private interface FragmentBuilder<T extends Fragment> {
T build();
}
@@ -149,7 +154,9 @@
@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 @@
}
}
+ 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 @@
// 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/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java
index ef8f569..f908b8a 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 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 @@
}
@Test
- @Config(shadows = {ShadowRotationPolicy.class})
+ @Config(shadows = {
+ ShadowRotationPolicy.class,
+ ShadowDeviceStateRotationLockSettingsManager.class
+ })
public void getAvailabilityStatus_supportedRotation_shouldReturnAvailable() {
ShadowRotationPolicy.setRotationSupported(true /* supported */);
@@ -59,8 +63,23 @@
}
@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 fd1c8ff..aa5f980 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -144,6 +144,21 @@
}
@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<TestPreferenceController> retrievedControllers = mTestFragment.useAll(
+ TestPreferenceController.class);
+
+ assertThat(retrievedControllers).containsExactly(controller1, controller2);
+ }
+
+ @Test
public void displayTilesAsPreference_shouldAddTilesWithIntent() {
when(mFakeFeatureFactory.dashboardFeatureProvider
.getTilesForCategory(nullable(String.class)))
@@ -360,6 +375,13 @@
}
}
+ 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 0000000..1956b09
--- /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 1d175de..54e6b99 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 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 @@
mPreference = new SwitchPreference(RuntimeEnvironment.application);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ disableDeviceStateRotation();
mController = new AutoRotatePreferenceController(mContext, "auto_rotate");
}
@@ -112,6 +114,26 @@
}
@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 @@
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 0000000..b773657
--- /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<AbstractPreferenceController> 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<AbstractPreferenceController> 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 0000000..a5416e7
--- /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 0000000..28a071a
--- /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<SearchIndexableRaw> 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 778721a..4fec38b 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 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 @@
@Mock
private Preference mPreference;
private ContentResolver mContentResolver;
+ private final DeviceStateRotationLockSettingsManager mDeviceStateAutoRotateSettingsManager =
+ DeviceStateRotationLockSettingsManager.getInstance(RuntimeEnvironment.application);
@Before
public void setUp() {
@@ -122,6 +127,34 @@
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 @@
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 068de34..39fdb04 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.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.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 @@
new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate"));
when(mController.isCameraLocked()).thenReturn(false);
when(mController.isPowerSaveMode()).thenReturn(false);
+ ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false);
}
@Test
@@ -199,6 +204,16 @@
.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 877d2c1..942fed6 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 @@
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.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 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.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 @@
@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 @@
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);
}
@@ -111,6 +131,17 @@
}
@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 @@
verify(mRotateSwitchPreference, never()).setVisible(false);
}
+ @Test
+ public void createPreferenceControllers_noSettableDeviceStates_returnsEmptyList() {
+ enableDeviceStateSettableRotationStates(new String[]{}, new String[]{});
+
+ List<AbstractPreferenceController> 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<AbstractPreferenceController> 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 0000000..72df3cc
--- /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;
+ }
+}