@@ -20,6 +20,7 @@ package androidx.test.espresso.device.util
2020
2121import android.os.Build
2222import 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 {
5758fun 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