summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/Settings.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java167
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingsManager.java266
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java151
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java28
7 files changed, 407 insertions, 218 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 72e28630da40..5cdb1fdf64ce 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10525,7 +10525,7 @@ public final class Settings {
DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
})
@Retention(RetentionPolicy.SOURCE)
- @interface DeviceStateRotationLockSetting {
+ public @interface DeviceStateRotationLockSetting {
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
index 41cacf5142fd..1030bfdb40fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
@@ -16,110 +16,53 @@
package com.android.systemui.statusbar.policy;
-
import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED;
import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED;
-import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED;
-
-import static com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule.DEVICE_STATE_ROTATION_LOCK_DEFAULTS;
import android.annotation.Nullable;
import android.hardware.devicestate.DeviceStateManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
-import android.util.SparseIntArray;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
import java.util.concurrent.Executor;
import javax.inject.Inject;
-import javax.inject.Named;
/**
- * Handles reading and writing of rotation lock settings per device state, as well as setting
- * the rotation lock when device state changes.
- **/
+ * Handles reading and writing of rotation lock settings per device state, as well as setting the
+ * rotation lock when device state changes.
+ */
@SysUISingleton
-public final class DeviceStateRotationLockSettingController implements Listenable,
- RotationLockController.RotationLockControllerCallback {
+public final class DeviceStateRotationLockSettingController
+ implements Listenable, RotationLockController.RotationLockControllerCallback {
private static final String TAG = "DSRotateLockSettingCon";
- private static final String SEPARATOR_REGEX = ":";
-
- private final SecureSettings mSecureSettings;
private final RotationPolicyWrapper mRotationPolicyWrapper;
private final DeviceStateManager mDeviceStateManager;
private final Executor mMainExecutor;
- private final String[] mDeviceStateRotationLockDefaults;
+ private final DeviceStateRotationLockSettingsManager mDeviceStateRotationLockSettingsManager;
- private SparseIntArray mDeviceStateRotationLockSettings;
- // TODO(b/183001527): Add API to query current device state and initialize this.
+ // On registration for DeviceStateCallback, we will receive a callback with the current state
+ // and this will be initialized.
private int mDeviceState = -1;
- @Nullable
- private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
-
+ @Nullable private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
+ private DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener
+ mDeviceStateRotationLockSettingsListener;
@Inject
public DeviceStateRotationLockSettingController(
- SecureSettings secureSettings,
RotationPolicyWrapper rotationPolicyWrapper,
DeviceStateManager deviceStateManager,
@Main Executor executor,
- @Named(DEVICE_STATE_ROTATION_LOCK_DEFAULTS) String[] deviceStateRotationLockDefaults
- ) {
- mSecureSettings = secureSettings;
+ DeviceStateRotationLockSettingsManager deviceStateRotationLockSettingsManager) {
mRotationPolicyWrapper = rotationPolicyWrapper;
mDeviceStateManager = deviceStateManager;
mMainExecutor = executor;
- mDeviceStateRotationLockDefaults = deviceStateRotationLockDefaults;
- }
-
- /**
- * Loads the settings from storage.
- */
- public void initialize() {
- String serializedSetting =
- mSecureSettings.getStringForUser(Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- UserHandle.USER_CURRENT);
- if (TextUtils.isEmpty(serializedSetting)) {
- // No settings saved, we should load the defaults and persist them.
- fallbackOnDefaults();
- return;
- }
- String[] values = serializedSetting.split(SEPARATOR_REGEX);
- if (values.length % 2 != 0) {
- // Each entry should be a key/value pair, so this is corrupt.
- Log.wtf(TAG, "Can't deserialize saved settings, falling back on defaults");
- fallbackOnDefaults();
- return;
- }
- mDeviceStateRotationLockSettings = new SparseIntArray(values.length / 2);
- int key;
- int value;
-
- for (int i = 0; i < values.length - 1; ) {
- try {
- key = Integer.parseInt(values[i++]);
- value = Integer.parseInt(values[i++]);
- mDeviceStateRotationLockSettings.put(key, value);
- } catch (NumberFormatException e) {
- Log.wtf(TAG, "Error deserializing one of the saved settings", e);
- fallbackOnDefaults();
- return;
- }
- }
- }
-
- private void fallbackOnDefaults() {
- loadDefaults();
- persistSettings();
+ mDeviceStateRotationLockSettingsManager = deviceStateRotationLockSettingsManager;
}
@Override
@@ -129,10 +72,17 @@ public final class DeviceStateRotationLockSettingController implements Listenabl
// is no user action.
mDeviceStateCallback = this::updateDeviceState;
mDeviceStateManager.registerCallback(mMainExecutor, mDeviceStateCallback);
+ mDeviceStateRotationLockSettingsListener = () -> readPersistedSetting(mDeviceState);
+ mDeviceStateRotationLockSettingsManager.registerListener(
+ mDeviceStateRotationLockSettingsListener);
} else {
if (mDeviceStateCallback != null) {
mDeviceStateManager.unregisterCallback(mDeviceStateCallback);
}
+ if (mDeviceStateRotationLockSettingsListener != null) {
+ mDeviceStateRotationLockSettingsManager.unregisterListener(
+ mDeviceStateRotationLockSettingsListener);
+ }
}
}
@@ -143,7 +93,8 @@ public final class DeviceStateRotationLockSettingController implements Listenabl
return;
}
- if (rotationLocked == isRotationLockedForCurrentState()) {
+ if (rotationLocked
+ == mDeviceStateRotationLockSettingsManager.isRotationLocked(mDeviceState)) {
Log.v(TAG, "Rotation lock same as the current setting, no need to update.");
return;
}
@@ -152,19 +103,15 @@ public final class DeviceStateRotationLockSettingController implements Listenabl
}
private void saveNewRotationLockSetting(boolean isRotationLocked) {
- Log.v(TAG, "saveNewRotationLockSetting [state=" + mDeviceState + "] [isRotationLocked="
- + isRotationLocked + "]");
-
- mDeviceStateRotationLockSettings.put(mDeviceState,
- isRotationLocked
- ? DEVICE_STATE_ROTATION_LOCK_LOCKED
- : DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
- persistSettings();
- }
-
- private boolean isRotationLockedForCurrentState() {
- return mDeviceStateRotationLockSettings.get(mDeviceState,
- DEVICE_STATE_ROTATION_LOCK_IGNORED) == DEVICE_STATE_ROTATION_LOCK_LOCKED;
+ Log.v(
+ TAG,
+ "saveNewRotationLockSetting [state="
+ + mDeviceState
+ + "] [isRotationLocked="
+ + isRotationLocked
+ + "]");
+
+ mDeviceStateRotationLockSettingsManager.updateSetting(mDeviceState, isRotationLocked);
}
private void updateDeviceState(int state) {
@@ -173,8 +120,12 @@ public final class DeviceStateRotationLockSettingController implements Listenabl
return;
}
+ readPersistedSetting(state);
+ }
+
+ private void readPersistedSetting(int state) {
int rotationLockSetting =
- mDeviceStateRotationLockSettings.get(state, DEVICE_STATE_ROTATION_LOCK_IGNORED);
+ mDeviceStateRotationLockSettingsManager.getRotationLockSetting(state);
if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
// We won't handle this device state. The same rotation lock setting as before should
// apply and any changes to the rotation lock setting will be written for the previous
@@ -186,54 +137,10 @@ public final class DeviceStateRotationLockSettingController implements Listenabl
// Accept the new state
mDeviceState = state;
- // Update the rotation lock setting if needed for this new device state
+ // Update the rotation policy, if needed, for this new device state
boolean newRotationLockSetting = rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_LOCKED;
if (newRotationLockSetting != mRotationPolicyWrapper.isRotationLocked()) {
mRotationPolicyWrapper.setRotationLock(newRotationLockSetting);
}
}
-
- private void persistSettings() {
- if (mDeviceStateRotationLockSettings.size() == 0) {
- mSecureSettings.putStringForUser(Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- /* value= */"", UserHandle.USER_CURRENT);
- return;
- }
-
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(mDeviceStateRotationLockSettings.keyAt(0))
- .append(SEPARATOR_REGEX)
- .append(mDeviceStateRotationLockSettings.valueAt(0));
-
- for (int i = 1; i < mDeviceStateRotationLockSettings.size(); i++) {
- stringBuilder
- .append(SEPARATOR_REGEX)
- .append(mDeviceStateRotationLockSettings.keyAt(i))
- .append(SEPARATOR_REGEX)
- .append(mDeviceStateRotationLockSettings.valueAt(i));
- }
- mSecureSettings.putStringForUser(Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- stringBuilder.toString(), UserHandle.USER_CURRENT);
- }
-
- private void loadDefaults() {
- if (mDeviceStateRotationLockDefaults.length == 0) {
- Log.w(TAG, "Empty default settings");
- mDeviceStateRotationLockSettings = new SparseIntArray(/* initialCapacity= */0);
- return;
- }
- mDeviceStateRotationLockSettings =
- new SparseIntArray(mDeviceStateRotationLockDefaults.length);
- for (String serializedDefault : mDeviceStateRotationLockDefaults) {
- String[] entry = serializedDefault.split(SEPARATOR_REGEX);
- try {
- int key = Integer.parseInt(entry[0]);
- int value = Integer.parseInt(entry[1]);
- mDeviceStateRotationLockSettings.put(key, value);
- } catch (NumberFormatException e) {
- Log.wtf(TAG, "Error deserializing default settings", e);
- }
- }
- }
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingsManager.java
new file mode 100644
index 000000000000..a418c74848a5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingsManager.java
@@ -0,0 +1,266 @@
+/*
+ * 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.systemui.statusbar.policy;
+
+import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED;
+import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED;
+import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseIntArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manages device-state based rotation lock settings. Handles reading, writing, and listening for
+ * changes.
+ */
+public final class DeviceStateRotationLockSettingsManager {
+
+ private static final String TAG = "DSRotLockSettingsMngr";
+ private static final String SEPARATOR_REGEX = ":";
+
+ private static DeviceStateRotationLockSettingsManager sSingleton;
+
+ private final ContentResolver mContentResolver;
+ private final String[] mDeviceStateRotationLockDefaults;
+ private final Handler mMainHandler = Handler.getMain();
+ private final Set<DeviceStateRotationLockSettingsListener> mListeners = new HashSet<>();
+ private SparseIntArray mDeviceStateRotationLockSettings;
+
+ private DeviceStateRotationLockSettingsManager(Context context) {
+ mContentResolver = context.getContentResolver();
+ mDeviceStateRotationLockDefaults =
+ context.getResources()
+ .getStringArray(R.array.config_perDeviceStateRotationLockDefaults);
+ initializeInMemoryMap();
+ listenForSettingsChange(context);
+ }
+
+ /** Returns a singleton instance of this class */
+ public static synchronized DeviceStateRotationLockSettingsManager getInstance(Context context) {
+ if (sSingleton == null) {
+ sSingleton =
+ new DeviceStateRotationLockSettingsManager(context.getApplicationContext());
+ }
+ return sSingleton;
+ }
+
+ /** Returns true if device-state based rotation lock settings are enabled. */
+ public static boolean isDeviceStateRotationLockEnabled(Context context) {
+ return context.getResources()
+ .getStringArray(R.array.config_perDeviceStateRotationLockDefaults)
+ .length
+ > 0;
+ }
+
+ private void listenForSettingsChange(Context context) {
+ context.getContentResolver()
+ .registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.DEVICE_STATE_ROTATION_LOCK),
+ /* notifyForDescendents= */ false, //NOTYPO
+ new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ onPersistedSettingsChanged();
+ }
+ },
+ UserHandle.USER_CURRENT);
+ }
+
+ /**
+ * Registers a {@link DeviceStateRotationLockSettingsListener} to be notified when the settings
+ * change. Can be called multiple times with different listeners.
+ */
+ public void registerListener(DeviceStateRotationLockSettingsListener runnable) {
+ mListeners.add(runnable);
+ }
+
+ /**
+ * Unregisters a {@link DeviceStateRotationLockSettingsListener}. No-op if the given instance
+ * was never registered.
+ */
+ public void unregisterListener(
+ DeviceStateRotationLockSettingsListener deviceStateRotationLockSettingsListener) {
+ if (!mListeners.remove(deviceStateRotationLockSettingsListener)) {
+ Log.w(TAG, "Attempting to unregister a listener hadn't been registered");
+ }
+ }
+
+ /** Updates the rotation lock setting for a specified device state. */
+ public void updateSetting(int deviceState, boolean rotationLocked) {
+ mDeviceStateRotationLockSettings.put(
+ deviceState,
+ rotationLocked
+ ? DEVICE_STATE_ROTATION_LOCK_LOCKED
+ : DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
+ persistSettings();
+ }
+
+ /**
+ * Returns the {@link DeviceStateRotationLockSetting} for the given device state. If no setting
+ * is specified for this device state, it will return {@link
+ * DEVICE_STATE_ROTATION_LOCK_IGNORED}.
+ */
+ @Settings.Secure.DeviceStateRotationLockSetting
+ public int getRotationLockSetting(int deviceState) {
+ return mDeviceStateRotationLockSettings.get(
+ deviceState, DEVICE_STATE_ROTATION_LOCK_IGNORED);
+ }
+
+ /** Returns true if the rotation is locked for the current device state */
+ public boolean isRotationLocked(int deviceState) {
+ return getRotationLockSetting(deviceState) == DEVICE_STATE_ROTATION_LOCK_LOCKED;
+ }
+
+ /**
+ * Returns true if there is no device state for which the current setting is {@link
+ * DEVICE_STATE_ROTATION_LOCK_UNLOCKED}.
+ */
+ public boolean isRotationLockedForAllStates() {
+ for (int i = 0; i < mDeviceStateRotationLockSettings.size(); i++) {
+ if (mDeviceStateRotationLockSettings.valueAt(i)
+ == DEVICE_STATE_ROTATION_LOCK_UNLOCKED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void initializeInMemoryMap() {
+ String serializedSetting =
+ Settings.Secure.getStringForUser(
+ mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ UserHandle.USER_CURRENT);
+ if (TextUtils.isEmpty(serializedSetting)) {
+ // No settings saved, we should load the defaults and persist them.
+ fallbackOnDefaults();
+ return;
+ }
+ String[] values = serializedSetting.split(SEPARATOR_REGEX);
+ if (values.length % 2 != 0) {
+ // Each entry should be a key/value pair, so this is corrupt.
+ Log.wtf(TAG, "Can't deserialize saved settings, falling back on defaults");
+ fallbackOnDefaults();
+ return;
+ }
+ mDeviceStateRotationLockSettings = new SparseIntArray(values.length / 2);
+ int key;
+ int value;
+
+ for (int i = 0; i < values.length - 1; ) {
+ try {
+ key = Integer.parseInt(values[i++]);
+ value = Integer.parseInt(values[i++]);
+ mDeviceStateRotationLockSettings.put(key, value);
+ } catch (NumberFormatException e) {
+ Log.wtf(TAG, "Error deserializing one of the saved settings", e);
+ fallbackOnDefaults();
+ return;
+ }
+ }
+ }
+
+ private void fallbackOnDefaults() {
+ loadDefaults();
+ persistSettings();
+ }
+
+ private void persistSettings() {
+ if (mDeviceStateRotationLockSettings.size() == 0) {
+ Settings.Secure.putStringForUser(
+ mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ /* value= */ "",
+ UserHandle.USER_CURRENT);
+ return;
+ }
+
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder
+ .append(mDeviceStateRotationLockSettings.keyAt(0))
+ .append(SEPARATOR_REGEX)
+ .append(mDeviceStateRotationLockSettings.valueAt(0));
+
+ for (int i = 1; i < mDeviceStateRotationLockSettings.size(); i++) {
+ stringBuilder
+ .append(SEPARATOR_REGEX)
+ .append(mDeviceStateRotationLockSettings.keyAt(i))
+ .append(SEPARATOR_REGEX)
+ .append(mDeviceStateRotationLockSettings.valueAt(i));
+ }
+ Settings.Secure.putStringForUser(
+ mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ stringBuilder.toString(),
+ UserHandle.USER_CURRENT);
+ }
+
+ private void loadDefaults() {
+ if (mDeviceStateRotationLockDefaults.length == 0) {
+ Log.w(TAG, "Empty default settings");
+ mDeviceStateRotationLockSettings = new SparseIntArray(/* initialCapacity= */ 0);
+ return;
+ }
+ mDeviceStateRotationLockSettings =
+ new SparseIntArray(mDeviceStateRotationLockDefaults.length);
+ for (String serializedDefault : mDeviceStateRotationLockDefaults) {
+ String[] entry = serializedDefault.split(SEPARATOR_REGEX);
+ try {
+ int key = Integer.parseInt(entry[0]);
+ int value = Integer.parseInt(entry[1]);
+ mDeviceStateRotationLockSettings.put(key, value);
+ } catch (NumberFormatException e) {
+ Log.wtf(TAG, "Error deserializing default settings", e);
+ }
+ }
+ }
+
+ /**
+ * Called when the persisted settings have changed, requiring a reinitialization of the
+ * in-memory map.
+ */
+ @VisibleForTesting
+ public void onPersistedSettingsChanged() {
+ initializeInMemoryMap();
+ notifyListeners();
+ }
+
+ private void notifyListeners() {
+ for (DeviceStateRotationLockSettingsListener r : mListeners) {
+ r.onSettingsChanged();
+ }
+ }
+
+ /** Listener for changes in device-state based rotation lock settings */
+ public interface DeviceStateRotationLockSettingsListener {
+ /** Called whenever the settings have changed. */
+ void onSettingsChanged();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
index 3143a471649c..1eeb0ac8b3bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
@@ -64,7 +64,6 @@ public final class RotationLockControllerImpl implements RotationLockController
mDeviceStateRotationLockSettingController = deviceStateRotationLockSettingController;
mIsPerDeviceStateRotationLockEnabled = deviceStateRotationLockDefaults.length > 0;
if (mIsPerDeviceStateRotationLockEnabled) {
- deviceStateRotationLockSettingController.initialize();
mCallbacks.add(mDeviceStateRotationLockSettingController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index b6a96a7e49b9..60938fb2feb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.policy.dagger;
+import android.content.Context;
import android.content.res.Resources;
import android.os.UserManager;
@@ -35,6 +36,7 @@ import com.android.systemui.statusbar.policy.DeviceControlsController;
import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.statusbar.policy.DevicePostureControllerImpl;
+import com.android.systemui.statusbar.policy.DeviceStateRotationLockSettingsManager;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
import com.android.systemui.statusbar.policy.FlashlightController;
@@ -163,6 +165,14 @@ public interface StatusBarPolicyModule {
return controller;
}
+ /** Returns a singleton instance of DeviceStateRotationLockSettingsManager */
+ @SysUISingleton
+ @Provides
+ static DeviceStateRotationLockSettingsManager provideAutoRotateSettingsManager(
+ Context context) {
+ return DeviceStateRotationLockSettingsManager.getInstance(context);
+ }
+
/**
* Default values for per-device state rotation lock settings.
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
index db7b2f20fa4c..a8522c787029 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
@@ -16,6 +16,10 @@
package com.android.systemui.statusbar.policy;
+import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED;
+import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED;
+import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -25,14 +29,15 @@ import android.hardware.devicestate.DeviceStateManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
+import android.testing.TestableContentResolver;
import android.testing.TestableResources;
import androidx.test.filters.SmallTest;
+import com.android.internal.R;
import com.android.internal.view.RotationPolicy;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
@@ -47,63 +52,55 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase {
- private static final String[] DEFAULT_SETTINGS = new String[]{
- "0:0",
- "1:2"
- };
+ private static final String[] DEFAULT_SETTINGS = new String[] {"0:0", "1:2"};
- private final FakeSettings mFakeSettings = new FakeSettings();
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private final FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
@Mock DeviceStateManager mDeviceStateManager;
RotationPolicyWrapper mFakeRotationPolicy = new FakeRotationPolicy();
DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
+ private DeviceStateRotationLockSettingsManager mSettingsManager;
+ private TestableContentResolver mContentResolver;
@Before
public void setUp() {
MockitoAnnotations.initMocks(/* testClass= */ this);
TestableResources resources = mContext.getOrCreateTestableResources();
+ resources.addOverride(R.array.config_perDeviceStateRotationLockDefaults, DEFAULT_SETTINGS);
ArgumentCaptor<DeviceStateManager.DeviceStateCallback> deviceStateCallbackArgumentCaptor =
- ArgumentCaptor.forClass(
- DeviceStateManager.DeviceStateCallback.class);
+ ArgumentCaptor.forClass(DeviceStateManager.DeviceStateCallback.class);
- mDeviceStateRotationLockSettingController = new DeviceStateRotationLockSettingController(
- mFakeSettings,
- mFakeRotationPolicy,
- mDeviceStateManager,
- mFakeExecutor,
- DEFAULT_SETTINGS
- );
+ mContentResolver = mContext.getContentResolver();
+ mSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(mContext);
+ mDeviceStateRotationLockSettingController =
+ new DeviceStateRotationLockSettingController(
+ mFakeRotationPolicy, mDeviceStateManager, mFakeExecutor, mSettingsManager);
mDeviceStateRotationLockSettingController.setListening(true);
- verify(mDeviceStateManager).registerCallback(any(),
- deviceStateCallbackArgumentCaptor.capture());
+ verify(mDeviceStateManager)
+ .registerCallback(any(), deviceStateCallbackArgumentCaptor.capture());
mDeviceStateCallback = deviceStateCallbackArgumentCaptor.getValue();
}
@Test
public void whenSavedSettingsEmpty_defaultsLoadedAndSaved() {
- mFakeSettings.putStringForUser(Settings.Secure.DEVICE_STATE_ROTATION_LOCK, "",
- UserHandle.USER_CURRENT);
+ initializeSettingsWith();
- mDeviceStateRotationLockSettingController.initialize();
-
- assertThat(mFakeSettings
- .getStringForUser(Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- UserHandle.USER_CURRENT))
+ assertThat(
+ Settings.Secure.getStringForUser(
+ mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ UserHandle.USER_CURRENT))
.isEqualTo("0:0:1:2");
}
@Test
public void whenNoSavedValueForDeviceState_assumeIgnored() {
- mFakeSettings.putStringForUser(
- Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- /* value= */"0:2:1:2",
- UserHandle.USER_CURRENT);
+ initializeSettingsWith(
+ 0, DEVICE_STATE_ROTATION_LOCK_UNLOCKED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
mFakeRotationPolicy.setRotationLock(true);
- mDeviceStateRotationLockSettingController.initialize();
mDeviceStateCallback.onStateChanged(1);
assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
@@ -116,52 +113,43 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
@Test
public void whenDeviceStateSwitched_loadCorrectSetting() {
- mFakeSettings.putStringForUser(
- Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- /* value= */"0:2:1:1",
- UserHandle.USER_CURRENT);
+ initializeSettingsWith(
+ 0, DEVICE_STATE_ROTATION_LOCK_UNLOCKED, 1, DEVICE_STATE_ROTATION_LOCK_LOCKED);
mFakeRotationPolicy.setRotationLock(true);
- mDeviceStateRotationLockSettingController.initialize();
mDeviceStateCallback.onStateChanged(0);
assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
mDeviceStateCallback.onStateChanged(1);
assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue();
-
}
@Test
public void whenUserChangesSetting_saveSettingForCurrentState() {
- mFakeSettings.putStringForUser(
- Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- /* value= */"0:1:1:2",
- UserHandle.USER_CURRENT);
+ initializeSettingsWith(
+ 0, DEVICE_STATE_ROTATION_LOCK_LOCKED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
+ mSettingsManager.onPersistedSettingsChanged();
mFakeRotationPolicy.setRotationLock(true);
- mDeviceStateRotationLockSettingController.initialize();
mDeviceStateCallback.onStateChanged(0);
assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue();
- mDeviceStateRotationLockSettingController
- .onRotationLockStateChanged(/* rotationLocked= */false,
- /* affordanceVisible= */ true);
+ mDeviceStateRotationLockSettingController.onRotationLockStateChanged(
+ /* rotationLocked= */ false, /* affordanceVisible= */ true);
- assertThat(mFakeSettings
- .getStringForUser(Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- UserHandle.USER_CURRENT))
+ assertThat(
+ Settings.Secure.getStringForUser(
+ mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ UserHandle.USER_CURRENT))
.isEqualTo("0:2:1:2");
}
-
@Test
public void whenDeviceStateSwitchedToIgnoredState_usePreviousSetting() {
- mFakeSettings.putStringForUser(
- Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- /* value= */"0:0:1:2",
- UserHandle.USER_CURRENT);
+ initializeSettingsWith(
+ 0, DEVICE_STATE_ROTATION_LOCK_IGNORED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
mFakeRotationPolicy.setRotationLock(true);
- mDeviceStateRotationLockSettingController.initialize();
mDeviceStateCallback.onStateChanged(1);
assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
@@ -172,12 +160,9 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
@Test
public void whenDeviceStateSwitchedToIgnoredState_newSettingsSaveForPreviousState() {
- mFakeSettings.putStringForUser(
- Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- /* value= */"0:0:1:2",
- UserHandle.USER_CURRENT);
+ initializeSettingsWith(
+ 0, DEVICE_STATE_ROTATION_LOCK_IGNORED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
mFakeRotationPolicy.setRotationLock(true);
- mDeviceStateRotationLockSettingController.initialize();
mDeviceStateCallback.onStateChanged(1);
assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
@@ -185,16 +170,52 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
mDeviceStateCallback.onStateChanged(0);
assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
- mDeviceStateRotationLockSettingController
- .onRotationLockStateChanged(/* rotationLocked= */true,
- /* affordanceVisible= */ true);
+ mDeviceStateRotationLockSettingController.onRotationLockStateChanged(
+ /* rotationLocked= */ true, /* affordanceVisible= */ true);
- assertThat(mFakeSettings
- .getStringForUser(Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- UserHandle.USER_CURRENT))
+ assertThat(
+ Settings.Secure.getStringForUser(
+ mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ UserHandle.USER_CURRENT))
.isEqualTo("0:0:1:1");
}
+ @Test
+ public void whenSettingsChangedExternally_updateRotationPolicy() throws InterruptedException {
+ initializeSettingsWith(
+ 0, DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
+ 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
+ mFakeRotationPolicy.setRotationLock(false);
+ mDeviceStateCallback.onStateChanged(0);
+
+ assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
+
+ // Changing device state 0 to LOCKED
+ initializeSettingsWith(
+ 0, DEVICE_STATE_ROTATION_LOCK_LOCKED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
+
+ assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue();
+ }
+
+ private void initializeSettingsWith(int... values) {
+ if (values.length % 2 != 0) {
+ throw new IllegalArgumentException("Expecting key-value pairs");
+ }
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < values.length; sb.append(":")) {
+ sb.append(values[i++]).append(":").append(values[i++]);
+ }
+
+ Settings.Secure.putStringForUser(
+ mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ sb.toString(),
+ UserHandle.USER_CURRENT);
+
+ mSettingsManager.onPersistedSettingsChanged();
+ }
+
private static class FakeRotationPolicy implements RotationPolicyWrapper {
private boolean mRotationLock;
@@ -230,8 +251,8 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase
}
@Override
- public void registerRotationPolicyListener(RotationPolicy.RotationPolicyListener listener,
- int userHandle) {
+ public void registerRotationPolicyListener(
+ RotationPolicy.RotationPolicyListener listener, int userHandle) {
throw new AssertionError("Not implemented");
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java
index 0581264d18e2..ea620a6856f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java
@@ -23,7 +23,6 @@ import static org.mockito.Mockito.verifyZeroInteractions;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.testing.TestableResources;
import androidx.test.filters.SmallTest;
@@ -43,25 +42,19 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class RotationLockControllerImplTest extends SysuiTestCase {
- private static final String[] DEFAULT_SETTINGS = new String[]{
- "0:0",
- "1:2"
- };
+ private static final String[] DEFAULT_SETTINGS = new String[] {"0:0", "1:2"};
@Mock RotationPolicyWrapper mRotationPolicyWrapper;
@Mock DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
- private TestableResources mResources;
- private ArgumentCaptor<RotationPolicy.RotationPolicyListener>
- mRotationPolicyListenerCaptor;
+ private ArgumentCaptor<RotationPolicy.RotationPolicyListener> mRotationPolicyListenerCaptor;
@Before
public void setUp() {
MockitoAnnotations.initMocks(/* testClass= */ this);
- mResources = mContext.getOrCreateTestableResources();
- mRotationPolicyListenerCaptor = ArgumentCaptor.forClass(
- RotationPolicy.RotationPolicyListener.class);
+ mRotationPolicyListenerCaptor =
+ ArgumentCaptor.forClass(RotationPolicy.RotationPolicyListener.class);
}
@Test
@@ -79,14 +72,7 @@ public class RotationLockControllerImplTest extends SysuiTestCase {
}
@Test
- public void whenFlagOn_initializesDeviceStateRotationController() {
- createRotationLockController();
-
- verify(mDeviceStateRotationLockSettingController).initialize();
- }
-
- @Test
- public void whenFlagOn_dviceStateRotationControllerAddedToCallbacks() {
+ public void whenFlagOn_deviceStateRotationControllerAddedToCallbacks() {
createRotationLockController();
captureRotationPolicyListener().onChange();
@@ -103,11 +89,11 @@ public class RotationLockControllerImplTest extends SysuiTestCase {
private void createRotationLockController() {
createRotationLockController(DEFAULT_SETTINGS);
}
+
private void createRotationLockController(String[] deviceStateRotationLockDefaults) {
new RotationLockControllerImpl(
mRotationPolicyWrapper,
mDeviceStateRotationLockSettingController,
- deviceStateRotationLockDefaults
- );
+ deviceStateRotationLockDefaults);
}
}