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 android.virtualdevice.cts; 18 19 import static android.Manifest.permission.ACTIVITY_EMBEDDING; 20 import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY; 21 import static android.Manifest.permission.CREATE_VIRTUAL_DEVICE; 22 import static android.Manifest.permission.WAKE_LOCK; 23 import static android.content.Context.DEVICE_ID_DEFAULT; 24 import static android.content.Context.DEVICE_ID_INVALID; 25 import static android.view.Display.DEFAULT_DISPLAY; 26 import static android.virtualdevice.cts.util.VirtualDeviceTestUtils.createActivityOptions; 27 28 import static androidx.test.core.app.ApplicationProvider.getApplicationContext; 29 30 import static com.google.common.truth.Truth.assertThat; 31 32 import static org.junit.Assert.assertThrows; 33 import static org.junit.Assume.assumeTrue; 34 import static org.mockito.ArgumentMatchers.eq; 35 import static org.mockito.Mockito.timeout; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.verifyNoMoreInteractions; 38 39 import android.annotation.Nullable; 40 import android.app.Activity; 41 import android.app.Instrumentation; 42 import android.app.Instrumentation.ActivityMonitor; 43 import android.app.Service; 44 import android.companion.virtual.VirtualDeviceManager; 45 import android.companion.virtual.VirtualDeviceManager.VirtualDevice; 46 import android.companion.virtual.VirtualDeviceParams; 47 import android.content.Context; 48 import android.content.Intent; 49 import android.content.pm.PackageManager; 50 import android.hardware.display.DisplayManager; 51 import android.hardware.display.VirtualDisplay; 52 import android.os.Bundle; 53 import android.os.IBinder; 54 import android.platform.test.annotations.AppModeFull; 55 import android.view.Display; 56 import android.virtualdevice.cts.common.FakeAssociationRule; 57 import android.virtualdevice.cts.util.EmptyActivity; 58 import android.virtualdevice.cts.util.SecondActivity; 59 import android.virtualdevice.cts.util.TestService; 60 61 import androidx.test.ext.junit.runners.AndroidJUnit4; 62 import androidx.test.platform.app.InstrumentationRegistry; 63 import androidx.test.rule.ServiceTestRule; 64 65 import com.android.compatibility.common.util.AdoptShellPermissionsRule; 66 import com.android.compatibility.common.util.ApiTest; 67 68 import org.junit.After; 69 import org.junit.Before; 70 import org.junit.Rule; 71 import org.junit.Test; 72 import org.junit.runner.RunWith; 73 import org.mockito.Mock; 74 import org.mockito.MockitoAnnotations; 75 76 import java.util.ArrayList; 77 import java.util.List; 78 import java.util.concurrent.Executor; 79 import java.util.concurrent.TimeoutException; 80 import java.util.function.IntConsumer; 81 82 @RunWith(AndroidJUnit4.class) 83 @ApiTest(apis = {"android.content.Context#updateDeviceId", 84 "android.content.Context#unregisterDeviceIdChangeListener", 85 "android.content.Context#registerDeviceIdChangeListener"} 86 ) 87 @AppModeFull(reason = "VirtualDeviceManager cannot be accessed by instant apps") 88 public class DeviceAssociationTest { 89 90 private static final VirtualDeviceParams DEFAULT_VIRTUAL_DEVICE_PARAMS = 91 new VirtualDeviceParams.Builder().build(); 92 private static final int TIMEOUT_MILLIS = 3000; 93 94 private Executor mTestExecutor; 95 @Mock 96 private IntConsumer mDeviceChangeListener; 97 @Mock 98 private IntConsumer mDeviceChangeListener2; 99 private Display mDefaultDisplay; 100 private VirtualDisplay mVirtualDisplay; 101 @Mock 102 private VirtualDisplay.Callback mVirtualDisplayCallback; 103 @Mock 104 private VirtualDeviceManager.ActivityListener mActivityListener; 105 106 @Rule 107 public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( 108 InstrumentationRegistry.getInstrumentation().getUiAutomation(), 109 ACTIVITY_EMBEDDING, 110 ADD_ALWAYS_UNLOCKED_DISPLAY, 111 CREATE_VIRTUAL_DEVICE, 112 WAKE_LOCK); 113 114 @Rule 115 public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule(); 116 117 private VirtualDeviceManager mVirtualDeviceManager; 118 @Nullable 119 private VirtualDevice mVirtualDevice; 120 private List<Activity> mActivities = new ArrayList(); 121 private List<VirtualDevice> mVirtualDevices = new ArrayList(); 122 123 @Before setUp()124 public void setUp() throws Exception { 125 MockitoAnnotations.initMocks(this); 126 Context context = getApplicationContext(); 127 final PackageManager packageManager = context.getPackageManager(); 128 assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP)); 129 assumeTrue(packageManager.hasSystemFeature( 130 PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS)); 131 mVirtualDeviceManager = context.getSystemService(VirtualDeviceManager.class); 132 mTestExecutor = context.getMainExecutor(); 133 final DisplayManager dm = context.getSystemService(DisplayManager.class); 134 mDefaultDisplay = dm.getDisplay(DEFAULT_DISPLAY); 135 mVirtualDevice = createVirtualDevice(); 136 mVirtualDevice.addActivityListener(context.getMainExecutor(), mActivityListener); 137 mVirtualDisplay = createVirtualDisplay(mVirtualDevice); 138 } 139 140 @After tearDown()141 public void tearDown() { 142 for (VirtualDevice virtualDevice : mVirtualDevices) { 143 virtualDevice.close(); 144 } 145 for (Activity activity : mActivities) { 146 activity.finish(); 147 activity.releaseInstance(); 148 } 149 } 150 151 @Test 152 @ApiTest(apis = {"android.content.Context#registerDeviceIdChangeListener"}) registerDeviceIdChangeListener_nullListener_throwsException()153 public void registerDeviceIdChangeListener_nullListener_throwsException() { 154 Context context = getApplicationContext(); 155 156 assertThrows( 157 NullPointerException.class, 158 () -> context.registerDeviceIdChangeListener(mTestExecutor, null)); 159 } 160 161 @Test 162 @ApiTest(apis = {"android.content.Context#registerDeviceIdChangeListener"}) registerDeviceIdChangeListener_nullExecutor_throwsException()163 public void registerDeviceIdChangeListener_nullExecutor_throwsException() { 164 Context context = getApplicationContext(); 165 166 assertThrows( 167 NullPointerException.class, 168 () -> context.registerDeviceIdChangeListener(null, mDeviceChangeListener)); 169 } 170 171 @Test 172 @ApiTest(apis = {"android.content.Context#unregisterDeviceIdChangeListener"}) registerDeviceIdChangeListener_registerTwice_throwsException()173 public void registerDeviceIdChangeListener_registerTwice_throwsException() { 174 Context context = getApplicationContext(); 175 176 context.registerDeviceIdChangeListener(mTestExecutor, mDeviceChangeListener); 177 178 assertThrows( 179 IllegalArgumentException.class, 180 () -> context.registerDeviceIdChangeListener(mTestExecutor, mDeviceChangeListener)); 181 } 182 183 @Test 184 @ApiTest(apis = {"android.content.Context#unregisterDeviceIdChangeListener"}) unregisterDeviceChangedListener_nullListener_throwsException()185 public void unregisterDeviceChangedListener_nullListener_throwsException() { 186 Context context = getApplicationContext(); 187 188 assertThrows( 189 NullPointerException.class, 190 () -> context.unregisterDeviceIdChangeListener(null)); 191 } 192 193 @Test 194 @ApiTest(apis = {"android.content.Context#unregisterDeviceIdChangeListener"}) unregisterDeviceChangedListener_succeeds()195 public void unregisterDeviceChangedListener_succeeds() { 196 Context context = getApplicationContext(); 197 context.registerDeviceIdChangeListener(mTestExecutor, mDeviceChangeListener); 198 199 context.updateDeviceId(mVirtualDevice.getDeviceId()); 200 201 assertThat(context.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 202 verify(mDeviceChangeListener, timeout(TIMEOUT_MILLIS)) 203 .accept(mVirtualDevice.getDeviceId()); 204 205 206 // DeviceId of listener is not updated after unregistering. 207 context.unregisterDeviceIdChangeListener(mDeviceChangeListener); 208 context.updateDeviceId(DEVICE_ID_DEFAULT); 209 210 assertThat(context.getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 211 verifyNoMoreInteractions(mDeviceChangeListener); 212 } 213 214 @Test 215 @ApiTest(apis = {"android.content.Context#updateDeviceId"}) updateDeviceId_invalidDeviceId_shouldThrowIllegalArgumentException()216 public void updateDeviceId_invalidDeviceId_shouldThrowIllegalArgumentException() { 217 Context context = getApplicationContext(); 218 219 assertThrows( 220 IllegalArgumentException.class, 221 () -> context.updateDeviceId(DEVICE_ID_INVALID)); 222 } 223 224 @Test 225 @ApiTest(apis = {"android.content.Context#updateDeviceId"}) updateDeviceId_missingDeviceId_shouldThrowIllegalArgumentException()226 public void updateDeviceId_missingDeviceId_shouldThrowIllegalArgumentException() { 227 Context context = getApplicationContext(); 228 229 assertThrows( 230 IllegalArgumentException.class, 231 () -> context.updateDeviceId(mVirtualDevice.getDeviceId() + 1)); 232 } 233 234 @Test 235 @ApiTest(apis = {"android.content.Context#updateDeviceId"}) updateDeviceId_defaultDeviceId()236 public void updateDeviceId_defaultDeviceId() { 237 Context context = getApplicationContext(); 238 239 context.updateDeviceId(DEVICE_ID_DEFAULT); 240 241 assertThat(context.getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 242 } 243 244 @Test 245 @ApiTest(apis = {"android.content.Context#updateDeviceId"}) updateDeviceId_validVirtualDeviceId()246 public void updateDeviceId_validVirtualDeviceId() { 247 Context context = getApplicationContext(); 248 249 context.updateDeviceId(mVirtualDevice.getDeviceId()); 250 251 assertThat(context.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 252 } 253 254 @Test 255 @ApiTest(apis = {"android.content.Context#updateDeviceId"}) updateDeviceId_convertToDeviceContext_overridesValue()256 public void updateDeviceId_convertToDeviceContext_overridesValue() { 257 Context context = getApplicationContext(); 258 259 context.updateDeviceId(mVirtualDevice.getDeviceId()); 260 assertThat(context.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 261 262 Context defaultDeviceContext = context.createDeviceContext(DEVICE_ID_DEFAULT); 263 264 assertThat(defaultDeviceContext.getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 265 } 266 267 @Test 268 @ApiTest(apis = {"android.content.Context#updateDeviceId"}) updateDeviceId_onDeviceContext_throwsException()269 public void updateDeviceId_onDeviceContext_throwsException() { 270 Context context = getApplicationContext(); 271 Context deviceContext = context.createDeviceContext(mVirtualDevice.getDeviceId()); 272 deviceContext.registerDeviceIdChangeListener(mTestExecutor, mDeviceChangeListener); 273 274 assertThrows( 275 UnsupportedOperationException.class, 276 () -> deviceContext.updateDeviceId(DEVICE_ID_DEFAULT)); 277 } 278 279 @Test 280 @ApiTest(apis = {"android.content.Context#updateDeviceId"}) updateDeviceId_notifiesListeners()281 public void updateDeviceId_notifiesListeners() { 282 Context context = getApplicationContext(); 283 context.registerDeviceIdChangeListener(mTestExecutor, mDeviceChangeListener); 284 context.registerDeviceIdChangeListener(mTestExecutor, mDeviceChangeListener2); 285 286 context.updateDeviceId(mVirtualDevice.getDeviceId()); 287 288 assertThat(context.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 289 verify(mDeviceChangeListener, timeout(TIMEOUT_MILLIS)).accept(mVirtualDevice.getDeviceId()); 290 verify(mDeviceChangeListener2, timeout(TIMEOUT_MILLIS)) 291 .accept(mVirtualDevice.getDeviceId()); 292 } 293 294 @Test 295 @ApiTest(apis = {"android.content.Context#updateDeviceId"}) updateDeviceId_sameId_DoesNotNotifyListeners()296 public void updateDeviceId_sameId_DoesNotNotifyListeners() { 297 Context context = getApplicationContext(); 298 context.registerDeviceIdChangeListener(mTestExecutor, mDeviceChangeListener); 299 300 context.updateDeviceId(mVirtualDevice.getDeviceId()); 301 verify(mDeviceChangeListener, timeout(TIMEOUT_MILLIS)).accept(mVirtualDevice.getDeviceId()); 302 303 context.updateDeviceId(mVirtualDevice.getDeviceId()); 304 verifyNoMoreInteractions(mDeviceChangeListener); 305 } 306 307 @Test activityContext_startActivityOnVirtualDevice_returnsVirtualDeviceId()308 public void activityContext_startActivityOnVirtualDevice_returnsVirtualDeviceId() { 309 Activity activityContext = startActivity(EmptyActivity.class, mVirtualDisplay); 310 311 assertThat(activityContext.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 312 } 313 314 @Test activityContext_startActivityOnDefaultDevice_returnsDefaultDeviceId()315 public void activityContext_startActivityOnDefaultDevice_returnsDefaultDeviceId() { 316 Activity activityContext = startActivity(EmptyActivity.class, DEFAULT_DISPLAY); 317 318 assertThat(activityContext.getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 319 } 320 321 @Test activityContext_activityMovesDisplay_returnsDeviceIdAssociatedWithDisplay()322 public void activityContext_activityMovesDisplay_returnsDeviceIdAssociatedWithDisplay() { 323 Activity activity = startActivity(EmptyActivity.class, mVirtualDisplay); 324 try (VirtualDevice virtualDevice2 = createVirtualDevice()) { 325 VirtualDisplay virtualDisplay2 = createVirtualDisplay(virtualDevice2); 326 327 assertThat(activity.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 328 329 activity.updateDisplay(virtualDisplay2.getDisplay().getDisplayId()); 330 331 assertThat(activity.getDeviceId()).isEqualTo(virtualDevice2.getDeviceId()); 332 } 333 } 334 335 @Test applicationContext_lastActivityOnVirtualDevice_returnsVirtualDeviceId()336 public void applicationContext_lastActivityOnVirtualDevice_returnsVirtualDeviceId() { 337 startActivity(EmptyActivity.class, DEFAULT_DISPLAY); 338 startActivity(SecondActivity.class, mVirtualDisplay); 339 340 assertThat(getApplicationContext().getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 341 } 342 343 @Test applicationContext_recreateActivity_returnsDeviceIdOfActivity()344 public void applicationContext_recreateActivity_returnsDeviceIdOfActivity() { 345 Activity virtualDeviceActivity = startActivity(EmptyActivity.class, mVirtualDisplay); 346 Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 347 ActivityMonitor monitor = createMonitor(EmptyActivity.class.getName()); 348 instrumentation.addMonitor(monitor); 349 350 instrumentation.runOnMainSync(() -> virtualDeviceActivity.recreate()); 351 monitor.waitForActivity(); 352 instrumentation.removeMonitor(monitor); 353 354 assertThat(getApplicationContext().getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 355 } 356 357 @Test applicationContext_recreateFirstActivity_returnsDeviceOfLastCreatedActivity()358 public void applicationContext_recreateFirstActivity_returnsDeviceOfLastCreatedActivity() { 359 Activity defaultActivity = startActivity(EmptyActivity.class, DEFAULT_DISPLAY); 360 startActivity(SecondActivity.class, mVirtualDisplay); 361 Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 362 ActivityMonitor monitor = createMonitor(EmptyActivity.class.getName()); 363 instrumentation.addMonitor(monitor); 364 365 instrumentation.runOnMainSync(() -> defaultActivity.recreate()); 366 monitor.waitForActivity(); 367 instrumentation.removeMonitor(monitor); 368 369 assertThat(getApplicationContext().getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 370 } 371 372 @Test applicationContext_activityOnVirtualDeviceDestroyed_returnsDefault()373 public void applicationContext_activityOnVirtualDeviceDestroyed_returnsDefault() { 374 Activity activity = startActivity(EmptyActivity.class, mVirtualDisplay); 375 activity.finish(); 376 activity.releaseInstance(); 377 378 verify(mActivityListener, timeout(TIMEOUT_MILLIS)) 379 .onDisplayEmpty(eq(mVirtualDisplay.getDisplay().getDisplayId())); 380 381 assertThat(getApplicationContext().getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 382 } 383 384 @Test applicationContext_lastActivityOnDefaultDevice_returnsDefault()385 public void applicationContext_lastActivityOnDefaultDevice_returnsDefault() { 386 startActivity(EmptyActivity.class, mVirtualDisplay); 387 startActivity(SecondActivity.class, DEFAULT_DISPLAY); 388 389 assertThat(getApplicationContext().getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 390 } 391 392 @Test application_context_noActivities_returnsDefault()393 public void application_context_noActivities_returnsDefault() { 394 assertThat(getApplicationContext().getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 395 } 396 397 @Test applicationContext_twoVirtualDevices_returnsIdOfLatest()398 public void applicationContext_twoVirtualDevices_returnsIdOfLatest() { 399 startActivity(EmptyActivity.class, mVirtualDisplay); 400 Context context = getApplicationContext(); 401 try (VirtualDevice virtualDevice2 = createVirtualDevice()) { 402 VirtualDisplay virtualDisplay2 = createVirtualDisplay(virtualDevice2); 403 404 assertThat(context.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 405 406 startActivity(SecondActivity.class, virtualDisplay2); 407 408 assertThat(context.getDeviceId()).isEqualTo(virtualDevice2.getDeviceId()); 409 410 startActivity(SecondActivity.class, DEFAULT_DISPLAY); 411 412 assertThat(context.getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 413 } 414 } 415 416 @Test serviceContext_lastActivityOnVirtualDevice_returnsVirtualDeviceId()417 public void serviceContext_lastActivityOnVirtualDevice_returnsVirtualDeviceId() 418 throws TimeoutException { 419 Service service = createTestService(); 420 startActivity(EmptyActivity.class, DEFAULT_DISPLAY); 421 startActivity(SecondActivity.class, mVirtualDisplay); 422 423 assertThat(service.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 424 } 425 426 @Test serviceContext_lastActivityOnDefaultDevice_returnsDefault()427 public void serviceContext_lastActivityOnDefaultDevice_returnsDefault() 428 throws TimeoutException { 429 Service service = createTestService(); 430 startActivity(EmptyActivity.class, mVirtualDisplay); 431 startActivity(SecondActivity.class, DEFAULT_DISPLAY); 432 433 assertThat(service.getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 434 } 435 436 @Test serviceContext_startServiceAfterActivity_hasDeviceIdOfTopActivity()437 public void serviceContext_startServiceAfterActivity_hasDeviceIdOfTopActivity() 438 throws TimeoutException { 439 startActivity(EmptyActivity.class, DEFAULT_DISPLAY); 440 startActivity(SecondActivity.class, mVirtualDisplay); 441 Service service = createTestService(); 442 443 assertThat(service.getDeviceId()).isEqualTo(mVirtualDevice.getDeviceId()); 444 } 445 446 @Test serviceContext_startServiceAfterActivityDeviceIsClosed_returnsDefault()447 public void serviceContext_startServiceAfterActivityDeviceIsClosed_returnsDefault() 448 throws TimeoutException { 449 startActivity(EmptyActivity.class, DEFAULT_DISPLAY); 450 startActivity(SecondActivity.class, mVirtualDisplay); 451 mVirtualDevice.close(); 452 Service service = createTestService(); 453 454 assertThat(service.getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 455 } 456 457 @Test serviceContext_noActivities_hasDefaultId()458 public void serviceContext_noActivities_hasDefaultId() 459 throws TimeoutException { 460 Service service = createTestService(); 461 462 assertThat(service.getDeviceId()).isEqualTo(DEVICE_ID_DEFAULT); 463 } 464 createVirtualDevice()465 private VirtualDevice createVirtualDevice() { 466 VirtualDevice virtualDevice = mVirtualDeviceManager.createVirtualDevice( 467 mFakeAssociationRule.getAssociationInfo().getId(), 468 DEFAULT_VIRTUAL_DEVICE_PARAMS); 469 mVirtualDevices.add(virtualDevice); 470 return virtualDevice; 471 } 472 createVirtualDisplay(VirtualDevice virtualDevice)473 private VirtualDisplay createVirtualDisplay(VirtualDevice virtualDevice) { 474 return virtualDevice.createVirtualDisplay( 475 /* width= */ 100, 476 /* height= */ 100, 477 /* densityDpi= */ 240, 478 /* surface= */ null, 479 /* flags= */ 0, 480 Runnable::run, 481 mVirtualDisplayCallback); 482 } 483 createMonitor(String activityName)484 private ActivityMonitor createMonitor(String activityName) { 485 return new ActivityMonitor(activityName, 486 new Instrumentation.ActivityResult(0, new Intent()), false); 487 } 488 startActivity(Class<?> activityClass, VirtualDisplay virtualDisplay)489 private Activity startActivity(Class<?> activityClass, VirtualDisplay virtualDisplay) { 490 return startActivityWithOptions(createActivityOptions(virtualDisplay), activityClass); 491 } 492 startActivity(Class<?> activityClass, int displayId)493 private Activity startActivity(Class<?> activityClass, int displayId) { 494 return startActivityWithOptions(createActivityOptions(displayId), activityClass); 495 } 496 startActivityWithOptions(Bundle activityOptions, Class<?> activityClass)497 private Activity startActivityWithOptions(Bundle activityOptions, Class<?> activityClass) { 498 Activity activity = InstrumentationRegistry.getInstrumentation() 499 .startActivitySync( 500 new Intent(getApplicationContext(), activityClass) 501 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 502 | Intent.FLAG_ACTIVITY_CLEAR_TASK), 503 activityOptions); 504 mActivities.add(activity); 505 return activity; 506 } 507 createTestService()508 private Service createTestService() throws TimeoutException { 509 final Intent intent = new Intent(getApplicationContext(), TestService.class); 510 final ServiceTestRule serviceRule = new ServiceTestRule(); 511 IBinder serviceToken = serviceRule.bindService(intent); 512 return ((TestService.TestBinder) serviceToken).getService(); 513 } 514 } 515