Merge "Extract device state rotation lock settings management to a separate class. This will be followed-up by a CL moving it to SettingsLib so it can be shared with Settings"
This commit is contained in:
commit
491bd1a6fb
@ -10525,7 +10525,7 @@ public final class Settings {
|
||||
DEVICE_STATE_ROTATION_LOCK_UNLOCKED,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface DeviceStateRotationLockSetting {
|
||||
public @interface DeviceStateRotationLockSetting {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 + "]");
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -64,7 +64,6 @@ public final class RotationLockControllerImpl implements RotationLockController
|
||||
mDeviceStateRotationLockSettingController = deviceStateRotationLockSettingController;
|
||||
mIsPerDeviceStateRotationLockEnabled = deviceStateRotationLockDefaults.length > 0;
|
||||
if (mIsPerDeviceStateRotationLockEnabled) {
|
||||
deviceStateRotationLockSettingController.initialize();
|
||||
mCallbacks.add(mDeviceStateRotationLockSettingController);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user