1 /*
2  * Copyright (C) 2024 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.bedstead.nene.display
18 
19 import android.app.UiModeManager
20 import android.view.Surface
21 import androidx.test.platform.app.InstrumentationRegistry
22 import androidx.test.uiautomator.UiDevice
23 import com.android.bedstead.nene.TestApis
24 import com.android.bedstead.permissions.CommonPermissions.MODIFY_DAY_NIGHT_MODE
25 
26 /**
27  * Access Test APIs related to device display settings.
28  */
displaynull29 fun TestApis.display() = Display
30 
31 /**
32  * Helper methods related to the display settings of device.
33  */
34 object Display {
35 
36     private const val USER_ROTATION_KEY = "user_rotation"
37 
38     /**
39      * Enables and disables the dark mode of the device depending on [displayTheme].
40      */
41     fun setDisplayTheme(displayTheme: DisplayProperties.Theme) {
42         TestApis.permissions().withPermission(MODIFY_DAY_NIGHT_MODE).use {
43             TestApis.context().androidContextAsUser(TestApis.users().system()).getSystemService(
44                 UiModeManager::class.java)?.nightMode = getUiModeNightValue(displayTheme)
45         }
46     }
47 
48     /**
49      * Gets the device display theme. The values could be one of [DisplayProperties.Theme].
50      */
51     fun getDisplayTheme(): DisplayProperties.Theme {
52         TestApis.permissions().withPermission(MODIFY_DAY_NIGHT_MODE).use {
53             val uiMode = TestApis.context().androidContextAsUser(
54                 TestApis.users().system()).getSystemService(
55                 UiModeManager::class.java)?.nightMode ?: error("Unable to fetch nightMode value")
56             return when (uiMode) {
57                 UiModeManager.MODE_NIGHT_NO -> DisplayProperties.Theme.LIGHT
58                 UiModeManager.MODE_NIGHT_YES -> DisplayProperties.Theme.DARK
59                 else -> throw Exception("Unsupported display theme value $uiMode")
60             }
61         }
62     }
63 
64     /**
65      * Sets the screen orientation of the device.
66      */
67     fun setScreenOrientation(orientation: DisplayProperties.ScreenOrientation) {
68         val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
69         when (orientation) {
70             DisplayProperties.ScreenOrientation.PORTRAIT -> device.setOrientationPortrait()
71             DisplayProperties.ScreenOrientation.LANDSCAPE -> device.setOrientationLandscape()
72         }
73     }
74 
75     /**
76      * Gets the screen orientation of the device.
77      */
78     fun getScreenOrientation(): DisplayProperties.ScreenOrientation {
79         val userRotationValue = TestApis.settings().system().getInt(USER_ROTATION_KEY)
80 
81         return when (userRotationValue) {
82             Surface.ROTATION_0 -> DisplayProperties.ScreenOrientation.PORTRAIT
83             Surface.ROTATION_90 -> DisplayProperties.ScreenOrientation.LANDSCAPE
84             else -> error("Unsupported user_rotation value $userRotationValue")
85         }
86     }
87 
88     private fun getUiModeNightValue(displayTheme: DisplayProperties.Theme): Int {
89         return when (displayTheme) {
90             DisplayProperties.Theme.DARK -> UiModeManager.MODE_NIGHT_YES
91             DisplayProperties.Theme.LIGHT -> UiModeManager.MODE_NIGHT_NO
92         }
93     }
94 }
95