1 /* 2 * Copyright (C) 2021 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 android.hardware.devicestate.cts; 18 19 import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE; 20 import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE; 21 import static android.server.wm.DeviceStateUtils.assertValidState; 22 import static android.server.wm.DeviceStateUtils.runWithControlDeviceStatePermission; 23 import static android.view.Display.DEFAULT_DISPLAY; 24 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertTrue; 28 import static org.junit.Assume.assumeFalse; 29 import static org.junit.Assume.assumeTrue; 30 import static org.mockito.Mockito.atLeastOnce; 31 import static org.mockito.Mockito.mock; 32 import static org.mockito.Mockito.timeout; 33 import static org.mockito.Mockito.verify; 34 35 import android.content.Context; 36 import android.content.res.Resources; 37 import android.hardware.devicestate.DeviceStateManager; 38 import android.hardware.devicestate.DeviceStateRequest; 39 import android.server.wm.jetpack.utils.ExtensionUtil; 40 import android.server.wm.jetpack.utils.Version; 41 42 import androidx.test.ext.junit.runners.AndroidJUnit4; 43 import androidx.test.platform.app.InstrumentationRegistry; 44 45 import com.android.compatibility.common.util.ApiTest; 46 import com.android.compatibility.common.util.PollingCheck; 47 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 import org.mockito.ArgumentCaptor; 51 52 import java.util.HashSet; 53 import java.util.Set; 54 import java.util.concurrent.Executor; 55 56 /** CTS tests for {@link DeviceStateManager} API(s). */ 57 @RunWith(AndroidJUnit4.class) 58 public class DeviceStateManagerTests extends DeviceStateManagerTestBase { 59 60 public static final int TIMEOUT = 2000; 61 62 private static final int INVALID_DEVICE_STATE = -1; 63 64 /** Vendor extension version. Some API behaviors are only available in newer version. */ 65 private static final Version WM_EXTENSION_VERSION = ExtensionUtil.getExtensionVersion(); 66 67 /** 68 * Tests that {@link DeviceStateManager#getSupportedStates()} returns at least one state and 69 * that none of the returned states are in the range 70 * [{@link #MINIMUM_DEVICE_STATE}, {@link #MAXIMUM_DEVICE_STATE}]. 71 */ 72 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#getSupportedStates"}) 73 @Test testValidSupportedStates()74 public void testValidSupportedStates() throws Exception { 75 final int[] supportedStates = getDeviceStateManager().getSupportedStates(); 76 assertTrue(supportedStates.length > 0); 77 78 for (int i = 0; i < supportedStates.length; i++) { 79 final int state = supportedStates[i]; 80 assertValidState(state); 81 } 82 } 83 84 /** 85 * Tests that calling {@link DeviceStateManager#requestState(DeviceStateRequest, Executor, 86 * DeviceStateRequest.Callback)} is successful and results in a registered callback being 87 * triggered with a value equal to the requested state. 88 */ 89 @ApiTest(apis = { 90 "android.hardware.devicestate.DeviceStateManager#getSupportedStates", 91 "android.hardware.devicestate.DeviceStateManager#requestState"}) 92 @Test testRequestAllSupportedStates()93 public void testRequestAllSupportedStates() throws Throwable { 94 final ArgumentCaptor<Integer> intAgumentCaptor = ArgumentCaptor.forClass(Integer.class); 95 final DeviceStateManager.DeviceStateCallback callback 96 = mock(DeviceStateManager.DeviceStateCallback.class); 97 final DeviceStateManager manager = getDeviceStateManager(); 98 manager.registerCallback(Runnable::run, callback); 99 100 final int[] supportedStates = manager.getSupportedStates(); 101 for (int i = 0; i < supportedStates.length; i++) { 102 final DeviceStateRequest request 103 = DeviceStateRequest.newBuilder(supportedStates[i]).build(); 104 105 runWithRequestActive(request, false, () -> { 106 verify(callback, atLeastOnce()).onStateChanged(intAgumentCaptor.capture()); 107 assertEquals(intAgumentCaptor.getValue().intValue(), request.getState()); 108 }); 109 } 110 } 111 112 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#requestBaseStateOverride"}) 113 @Test testRequestBaseState()114 public void testRequestBaseState() throws Throwable { 115 final ArgumentCaptor<Integer> intAgumentCaptor = ArgumentCaptor.forClass(Integer.class); 116 final DeviceStateManager.DeviceStateCallback callback = 117 mock(DeviceStateManager.DeviceStateCallback.class); 118 final DeviceStateManager manager = getDeviceStateManager(); 119 120 manager.registerCallback(Runnable::run, callback); 121 122 DeviceStateRequest request = DeviceStateRequest.newBuilder(0).build(); 123 runWithRequestActive(request, true, () -> { 124 verify(callback, atLeastOnce()).onStateChanged(intAgumentCaptor.capture()); 125 assertEquals(intAgumentCaptor.getValue().intValue(), request.getState()); 126 }); 127 } 128 129 /** 130 * Tests that calling {@link DeviceStateManager#requestState(DeviceStateRequest, Executor, 131 * DeviceStateRequest.Callback)} throws an {@link java.lang.IllegalArgumentException} if 132 * supplied with a state above {@link MAXIMUM_DEVICE_STATE}. 133 */ 134 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#requestState"}) 135 @Test(expected = IllegalArgumentException.class) testRequestStateTooLarge()136 public void testRequestStateTooLarge() throws Throwable { 137 final DeviceStateManager manager = getDeviceStateManager(); 138 final DeviceStateRequest request 139 = DeviceStateRequest.newBuilder(MAXIMUM_DEVICE_STATE + 1).build(); 140 runWithControlDeviceStatePermission(() -> manager.requestState(request, null, null)); 141 } 142 143 /** 144 * Tests that calling {@link DeviceStateManager#requestState(DeviceStateRequest, Executor, 145 * DeviceStateRequest.Callback)} throws an {@link java.lang.IllegalArgumentException} if 146 * supplied with a state below {@link MINIMUM_DEVICE_STATE}. 147 */ 148 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#requestState"}) 149 @Test(expected = IllegalArgumentException.class) testRequestStateTooSmall()150 public void testRequestStateTooSmall() throws Throwable { 151 final DeviceStateManager manager = getDeviceStateManager(); 152 final DeviceStateRequest request 153 = DeviceStateRequest.newBuilder(MINIMUM_DEVICE_STATE - 1).build(); 154 runWithControlDeviceStatePermission(() -> manager.requestState(request, null, null)); 155 } 156 157 /** 158 * Tests that calling {@link DeviceStateManager#requestState(DeviceStateRequest, Executor, 159 * DeviceStateRequest.Callback)} is not successful and results in a failure to change the 160 * state of the device due to the state requested not being available for apps to request. 161 */ 162 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#requestState"}) 163 @Test testRequestStateFailsAsTopApp_ifStateNotDefinedAsAvailableForAppsToRequest()164 public void testRequestStateFailsAsTopApp_ifStateNotDefinedAsAvailableForAppsToRequest() 165 throws IllegalArgumentException { 166 final DeviceStateManager manager = getDeviceStateManager(); 167 final int[] supportedStates = manager.getSupportedStates(); 168 // We want to verify that the app can change device state 169 // So we only attempt if there are more than 1 possible state. 170 assumeTrue(supportedStates.length > 1); 171 Set<Integer> statesAvailableToRequest = getAvailableStatesToRequest( 172 InstrumentationRegistry.getInstrumentation().getTargetContext(), supportedStates); 173 // checks that not every state is available for an app to request 174 assumeTrue(statesAvailableToRequest.size() < supportedStates.length); 175 176 Set<Integer> availableDeviceStates = generateDeviceStateSet(supportedStates); 177 178 final StateTrackingCallback callback = new StateTrackingCallback(); 179 manager.registerCallback(Runnable::run, callback); 180 PollingCheck.waitFor(TIMEOUT, () -> callback.mCurrentState != INVALID_DEVICE_STATE); 181 final TestActivitySession<DeviceStateTestActivity> activitySession = 182 createManagedTestActivitySession(); 183 184 activitySession.launchTestActivityOnDisplaySync( 185 DeviceStateTestActivity.class, 186 DEFAULT_DISPLAY 187 ); 188 189 DeviceStateTestActivity activity = activitySession.getActivity(); 190 191 Set<Integer> possibleStates = possibleStates(false /* shouldSucceed */, 192 availableDeviceStates, 193 statesAvailableToRequest); 194 int nextState = calculateDifferentState(callback.mCurrentState, possibleStates); 195 // checks that we were able to find a valid state to request. 196 assumeTrue(nextState != INVALID_DEVICE_STATE); 197 198 activity.requestDeviceStateChange(nextState); 199 200 assertTrue(activity.requestStateFailed); 201 } 202 203 /** 204 * Tests that calling {@link DeviceStateManager#requestState(DeviceStateRequest, Executor, 205 * DeviceStateRequest.Callback)} is successful and results in a registered callback being 206 * triggered with a value equal to the requested state. 207 */ 208 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#requestState"}) 209 @Test testRequestStateSucceedsAsTopApp_ifStateDefinedAsAvailableForAppsToRequest()210 public void testRequestStateSucceedsAsTopApp_ifStateDefinedAsAvailableForAppsToRequest() 211 throws Throwable { 212 final DeviceStateManager manager = getDeviceStateManager(); 213 final int[] supportedStates = manager.getSupportedStates(); 214 215 // We want to verify that the app can change device state 216 // So we only attempt if there are more than 1 possible state. 217 assumeTrue(supportedStates.length > 1); 218 Set<Integer> statesAvailableToRequest = getAvailableStatesToRequest( 219 InstrumentationRegistry.getInstrumentation().getTargetContext(), supportedStates); 220 assumeTrue(statesAvailableToRequest.size() > 0); 221 222 Set<Integer> availableDeviceStates = generateDeviceStateSet(supportedStates); 223 224 final StateTrackingCallback callback = new StateTrackingCallback(); 225 manager.registerCallback(Runnable::run, callback); 226 PollingCheck.waitFor(TIMEOUT, () -> callback.mCurrentState != INVALID_DEVICE_STATE); 227 final TestActivitySession<DeviceStateTestActivity> activitySession = 228 createManagedTestActivitySession(); 229 230 activitySession.launchTestActivityOnDisplaySync( 231 DeviceStateTestActivity.class, 232 DEFAULT_DISPLAY 233 ); 234 235 DeviceStateTestActivity activity = activitySession.getActivity(); 236 237 Set<Integer> possibleStates = possibleStates(true /* shouldSucceed */, 238 availableDeviceStates, 239 statesAvailableToRequest); 240 int nextState = calculateDifferentState(callback.mCurrentState, possibleStates); 241 // checks that we were able to find a valid state to request. 242 assumeTrue(nextState != INVALID_DEVICE_STATE); 243 244 runWithControlDeviceStatePermission(() -> activity.requestDeviceStateChange(nextState)); 245 246 PollingCheck.waitFor(TIMEOUT, () -> callback.mCurrentState == nextState); 247 248 assertEquals(nextState, callback.mCurrentState); 249 assertFalse(activity.requestStateFailed); 250 251 manager.cancelStateRequest(); // reset device state after successful request 252 } 253 254 /** 255 * Tests that calling {@link DeviceStateManager#requestState} is unsuccessful and results in a 256 * failure to update the state of the device as expected since the activity is backgrounded. 257 */ 258 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#requestState"}) 259 @Test testRequestStateFailsAsBackgroundApp()260 public void testRequestStateFailsAsBackgroundApp() throws IllegalArgumentException { 261 final DeviceStateManager manager = getDeviceStateManager(); 262 final int[] supportedStates = manager.getSupportedStates(); 263 // We want to verify that the app can change device state 264 // So we only attempt if there are more than 1 possible state. 265 assumeTrue(supportedStates.length > 1); 266 Set<Integer> statesAvailableToRequest = getAvailableStatesToRequest( 267 InstrumentationRegistry.getInstrumentation().getTargetContext(), supportedStates); 268 assumeTrue(statesAvailableToRequest.size() > 0); 269 270 Set<Integer> availableDeviceStates = generateDeviceStateSet(supportedStates); 271 272 final StateTrackingCallback callback = new StateTrackingCallback(); 273 manager.registerCallback(Runnable::run, callback); 274 PollingCheck.waitFor(TIMEOUT, () -> callback.mCurrentState != INVALID_DEVICE_STATE); 275 276 final TestActivitySession<DeviceStateTestActivity> activitySession = 277 createManagedTestActivitySession(); 278 activitySession.launchTestActivityOnDisplaySync( 279 DeviceStateTestActivity.class, 280 DEFAULT_DISPLAY 281 ); 282 283 DeviceStateTestActivity activity = activitySession.getActivity(); 284 assertFalse(activity.requestStateFailed); 285 286 launchHomeActivity(); // places our test activity in the background 287 288 Set<Integer> possibleStates = possibleStates(true /* shouldSucceed */, 289 availableDeviceStates, 290 statesAvailableToRequest); 291 int nextState = calculateDifferentState(callback.mCurrentState, possibleStates); 292 // checks that we were able to find a valid state to request. 293 assumeTrue(nextState != INVALID_DEVICE_STATE); 294 295 activity.requestDeviceStateChange(nextState); 296 297 assertTrue(activity.requestStateFailed); 298 } 299 300 /** 301 * Tests that calling {@link DeviceStateManager#cancelStateRequest} is successful and results 302 * in a registered callback being triggered with a value equal to the base state. 303 */ 304 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#cancelStateRequest"}) 305 @Test testCancelStateRequestFromNewActivity()306 public void testCancelStateRequestFromNewActivity() throws Throwable { 307 final DeviceStateManager manager = getDeviceStateManager(); 308 final int[] supportedStates = manager.getSupportedStates(); 309 // We want to verify that the app can change device state 310 // So we only attempt if there are more than 1 possible state. 311 assumeTrue(supportedStates.length > 1); 312 Set<Integer> statesAvailableToRequest = getAvailableStatesToRequest( 313 InstrumentationRegistry.getInstrumentation().getTargetContext(), supportedStates); 314 assumeFalse(statesAvailableToRequest.isEmpty()); 315 316 Set<Integer> availableDeviceStates = generateDeviceStateSet(supportedStates); 317 318 final StateTrackingCallback callback = new StateTrackingCallback(); 319 manager.registerCallback(Runnable::run, callback); 320 PollingCheck.waitFor(TIMEOUT, () -> callback.mCurrentState != INVALID_DEVICE_STATE); 321 final TestActivitySession<DeviceStateTestActivity> activitySession = 322 createManagedTestActivitySession(); 323 324 activitySession.launchTestActivityOnDisplaySync( 325 DeviceStateTestActivity.class, 326 DEFAULT_DISPLAY 327 ); 328 329 final DeviceStateTestActivity activity = activitySession.getActivity(); 330 331 int originalState = callback.mCurrentState; 332 333 Set<Integer> possibleStates = possibleStates(true /* shouldSucceed */, 334 availableDeviceStates, 335 statesAvailableToRequest); 336 int nextState = calculateDifferentState(callback.mCurrentState, possibleStates); 337 // checks that we were able to find a valid state to request. 338 assumeTrue(nextState != INVALID_DEVICE_STATE); 339 340 runWithControlDeviceStatePermission(() -> activity.requestDeviceStateChange(nextState)); 341 342 PollingCheck.waitFor(TIMEOUT, () -> callback.mCurrentState == nextState); 343 344 assertEquals(nextState, callback.mCurrentState); 345 assertFalse(activity.requestStateFailed); 346 347 activity.finish(); 348 349 final TestActivitySession<DeviceStateTestActivity> secondActivitySession = 350 createManagedTestActivitySession(); 351 secondActivitySession.launchTestActivityOnDisplaySync( 352 DeviceStateTestActivity.class, 353 DEFAULT_DISPLAY 354 ); 355 // Assumes that the overridden state is still active after finishing 356 // and launching the second activity. This due to some states may be cancelled 357 // if they have the FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP flag on them. 358 // TODO(b/305107721): Update this call when we can verify we're moving to a state 359 // that does not have the FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP flag. 360 assumeTrue(nextState == callback.mCurrentState); 361 362 final DeviceStateTestActivity activity2 = secondActivitySession.getActivity(); 363 activity2.cancelOverriddenState(); 364 365 PollingCheck.waitFor(TIMEOUT, () -> callback.mCurrentState == originalState); 366 367 assertEquals(originalState, callback.mCurrentState); 368 } 369 370 371 /** 372 * Reads in the states that are available to be requested by apps from the configuration file 373 * and returns a set of all valid states that are read in. 374 * 375 * @param context The context used to get the configuration values from {@link Resources} 376 * @param supportedStates The device states that are supported on that device. 377 * @return {@link Set} of valid device states that are read in. 378 */ getAvailableStatesToRequest(Context context, int[] supportedStates)379 private static Set<Integer> getAvailableStatesToRequest(Context context, 380 int[] supportedStates) { 381 Set<Integer> availableStatesToRequest = new HashSet<>(); 382 String[] availableStateIdentifiers = context.getResources().getStringArray( 383 Resources.getSystem().getIdentifier("config_deviceStatesAvailableForAppRequests", 384 "array", 385 "android")); 386 for (String identifier : availableStateIdentifiers) { 387 int stateIdentifier = context.getResources() 388 .getIdentifier(identifier, "integer", "android"); 389 int state = context.getResources().getInteger(stateIdentifier); 390 if (isValidState(state, supportedStates)) { 391 availableStatesToRequest.add(context.getResources().getInteger(stateIdentifier)); 392 } 393 } 394 return availableStatesToRequest; 395 } 396 isValidState(int state, int[] supportedStates)397 private static boolean isValidState(int state, int[] supportedStates) { 398 for (int i = 0; i < supportedStates.length; i++) { 399 if (state == supportedStates[i]) { 400 return true; 401 } 402 } 403 return false; 404 } 405 406 /** 407 * Generates a set of possible device states based on a {@link Set} of valid device states, 408 * {@code supportedDeviceStates}, and the set of device states available to be requested 409 * {@code availableStatesToRequest}, as well as if the request should succeed or not, given by 410 * {@code shouldSucceed}. 411 * 412 * If {@code shouldSucceed} is {@code true}, we only return device states that are available, 413 * and if it is {@code false}, we only return non available device states. 414 * 415 * @param availableStatesToRequest The states that are available to be requested from an app 416 * @param shouldSucceed Should the request succeed or not, to determine what states we return 417 * @param supportedDeviceStates All states supported on the device. 418 * {@throws} an {@link IllegalArgumentException} if {@code availableStatesToRequest} includes 419 * non-valid device states. 420 */ possibleStates(boolean shouldSucceed, Set<Integer> supportedDeviceStates, Set<Integer> availableStatesToRequest)421 private static Set<Integer> possibleStates(boolean shouldSucceed, 422 Set<Integer> supportedDeviceStates, 423 Set<Integer> availableStatesToRequest) { 424 425 if (!supportedDeviceStates.containsAll(availableStatesToRequest)) { 426 throw new IllegalArgumentException("Available states include invalid device states"); 427 } 428 429 Set<Integer> availableStates = new HashSet<>(supportedDeviceStates); 430 431 if (shouldSucceed) { 432 availableStates.retainAll(availableStatesToRequest); 433 } else { 434 availableStates.removeAll(availableStatesToRequest); 435 } 436 437 return availableStates; 438 } 439 440 /** 441 * Determines what state we should request that isn't the current state, and is included 442 * in {@code possibleStates}. If there is no state that fits these requirements, we return 443 * {@link INVALID_DEVICE_STATE}. 444 * 445 * @param currentState The current state of the device 446 * @param possibleStates States that we can request 447 */ calculateDifferentState(int currentState, Set<Integer> possibleStates)448 private static int calculateDifferentState(int currentState, Set<Integer> possibleStates) { 449 if (possibleStates.isEmpty()) { 450 return INVALID_DEVICE_STATE; 451 } 452 if (possibleStates.size() == 1 && possibleStates.contains(currentState)) { 453 return INVALID_DEVICE_STATE; 454 } 455 for (int state: possibleStates) { 456 if (state != currentState) { 457 return state; 458 } 459 } 460 return INVALID_DEVICE_STATE; 461 } 462 463 /** 464 * Creates a {@link Set} of values that are in the {@code states} array. 465 * 466 * Used to create a {@link Set} from the available device states that {@link DeviceStateManager} 467 * returns as an array. 468 * 469 * @param states Device states that are supported on the device 470 */ generateDeviceStateSet(int[] states)471 private static Set<Integer> generateDeviceStateSet(int[] states) { 472 Set<Integer> supportedStates = new HashSet<>(); 473 for (int i = 0; i < states.length; i++) { 474 supportedStates.add(states[i]); 475 } 476 return supportedStates; 477 } 478 479 /** 480 * Tests that calling {@link DeviceStateManager#requestState()} throws a 481 * {@link java.lang.SecurityException} without the 482 * {@link android.Manifest.permission.CONTROL_DEVICE_STATE} permission held. 483 */ 484 @Test(expected = SecurityException.class) 485 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#requestState"}) testRequestStateWithoutPermission()486 public void testRequestStateWithoutPermission() { 487 final DeviceStateManager manager = getDeviceStateManager(); 488 final int[] states = manager.getSupportedStates(); 489 final DeviceStateRequest request = DeviceStateRequest.newBuilder(states[0]).build(); 490 manager.requestState(request, null, null); 491 } 492 493 /** 494 * Tests that calling {@link DeviceStateManager#cancelStateRequest} throws a 495 * {@link java.lang.SecurityException} without the 496 * {@link android.Manifest.permission.CONTROL_DEVICE_STATE} permission held. 497 */ 498 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#cancelStateRequest"}) 499 @Test(expected = SecurityException.class) testCancelOverrideRequestWithoutPermission()500 public void testCancelOverrideRequestWithoutPermission() throws Throwable { 501 final DeviceStateManager manager = getDeviceStateManager(); 502 final int[] states = manager.getSupportedStates(); 503 final DeviceStateRequest request = DeviceStateRequest.newBuilder(states[0]).build(); 504 runWithRequestActive(request, false, manager::cancelStateRequest); 505 } 506 507 /** 508 * Tests that callbacks added with {@link DeviceStateManager#registerDeviceStateCallback()} are 509 * supplied with an initial callback that contains the state at the time of registration. 510 */ 511 @ApiTest(apis = {"android.hardware.devicestate.DeviceStateManager#registerCallback"}) 512 @Test testRegisterCallbackSuppliesInitialValue()513 public void testRegisterCallbackSuppliesInitialValue() throws InterruptedException { 514 final ArgumentCaptor<int[]> intArrayAgumentCaptor = ArgumentCaptor.forClass(int[].class); 515 final ArgumentCaptor<Integer> intAgumentCaptor = ArgumentCaptor.forClass(Integer.class); 516 517 final DeviceStateManager.DeviceStateCallback callback 518 = mock(DeviceStateManager.DeviceStateCallback.class); 519 final DeviceStateManager manager = getDeviceStateManager(); 520 manager.registerCallback(Runnable::run, callback); 521 522 verify(callback, timeout(CALLBACK_TIMEOUT_MS)).onStateChanged(intAgumentCaptor.capture()); 523 assertValidState(intAgumentCaptor.getValue().intValue()); 524 525 verify(callback, timeout(CALLBACK_TIMEOUT_MS)) 526 .onBaseStateChanged(intAgumentCaptor.capture()); 527 assertValidState(intAgumentCaptor.getValue().intValue()); 528 529 verify(callback, timeout(CALLBACK_TIMEOUT_MS)) 530 .onSupportedStatesChanged(intArrayAgumentCaptor.capture()); 531 final int[] supportedStates = intArrayAgumentCaptor.getValue(); 532 assertTrue(supportedStates.length > 0); 533 for (int i = 0; i < supportedStates.length; i++) { 534 final int state = supportedStates[i]; 535 assertValidState(state); 536 } 537 } 538 539 private class StateTrackingCallback implements DeviceStateManager.DeviceStateCallback { 540 private int mCurrentState = - 1; 541 542 @Override onStateChanged(int state)543 public void onStateChanged(int state) { 544 mCurrentState = state; 545 } 546 } 547 } 548