1 /*
2  * Copyright (C) 2023 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.settingslib.devicestate
18 
19 import android.content.Context
20 import android.hardware.devicestate.DeviceState
21 import android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY
22 import android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY
23 import android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY
24 import android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN
25 import android.hardware.devicestate.DeviceStateManager
26 import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_FOLDED
27 import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_HALF_FOLDED
28 import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY
29 import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNFOLDED
30 import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNKNOWN
31 import android.provider.Settings.Secure.DeviceStateRotationLockKey
32 import com.android.internal.R
33 import android.hardware.devicestate.feature.flags.Flags as DeviceStateManagerFlags
34 
35 /** Helps to convert between device state and posture. */
36 class PosturesHelper(context: Context, deviceStateManager: DeviceStateManager?) {
37 
38     private val postures: Map<Int, List<Int>>
39 
40     init {
41         if (deviceStateManager != null && DeviceStateManagerFlags.deviceStatePropertyMigration()) {
42             postures =
<lambda>null43                 deviceStateManager.supportedDeviceStates.groupBy { it.toPosture() }
<lambda>null44                     .filterKeys { it != DEVICE_STATE_ROTATION_KEY_UNKNOWN }
<lambda>null45                     .mapValues { it.value.map { it.identifier }}
46         } else {
47             val foldedDeviceStates =
48                 context.resources.getIntArray(R.array.config_foldedDeviceStates).toList()
49             val halfFoldedDeviceStates =
50                 context.resources.getIntArray(R.array.config_halfFoldedDeviceStates).toList()
51             val unfoldedDeviceStates =
52                 context.resources.getIntArray(R.array.config_openDeviceStates).toList()
53             val rearDisplayDeviceStates =
54                 context.resources.getIntArray(R.array.config_rearDisplayDeviceStates).toList()
55 
56             postures =
57                 mapOf(
58                     DEVICE_STATE_ROTATION_KEY_FOLDED to foldedDeviceStates,
59                     DEVICE_STATE_ROTATION_KEY_HALF_FOLDED to halfFoldedDeviceStates,
60                     DEVICE_STATE_ROTATION_KEY_UNFOLDED to unfoldedDeviceStates,
61                     DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY to rearDisplayDeviceStates
62                 )
63         }
64     }
65 
66     @DeviceStateRotationLockKey
deviceStateToPosturenull67     fun deviceStateToPosture(deviceState: Int): Int {
68         return postures.filterValues { it.contains(deviceState) }.keys.firstOrNull()
69             ?: DEVICE_STATE_ROTATION_KEY_UNKNOWN
70     }
71 
postureToDeviceStatenull72     fun postureToDeviceState(@DeviceStateRotationLockKey posture: Int): Int? {
73         return postures[posture]?.firstOrNull()
74     }
75 
76     /**
77      * Maps a [DeviceState] to the corresponding [DeviceStateRotationLockKey] value based on the
78      * properties of the state.
79      */
80     @DeviceStateRotationLockKey
toPosturenull81     private fun DeviceState.toPosture(): Int {
82         return if (hasProperty(PROPERTY_FEATURE_REAR_DISPLAY)) {
83             DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY
84         } else if (hasProperty(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY)) {
85             DEVICE_STATE_ROTATION_KEY_FOLDED
86         } else if (hasProperties(
87                 PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
88                 PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN
89             )) {
90             DEVICE_STATE_ROTATION_KEY_HALF_FOLDED
91         } else if (hasProperty(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY)) {
92             DEVICE_STATE_ROTATION_KEY_UNFOLDED
93         } else {
94             DEVICE_STATE_ROTATION_KEY_UNKNOWN
95         }
96     }
97 }
98