blob: 01fabcc8bc1e928fcfccc6873ccbc9084d4de360 [file] [log] [blame]
/*
* Copyright (C) 2021 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 android.annotation.Nullable;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Trace;
import android.util.IndentingPrintWriter;
import androidx.annotation.NonNull;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
import java.io.PrintWriter;
import java.util.concurrent.Executor;
import javax.inject.Inject;
/**
* 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, Dumpable {
private final RotationPolicyWrapper mRotationPolicyWrapper;
private final DeviceStateManager mDeviceStateManager;
private final Executor mMainExecutor;
private final DeviceStateRotationLockSettingsManager mDeviceStateRotationLockSettingsManager;
private final DeviceStateRotationLockSettingControllerLogger mLogger;
// 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;
private DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener
mDeviceStateRotationLockSettingsListener;
@Inject
public DeviceStateRotationLockSettingController(
RotationPolicyWrapper rotationPolicyWrapper,
DeviceStateManager deviceStateManager,
@Main Executor executor,
DeviceStateRotationLockSettingsManager deviceStateRotationLockSettingsManager,
DeviceStateRotationLockSettingControllerLogger logger,
DumpManager dumpManager) {
mRotationPolicyWrapper = rotationPolicyWrapper;
mDeviceStateManager = deviceStateManager;
mMainExecutor = executor;
mDeviceStateRotationLockSettingsManager = deviceStateRotationLockSettingsManager;
mLogger = logger;
dumpManager.registerDumpable(this);
}
@Override
public void setListening(boolean listening) {
mLogger.logListeningChange(listening);
if (listening) {
// Note that this is called once with the initial state of the device, even if there
// is no user action.
mDeviceStateCallback = this::updateDeviceState;
mDeviceStateManager.registerCallback(mMainExecutor, mDeviceStateCallback);
mDeviceStateRotationLockSettingsListener = () ->
readPersistedSetting("deviceStateRotationLockChange", mDeviceState);
mDeviceStateRotationLockSettingsManager.registerListener(
mDeviceStateRotationLockSettingsListener);
} else {
if (mDeviceStateCallback != null) {
mDeviceStateManager.unregisterCallback(mDeviceStateCallback);
}
if (mDeviceStateRotationLockSettingsListener != null) {
mDeviceStateRotationLockSettingsManager.unregisterListener(
mDeviceStateRotationLockSettingsListener);
}
}
}
@Override
public void onRotationLockStateChanged(boolean newRotationLocked, boolean affordanceVisible) {
int deviceState = mDeviceState;
boolean currentRotationLocked = mDeviceStateRotationLockSettingsManager
.isRotationLocked(deviceState);
mLogger.logRotationLockStateChanged(deviceState, newRotationLocked, currentRotationLocked);
if (deviceState == -1) {
return;
}
if (newRotationLocked == currentRotationLocked) {
return;
}
saveNewRotationLockSetting(newRotationLocked);
}
private void saveNewRotationLockSetting(boolean isRotationLocked) {
int deviceState = mDeviceState;
mLogger.logSaveNewRotationLockSetting(isRotationLocked, deviceState);
mDeviceStateRotationLockSettingsManager.updateSetting(deviceState, isRotationLocked);
}
private void updateDeviceState(int state) {
mLogger.logUpdateDeviceState(mDeviceState, state);
if (Trace.isEnabled()) {
Trace.traceBegin(
Trace.TRACE_TAG_APP, "updateDeviceState [state=" + state + "]");
}
try {
if (mDeviceState == state) {
return;
}
readPersistedSetting("updateDeviceState", state);
} finally {
Trace.endSection();
}
}
private void readPersistedSetting(String caller, int state) {
int rotationLockSetting =
mDeviceStateRotationLockSettingsManager.getRotationLockSetting(state);
boolean shouldBeLocked = rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_LOCKED;
boolean isLocked = mRotationPolicyWrapper.isRotationLocked();
mLogger.readPersistedSetting(caller, state, rotationLockSetting, shouldBeLocked, isLocked);
if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
// This should not happen. Device states that have an ignored setting, should also
// specify a fallback device state which is not 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
// valid device state.
return;
}
// Accept the new state
mDeviceState = state;
// Update the rotation policy, if needed, for this new device state
if (shouldBeLocked != isLocked) {
mRotationPolicyWrapper.setRotationLock(shouldBeLocked);
}
}
@Override
public void dump(@NonNull PrintWriter printWriter, @NonNull String[] args) {
IndentingPrintWriter pw = new IndentingPrintWriter(printWriter);
mDeviceStateRotationLockSettingsManager.dump(pw);
pw.println("DeviceStateRotationLockSettingController");
pw.increaseIndent();
pw.println("mDeviceState: " + mDeviceState);
pw.decreaseIndent();
}
}