1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.Context; 22 import android.hardware.devicestate.DeviceStateManager; 23 import android.os.Handler; 24 import android.os.HandlerExecutor; 25 26 import com.android.internal.R; 27 import com.android.internal.util.ArrayUtils; 28 29 import java.util.ArrayList; 30 import java.util.List; 31 import java.util.function.Consumer; 32 33 /** 34 * Class that registers callbacks with the {@link DeviceStateManager} and responds to device 35 * changes. 36 */ 37 final class DeviceStateController implements DeviceStateManager.DeviceStateCallback { 38 39 @NonNull 40 private final DeviceStateManager mDeviceStateManager; 41 @NonNull 42 private final int[] mOpenDeviceStates; 43 @NonNull 44 private final int[] mHalfFoldedDeviceStates; 45 @NonNull 46 private final int[] mFoldedDeviceStates; 47 @NonNull 48 private final int[] mRearDisplayDeviceStates; 49 @NonNull 50 private final int[] mReverseRotationAroundZAxisStates; 51 @NonNull 52 private final List<Consumer<DeviceState>> mDeviceStateCallbacks = new ArrayList<>(); 53 54 @Nullable 55 private DeviceState mLastDeviceState; 56 private int mCurrentState; 57 58 public enum DeviceState { 59 UNKNOWN, OPEN, FOLDED, HALF_FOLDED, REAR, 60 } 61 DeviceStateController(@onNull Context context, @NonNull Handler handler)62 DeviceStateController(@NonNull Context context, @NonNull Handler handler) { 63 mDeviceStateManager = context.getSystemService(DeviceStateManager.class); 64 65 mOpenDeviceStates = context.getResources() 66 .getIntArray(R.array.config_openDeviceStates); 67 mHalfFoldedDeviceStates = context.getResources() 68 .getIntArray(R.array.config_halfFoldedDeviceStates); 69 mFoldedDeviceStates = context.getResources() 70 .getIntArray(R.array.config_foldedDeviceStates); 71 mRearDisplayDeviceStates = context.getResources() 72 .getIntArray(R.array.config_rearDisplayDeviceStates); 73 mReverseRotationAroundZAxisStates = context.getResources() 74 .getIntArray(R.array.config_deviceStatesToReverseDefaultDisplayRotationAroundZAxis); 75 76 if (mDeviceStateManager != null) { 77 mDeviceStateManager.registerCallback(new HandlerExecutor(handler), this); 78 } 79 } 80 unregisterFromDeviceStateManager()81 void unregisterFromDeviceStateManager() { 82 if (mDeviceStateManager != null) { 83 mDeviceStateManager.unregisterCallback(this); 84 } 85 } 86 registerDeviceStateCallback(@onNull Consumer<DeviceState> callback)87 void registerDeviceStateCallback(@NonNull Consumer<DeviceState> callback) { 88 mDeviceStateCallbacks.add(callback); 89 } 90 91 /** 92 * @return true if the rotation direction on the Z axis should be reversed. 93 */ shouldReverseRotationDirectionAroundZAxis()94 boolean shouldReverseRotationDirectionAroundZAxis() { 95 return ArrayUtils.contains(mReverseRotationAroundZAxisStates, mCurrentState); 96 } 97 98 @Override onStateChanged(int state)99 public void onStateChanged(int state) { 100 mCurrentState = state; 101 102 final DeviceState deviceState; 103 if (ArrayUtils.contains(mHalfFoldedDeviceStates, state)) { 104 deviceState = DeviceState.HALF_FOLDED; 105 } else if (ArrayUtils.contains(mFoldedDeviceStates, state)) { 106 deviceState = DeviceState.FOLDED; 107 } else if (ArrayUtils.contains(mRearDisplayDeviceStates, state)) { 108 deviceState = DeviceState.REAR; 109 } else if (ArrayUtils.contains(mOpenDeviceStates, state)) { 110 deviceState = DeviceState.OPEN; 111 } else { 112 deviceState = DeviceState.UNKNOWN; 113 } 114 115 if (mLastDeviceState == null || !mLastDeviceState.equals(deviceState)) { 116 mLastDeviceState = deviceState; 117 118 for (Consumer<DeviceState> callback : mDeviceStateCallbacks) { 119 callback.accept(mLastDeviceState); 120 } 121 } 122 } 123 } 124