Skip to content

Commit eb66819

Browse files
Paige McAuliffecopybara-androidxtest
authored andcommitted
Check initial device state in FlatModeAction and ClosedModeAction and return if the device is already in the requested device mode
PiperOrigin-RevId: 534474498
1 parent 1874199 commit eb66819

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

espresso/device/java/androidx/test/espresso/device/action/ClosedModeAction.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,30 @@
1616

1717
package androidx.test.espresso.device.action
1818

19+
import android.util.Log
1920
import androidx.test.espresso.device.context.ActionContext
2021
import androidx.test.espresso.device.controller.DeviceMode
22+
import androidx.test.espresso.device.util.executeShellCommand
23+
import androidx.test.espresso.device.util.getMapOfDeviceStateNamesToIdentifiers
2124
import androidx.test.platform.device.DeviceController
2225
import java.util.concurrent.Executor
2326

2427
/** Action to set the test device to be closed. */
2528
internal class ClosedModeAction(private val mainExecutor: Executor) :
2629
BaseSingleFoldDeviceAction(DeviceMode.CLOSED, null, mainExecutor) {
2730
override fun perform(context: ActionContext, deviceController: DeviceController) {
28-
// TODO(b/203801760): Check current device mode and return if already in closed mode.
31+
val currentDeviceStateIdentifier = executeShellCommand("cmd device_state print-state").trim()
32+
if (currentDeviceStateIdentifier == getMapOfDeviceStateNamesToIdentifiers().get("CLOSED")) {
33+
if (Log.isLoggable(TAG, Log.DEBUG)) {
34+
Log.d(TAG, "Device is already in closed mode.")
35+
}
36+
return
37+
}
38+
2939
super.perform(context, deviceController)
3040
}
41+
42+
companion object {
43+
private val TAG = ClosedModeAction::class.java.simpleName
44+
}
3145
}

espresso/device/java/androidx/test/espresso/device/action/FlatModeAction.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616

1717
package androidx.test.espresso.device.action
1818

19+
import android.util.Log
1920
import androidx.test.espresso.device.context.ActionContext
2021
import androidx.test.espresso.device.controller.DeviceMode
22+
import androidx.test.espresso.device.util.executeShellCommand
23+
import androidx.test.espresso.device.util.getMapOfDeviceStateNamesToIdentifiers
2124
import androidx.test.platform.device.DeviceController
2225
import androidx.window.layout.FoldingFeature
2326
import java.util.concurrent.Executor
@@ -26,7 +29,18 @@ import java.util.concurrent.Executor
2629
internal class FlatModeAction(private val mainExecutor: Executor) :
2730
BaseSingleFoldDeviceAction(DeviceMode.FLAT, FoldingFeature.State.FLAT, mainExecutor) {
2831
override fun perform(context: ActionContext, deviceController: DeviceController) {
29-
// TODO(b/203801760): Check current device mode and return if already in flat mode.
32+
val currentDeviceStateIdentifier = executeShellCommand("cmd device_state print-state").trim()
33+
if (currentDeviceStateIdentifier == getMapOfDeviceStateNamesToIdentifiers().get("OPENED")) {
34+
if (Log.isLoggable(TAG, Log.DEBUG)) {
35+
Log.d(TAG, "Device is already in flat mode.")
36+
}
37+
return
38+
}
39+
3040
super.perform(context, deviceController)
3141
}
42+
43+
companion object {
44+
private val TAG = FlatModeAction::class.java.simpleName
45+
}
3246
}

espresso/device/java/androidx/test/espresso/device/util/DeviceUtil.kt

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package androidx.test.espresso.device.util
2020

2121
import android.os.Build
2222
import androidx.annotation.RestrictTo
23+
import java.util.regex.Pattern
2324

2425
/** Collection of utility methods for getting information about the test device. */
2526

@@ -57,3 +58,56 @@ fun isRobolectricTest(): Boolean {
5758
fun getDeviceApiLevel(): Int {
5859
return Build.VERSION.SDK_INT
5960
}
61+
62+
/**
63+
* Maps device state names to identifiers by processing the output of "device_state print-states"
64+
*
65+
* The output of "cmd device_state print-states" contains names and identifiers of supported device
66+
* states, as shown below.
67+
* [ DeviceState{identifier=1, name='CLOSED'}, DeviceState{identifier=2, name='HALF_OPENED'}, DeviceState{identifier=3, name='OPENED'}, ]
68+
* This method returns a map where the keys are the device state names and the values are the device
69+
* state identifiers.
70+
*
71+
* @hide
72+
*/
73+
@RestrictTo(RestrictTo.Scope.LIBRARY)
74+
fun getMapOfDeviceStateNamesToIdentifiers(): MutableMap<String, String> {
75+
if (getDeviceApiLevel() < 24) {
76+
// Executing shell commands requires API 24+. There are no foldable devices with API 23 or
77+
// below, so return an empty map.
78+
return mutableMapOf()
79+
}
80+
val deviceStateNameToIdentifier: MutableMap<String, String> = mutableMapOf()
81+
// Regex pattern that matches supported states, e.g. DeviceState{identifier=1, name='CLOSED',
82+
// app_accessible=true}
83+
val DEVICE_STATE_PATTERN_EXTRA_PARAMS: Pattern =
84+
Pattern.compile("DeviceState\\{identifier=(?<identifier>\\d+), name='(?<name>\\w+?)'.+?\\}")
85+
// Regex pattern that matches supported states, e.g. DeviceState{identifier=1, name='CLOSED'}
86+
val DEVICE_STATE_PATTERN_NO_EXTRA_PARAMS: Pattern =
87+
Pattern.compile("DeviceState\\{identifier=(?<identifier>\\d+), name='(?<name>\\w+?)'\\}")
88+
val supportedDeviceStates = listOf("CLOSED", "HALF_OPENED", "OPENED")
89+
90+
val printedStates = executeShellCommand("cmd device_state print-states")
91+
val lines = printedStates.split("\n")
92+
for (line in lines) {
93+
val matcherExtraParams = DEVICE_STATE_PATTERN_EXTRA_PARAMS.matcher(line)
94+
val matcherNoExtraParams = DEVICE_STATE_PATTERN_NO_EXTRA_PARAMS.matcher(line)
95+
var deviceStateName: String? = null
96+
var deviceStateIdentifier: String? = null
97+
if (matcherExtraParams.find()) {
98+
deviceStateName = matcherExtraParams.group("name")
99+
deviceStateIdentifier = matcherExtraParams.group("identifier")
100+
} else if (matcherNoExtraParams.find()) {
101+
deviceStateName = matcherNoExtraParams.group("name")
102+
deviceStateIdentifier = matcherNoExtraParams.group("identifier")
103+
}
104+
if (
105+
deviceStateName != null &&
106+
deviceStateIdentifier != null &&
107+
deviceStateName in supportedDeviceStates
108+
) {
109+
deviceStateNameToIdentifier.put(deviceStateName, deviceStateIdentifier)
110+
}
111+
}
112+
return deviceStateNameToIdentifier
113+
}

0 commit comments

Comments
 (0)