1 /* 2 * Copyright (C) 2016 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.server.wm.window; 18 19 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 20 import static android.server.wm.CliIntentExtra.extraString; 21 import static android.server.wm.UiDeviceUtils.dragPointer; 22 import static android.server.wm.dndsourceapp.Components.DRAG_SOURCE; 23 import static android.server.wm.dndsourceapp.Components.DRAG_SOURCE_DROP_TARGET; 24 import static android.server.wm.dndtargetapp.Components.DROP_TARGET; 25 import static android.server.wm.dndtargetappsdk23.Components.DROP_TARGET_SDK23; 26 import static android.view.Display.DEFAULT_DISPLAY; 27 28 import static org.junit.Assert.assertEquals; 29 import static org.junit.Assert.assertNotNull; 30 import static org.junit.Assert.assertTrue; 31 import static org.junit.Assert.fail; 32 import static org.junit.Assume.assumeTrue; 33 34 import android.content.ComponentName; 35 import android.graphics.Point; 36 import android.graphics.Rect; 37 import android.os.SystemClock; 38 import android.platform.test.annotations.AppModeFull; 39 import android.platform.test.annotations.Presubmit; 40 import android.platform.test.annotations.RequiresFlagsEnabled; 41 import android.server.wm.ActivityManagerTestBase; 42 import android.server.wm.DeprecatedTargetSdkUtils; 43 import android.server.wm.TestLogService; 44 import android.server.wm.WindowManagerState.Task; 45 import android.util.Log; 46 import android.view.Display; 47 48 import com.android.window.flags.Flags; 49 50 import com.google.common.collect.ImmutableSet; 51 52 import org.junit.After; 53 import org.junit.Before; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 import org.junit.runners.Parameterized; 57 58 import java.util.Map; 59 60 /** 61 * Build/Install/Run: 62 * atest CtsWindowManagerDeviceWindow:CrossAppDragAndDropTests 63 */ 64 @Presubmit 65 @AppModeFull(reason = "Requires android.permission.MANAGE_ACTIVITY_TASKS") 66 @RunWith(Parameterized.class) 67 @android.server.wm.annotation.Group2 68 public class CrossAppDragAndDropTests extends ActivityManagerTestBase { 69 private static final String TAG = "CrossAppDragAndDrop"; 70 71 private static final int SWIPE_STEPS = 100; 72 73 private static final String FILE_GLOBAL = "file_global"; 74 private static final String FILE_LOCAL = "file_local"; 75 private static final String DISALLOW_GLOBAL = "disallow_global"; 76 private static final String GLOBAL_SAME_APP = "global_same_app"; 77 private static final String CANCEL_SOON = "cancel_soon"; 78 private static final String GRANT_NONE = "grant_none"; 79 private static final String GRANT_READ = "grant_read"; 80 private static final String GRANT_WRITE = "grant_write"; 81 private static final String GRANT_READ_PREFIX = "grant_read_prefix"; 82 private static final String GRANT_READ_NOPREFIX = "grant_read_noprefix"; 83 private static final String GRANT_READ_PERSISTABLE = "grant_read_persistable"; 84 85 private static final String REQUEST_NONE = "request_none"; 86 private static final String REQUEST_READ = "request_read"; 87 private static final String REQUEST_READ_NESTED = "request_read_nested"; 88 private static final String REQUEST_TAKE_PERSISTABLE = "request_take_persistable"; 89 private static final String REQUEST_WRITE = "request_write"; 90 91 private static final String TARGET_ON_RECEIVE_CONTENT_LISTENER_TEXT_VIEW = 92 "textview_on_receive_content_listener"; 93 private static final String TARGET_ON_RECEIVE_CONTENT_LISTENER_EDIT_TEXT = 94 "edittext_on_receive_content_listener"; 95 private static final String TARGET_ON_RECEIVE_CONTENT_LISTENER_LINEAR_LAYOUT = 96 "linearlayout_on_receive_content_listener"; 97 private static final ImmutableSet<String> ON_RECEIVE_CONTENT_LISTENER_MODES = ImmutableSet.of( 98 TARGET_ON_RECEIVE_CONTENT_LISTENER_TEXT_VIEW, 99 TARGET_ON_RECEIVE_CONTENT_LISTENER_EDIT_TEXT, 100 TARGET_ON_RECEIVE_CONTENT_LISTENER_LINEAR_LAYOUT 101 ); 102 103 private static final String SOURCE_LOG_TAG = "DragSource"; 104 private static final String TARGET_LOG_TAG = "DropTarget"; 105 106 private static final String RESULT_KEY_START_DRAG = "START_DRAG"; 107 private static final String RESULT_KEY_DRAG_STARTED = "DRAG_STARTED"; 108 private static final String RESULT_KEY_DRAG_ENDED = "DRAG_ENDED"; 109 private static final String RESULT_KEY_EXTRAS = "EXTRAS"; 110 private static final String RESULT_KEY_DROP_RESULT = "DROP"; 111 private static final String RESULT_KEY_ACCESS_BEFORE = "BEFORE"; 112 private static final String RESULT_KEY_ACCESS_AFTER = "AFTER"; 113 private static final String RESULT_KEY_CLIP_DATA_ERROR = "CLIP_DATA_ERROR"; 114 private static final String RESULT_KEY_CLIP_DESCR_ERROR = "CLIP_DESCR_ERROR"; 115 private static final String RESULT_KEY_LOCAL_STATE_ERROR = "LOCAL_STATE_ERROR"; 116 117 private static final String RESULT_IGNORE = "Ignore"; 118 private static final String RESULT_MISSING = "Missing"; 119 private static final String RESULT_OK = "OK"; 120 private static final String RESULT_EXCEPTION = "Exception"; 121 private static final String RESULT_NULL_DROP_PERMISSIONS = "Null DragAndDropPermissions"; 122 123 private static final String EXTRA_MODE = "mode"; 124 private static final String EXTRA_LOGTAG = "logtag"; 125 126 private static final ActivityLaunchModeContext SPLIT_SCREEN_LAUNCH_MODE_CONTEXT = 127 new ActivityLaunchModeContext() { 128 @Override 129 void assumeDeviceSupportsLaunchMode() { 130 assumeTrue(mTestCase.supportsSplitScreenMultiWindow()); 131 } 132 133 @Override 134 void launchActivities(ComponentName sourceComponentName, String sourceMode, 135 ComponentName targetComponentName, String targetMode) { 136 mTestCase.launchSplitScreenActivities( 137 sourceComponentName, sourceMode, targetComponentName, targetMode); 138 } 139 140 @Override 141 public String toString() { 142 return "SplitScreen"; 143 } 144 }; 145 146 private static final ActivityLaunchModeContext FREEFORM_LAUNCH_MODE_CONTEXT = 147 new ActivityLaunchModeContext() { 148 @Override 149 void assumeDeviceSupportsLaunchMode() { 150 assumeTrue(mTestCase.supportsFreeform()); 151 } 152 153 @Override 154 void launchActivities(ComponentName sourceComponentName, String sourceMode, 155 ComponentName targetComponentName, String targetMode) throws Exception { 156 mTestCase.launchFreeformActivities( 157 sourceComponentName, sourceMode, targetComponentName, targetMode); 158 } 159 160 @Override 161 public String toString() { 162 return "Freeform"; 163 } 164 }; 165 166 167 @Parameterized.Parameters(name = "{0}") activityLaunchModes()168 public static Object[] activityLaunchModes() { 169 return new Object[] { 170 FREEFORM_LAUNCH_MODE_CONTEXT, 171 SPLIT_SCREEN_LAUNCH_MODE_CONTEXT 172 }; 173 } 174 175 @Parameterized.Parameter 176 public ActivityLaunchModeContext mActivityLaunchModeContext; 177 178 private Map<String, String> mSourceResults; 179 private Map<String, String> mTargetResults; 180 181 private String mSessionId; 182 private String mSourceLogTag; 183 private String mTargetLogTag; 184 185 @Before 186 @Override setUp()187 public void setUp() throws Exception { 188 super.setUp(); 189 mActivityLaunchModeContext.mTestCase = this; 190 mActivityLaunchModeContext.assumeDeviceSupportsLaunchMode(); 191 192 // Use uptime in seconds as unique test invocation id. 193 mSessionId = Long.toString(SystemClock.uptimeMillis() / 1000); 194 mSourceLogTag = SOURCE_LOG_TAG + mSessionId; 195 mTargetLogTag = TARGET_LOG_TAG + mSessionId; 196 197 cleanupState(); 198 } 199 200 @After tearDown()201 public void tearDown() { 202 cleanupState(); 203 } 204 205 /** 206 * Make sure that the special activity stacks are removed and the ActivityManager/WindowManager 207 * is in a good state. 208 */ cleanupState()209 private void cleanupState() { 210 stopTestPackage(DRAG_SOURCE.getPackageName()); 211 stopTestPackage(DROP_TARGET.getPackageName()); 212 stopTestPackage(DROP_TARGET_SDK23.getPackageName()); 213 } 214 launchFreeformActivities(ComponentName sourceComponentName, String sourceMode, ComponentName targetComponentName, String targetMode)215 private void launchFreeformActivities(ComponentName sourceComponentName, 216 String sourceMode, ComponentName targetComponentName, String targetMode) 217 throws Exception { 218 // Fallback to try to launch two freeform windows side by side. 219 Point displaySize = getDisplaySize(); 220 launchFreeformActivity(sourceComponentName, sourceMode, mSourceLogTag, 221 displaySize, true /* leftSide */); 222 launchFreeformActivity(targetComponentName, targetMode, mTargetLogTag, 223 displaySize, false /* leftSide */); 224 } 225 226 /** 227 * @param displaySize size of the display 228 * @param leftSide {@code true} to launch the app taking up the left half of the display, 229 * {@code false} to launch the app taking up the right half of the display. 230 */ launchFreeformActivity(ComponentName componentName, String mode, String logtag, Point displaySize, boolean leftSide)231 private void launchFreeformActivity(ComponentName componentName, String mode, 232 String logtag, Point displaySize, boolean leftSide) throws Exception { 233 launchActivity(componentName, WINDOWING_MODE_FREEFORM, extraString("mode", mode), 234 extraString("logtag", logtag)); 235 Point topLeft = new Point(leftSide ? 0 : displaySize.x / 2, 0); 236 Point bottomRight = new Point(leftSide ? displaySize.x / 2 : displaySize.x, displaySize.y); 237 resizeActivityTask(componentName, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); 238 waitAndAssertTopResumedActivity(componentName, DEFAULT_DISPLAY, 239 "Activity launched as freeform should be resumed"); 240 } 241 launchSplitScreenActivities(ComponentName sourceComponentName, String sourceMode, ComponentName targetComponentName, String targetMode)242 private void launchSplitScreenActivities(ComponentName sourceComponentName, 243 String sourceMode, ComponentName targetComponentName, String targetMode) { 244 // Launch primary activity. 245 getLaunchActivityBuilder() 246 .setTargetActivity(sourceComponentName) 247 .setUseInstrumentation() 248 .setWaitForLaunched(true) 249 .setIntentExtra(bundle -> { 250 bundle.putString(EXTRA_MODE, sourceMode); 251 bundle.putString(EXTRA_LOGTAG, mSourceLogTag); 252 }).execute(); 253 254 // Launch secondary activity. 255 getLaunchActivityBuilder().setTargetActivity(targetComponentName) 256 .setUseInstrumentation() 257 .setWaitForLaunched(true) 258 .setIntentExtra(bundle -> { 259 bundle.putString(EXTRA_MODE, targetMode); 260 bundle.putString(EXTRA_LOGTAG, mTargetLogTag); 261 }).execute(); 262 moveActivitiesToSplitScreen(sourceComponentName, targetComponentName); 263 } 264 injectInput(Point from, Point to, int steps)265 private void injectInput(Point from, Point to, int steps) throws Exception { 266 dragPointer(from, to, steps); 267 } 268 getDisplaySize()269 private Point getDisplaySize() throws Exception { 270 final Point displaySize = new Point(); 271 mDm.getDisplay(Display.DEFAULT_DISPLAY).getRealSize(displaySize); 272 return displaySize; 273 } 274 getWindowCenter(ComponentName name)275 private Point getWindowCenter(ComponentName name) throws Exception { 276 final Task sideTask = mWmState.getTaskByActivity(name); 277 Rect bounds = sideTask.getBounds(); 278 if (bounds != null) { 279 return new Point(bounds.centerX(), bounds.centerY()); 280 } 281 return null; 282 } 283 assertDropResult(String sourceMode, String targetMode, String expectedDropResult)284 private void assertDropResult(String sourceMode, String targetMode, String expectedDropResult) 285 throws Exception { 286 assertDragAndDropResults(DRAG_SOURCE, sourceMode, DROP_TARGET, targetMode, 287 RESULT_OK, expectedDropResult, RESULT_OK); 288 } 289 assertNoGlobalDragEvents(ComponentName sourceComponentName, String sourceMode, ComponentName targetComponentName, String expectedStartDragResult)290 private void assertNoGlobalDragEvents(ComponentName sourceComponentName, String sourceMode, 291 ComponentName targetComponentName, String expectedStartDragResult) 292 throws Exception { 293 assertDragAndDropResults( 294 sourceComponentName, sourceMode, targetComponentName, REQUEST_NONE, 295 expectedStartDragResult, RESULT_MISSING, RESULT_MISSING); 296 } 297 assertDragAndDropResults(ComponentName sourceComponentName, String sourceMode, ComponentName targetComponentName, String targetMode, String expectedStartDragResult, String expectedDropResult, String expectedListenerResults)298 private void assertDragAndDropResults(ComponentName sourceComponentName, String sourceMode, 299 ComponentName targetComponentName, String targetMode, 300 String expectedStartDragResult, String expectedDropResult, 301 String expectedListenerResults) throws Exception { 302 Log.e(TAG, "session: " + mSessionId + ", source: " + sourceMode 303 + ", target: " + targetMode); 304 305 mActivityLaunchModeContext.launchActivities( 306 sourceComponentName, sourceMode, targetComponentName, targetMode); 307 if (DROP_TARGET_SDK23.equals(targetComponentName)) { 308 DeprecatedTargetSdkUtils.waitAndDismissDeprecatedTargetSdkDialog(mWmState); 309 } 310 311 Point p1 = getWindowCenter(sourceComponentName); 312 assertNotNull(p1); 313 Point p2 = getWindowCenter(targetComponentName); 314 assertNotNull(p2); 315 316 TestLogService.registerClient(mSourceLogTag, RESULT_KEY_START_DRAG); 317 TestLogService.registerClient(mTargetLogTag, RESULT_KEY_DRAG_ENDED); 318 319 injectInput(p1, p2, SWIPE_STEPS); 320 321 mSourceResults = TestLogService.getResultsForClient(mSourceLogTag, 1000); 322 assertSourceResult(RESULT_KEY_START_DRAG, expectedStartDragResult); 323 324 mTargetResults = TestLogService.getResultsForClient(mTargetLogTag, 1000); 325 assertTargetResult(RESULT_KEY_DROP_RESULT, expectedDropResult); 326 327 // Skip the following assertions when testing OnReceiveContentListener, since it only 328 // handles drop events. 329 if (!RESULT_IGNORE.equals(expectedListenerResults) 330 && !ON_RECEIVE_CONTENT_LISTENER_MODES.contains(targetMode)) { 331 if (!RESULT_MISSING.equals(expectedDropResult)) { 332 assertTargetResult(RESULT_KEY_ACCESS_BEFORE, RESULT_EXCEPTION); 333 assertTargetResult(RESULT_KEY_ACCESS_AFTER, RESULT_EXCEPTION); 334 } 335 assertListenerResults(expectedListenerResults); 336 } 337 } 338 assertListenerResults(String expectedResult)339 private void assertListenerResults(String expectedResult) throws Exception { 340 assertTargetResult(RESULT_KEY_DRAG_STARTED, expectedResult); 341 assertTargetResult(RESULT_KEY_DRAG_ENDED, expectedResult); 342 assertTargetResult(RESULT_KEY_EXTRAS, expectedResult); 343 344 assertTargetResult(RESULT_KEY_CLIP_DATA_ERROR, RESULT_MISSING); 345 assertTargetResult(RESULT_KEY_CLIP_DESCR_ERROR, RESULT_MISSING); 346 assertTargetResult(RESULT_KEY_LOCAL_STATE_ERROR, RESULT_MISSING); 347 } 348 assertSourceResult(String resultKey, String expectedResult)349 private void assertSourceResult(String resultKey, String expectedResult) throws Exception { 350 assertResult(mSourceResults, resultKey, expectedResult); 351 } 352 assertTargetResult(String resultKey, String expectedResult)353 private void assertTargetResult(String resultKey, String expectedResult) throws Exception { 354 assertResult(mTargetResults, resultKey, expectedResult); 355 } 356 assertResult(Map<String, String> results, String resultKey, String expectedResult)357 private void assertResult(Map<String, String> results, String resultKey, String expectedResult) 358 throws Exception { 359 if (RESULT_MISSING.equals(expectedResult)) { 360 if (results.containsKey(resultKey)) { 361 fail("Unexpected " + resultKey + "=" + results.get(resultKey)); 362 } 363 } else { 364 assertTrue("Missing " + resultKey, results.containsKey(resultKey)); 365 assertEquals(resultKey + " result mismatch,", expectedResult, results.get(resultKey)); 366 } 367 } 368 369 @Test testCancelSoon()370 public void testCancelSoon() throws Exception { 371 assertDropResult(CANCEL_SOON, REQUEST_NONE, RESULT_MISSING); 372 } 373 374 @Test testDisallowGlobal()375 public void testDisallowGlobal() throws Exception { 376 // Verify that dragging to another window doesn't work without FLAG_DRAG_GLOBAL 377 assertNoGlobalDragEvents(DRAG_SOURCE, DISALLOW_GLOBAL, DROP_TARGET, RESULT_OK); 378 } 379 380 @Test testDisallowGlobalBelowSdk24()381 public void testDisallowGlobalBelowSdk24() throws Exception { 382 assertNoGlobalDragEvents(DRAG_SOURCE, GRANT_NONE, DROP_TARGET_SDK23, RESULT_OK); 383 } 384 385 @Test 386 @RequiresFlagsEnabled(Flags.FLAG_DELEGATE_UNHANDLED_DRAGS) testDisallowGlobalSameAppWithDifferentUids()387 public void testDisallowGlobalSameAppWithDifferentUids() throws Exception { 388 // Verify that dragging to another window from a different app doesn't work with 389 // FLAG_DRAG_GLOBAL_SAME_APP 390 assertNoGlobalDragEvents(DRAG_SOURCE, GLOBAL_SAME_APP, DROP_TARGET, RESULT_OK); 391 } 392 393 @Test 394 @RequiresFlagsEnabled(Flags.FLAG_DELEGATE_UNHANDLED_DRAGS) testGlobalSameAppWithSameUids()395 public void testGlobalSameAppWithSameUids() throws Exception { 396 // Verify that dragging to another window from the same app works with 397 // FLAG_DRAG_GLOBAL_SAME_APP 398 assertDragAndDropResults(DRAG_SOURCE, GLOBAL_SAME_APP, DRAG_SOURCE_DROP_TARGET, 399 REQUEST_NONE, RESULT_OK, RESULT_OK, RESULT_IGNORE); 400 } 401 402 @Test testFileUriLocal()403 public void testFileUriLocal() throws Exception { 404 assertNoGlobalDragEvents(DRAG_SOURCE, FILE_LOCAL, DROP_TARGET, RESULT_OK); 405 } 406 407 @Test testFileUriGlobal()408 public void testFileUriGlobal() throws Exception { 409 assertNoGlobalDragEvents(DRAG_SOURCE, FILE_GLOBAL, DROP_TARGET, RESULT_EXCEPTION); 410 } 411 412 @Test testGrantNoneRequestNone()413 public void testGrantNoneRequestNone() throws Exception { 414 assertDropResult(GRANT_NONE, REQUEST_NONE, RESULT_EXCEPTION); 415 } 416 417 @Test testGrantNoneRequestRead()418 public void testGrantNoneRequestRead() throws Exception { 419 assertDropResult(GRANT_NONE, REQUEST_READ, RESULT_NULL_DROP_PERMISSIONS); 420 } 421 422 @Test testGrantNoneRequestWrite()423 public void testGrantNoneRequestWrite() throws Exception { 424 assertDropResult(GRANT_NONE, REQUEST_WRITE, RESULT_NULL_DROP_PERMISSIONS); 425 } 426 427 @Test testGrantReadRequestNone()428 public void testGrantReadRequestNone() throws Exception { 429 assertDropResult(GRANT_READ, REQUEST_NONE, RESULT_EXCEPTION); 430 } 431 432 @Test testGrantReadRequestRead()433 public void testGrantReadRequestRead() throws Exception { 434 assertDropResult(GRANT_READ, REQUEST_READ, RESULT_OK); 435 } 436 437 @Test testGrantReadRequestWrite()438 public void testGrantReadRequestWrite() throws Exception { 439 assertDropResult(GRANT_READ, REQUEST_WRITE, RESULT_EXCEPTION); 440 } 441 442 @Test testGrantReadNoPrefixRequestReadNested()443 public void testGrantReadNoPrefixRequestReadNested() throws Exception { 444 assertDropResult(GRANT_READ_NOPREFIX, REQUEST_READ_NESTED, RESULT_EXCEPTION); 445 } 446 447 @Test testGrantReadPrefixRequestReadNested()448 public void testGrantReadPrefixRequestReadNested() throws Exception { 449 assertDropResult(GRANT_READ_PREFIX, REQUEST_READ_NESTED, RESULT_OK); 450 } 451 452 @Test testGrantPersistableRequestTakePersistable()453 public void testGrantPersistableRequestTakePersistable() throws Exception { 454 assertDropResult(GRANT_READ_PERSISTABLE, REQUEST_TAKE_PERSISTABLE, RESULT_OK); 455 } 456 457 @Test testGrantReadRequestTakePersistable()458 public void testGrantReadRequestTakePersistable() throws Exception { 459 assertDropResult(GRANT_READ, REQUEST_TAKE_PERSISTABLE, RESULT_EXCEPTION); 460 } 461 462 @Test testGrantWriteRequestNone()463 public void testGrantWriteRequestNone() throws Exception { 464 assertDropResult(GRANT_WRITE, REQUEST_NONE, RESULT_EXCEPTION); 465 } 466 467 @Test testGrantWriteRequestRead()468 public void testGrantWriteRequestRead() throws Exception { 469 assertDropResult(GRANT_WRITE, REQUEST_READ, RESULT_EXCEPTION); 470 } 471 472 @Test testGrantWriteRequestWrite()473 public void testGrantWriteRequestWrite() throws Exception { 474 assertDropResult(GRANT_WRITE, REQUEST_WRITE, RESULT_OK); 475 } 476 477 @Test testOnReceiveContentListener_TextView_GrantRead()478 public void testOnReceiveContentListener_TextView_GrantRead() throws Exception { 479 assertDropResult(GRANT_READ, TARGET_ON_RECEIVE_CONTENT_LISTENER_TEXT_VIEW, RESULT_OK); 480 } 481 482 @Test testOnReceiveContentListener_TextView_GrantNone()483 public void testOnReceiveContentListener_TextView_GrantNone() throws Exception { 484 assertDropResult(GRANT_NONE, TARGET_ON_RECEIVE_CONTENT_LISTENER_TEXT_VIEW, 485 RESULT_EXCEPTION); 486 } 487 488 @Test testOnReceiveContentListener_EditText_GrantRead()489 public void testOnReceiveContentListener_EditText_GrantRead() throws Exception { 490 assertDropResult(GRANT_READ, TARGET_ON_RECEIVE_CONTENT_LISTENER_EDIT_TEXT, RESULT_OK); 491 } 492 493 @Test testOnReceiveContentListener_EditText_GrantNone()494 public void testOnReceiveContentListener_EditText_GrantNone() throws Exception { 495 assertDropResult(GRANT_NONE, TARGET_ON_RECEIVE_CONTENT_LISTENER_EDIT_TEXT, 496 RESULT_EXCEPTION); 497 } 498 499 @Test testOnReceiveContentListener_LinearLayout_GrantRead()500 public void testOnReceiveContentListener_LinearLayout_GrantRead() throws Exception { 501 assertDropResult(GRANT_READ, TARGET_ON_RECEIVE_CONTENT_LISTENER_LINEAR_LAYOUT, RESULT_OK); 502 } 503 504 @Test testOnReceiveContentListener_LinearLayout_GrantNone()505 public void testOnReceiveContentListener_LinearLayout_GrantNone() throws Exception { 506 assertDropResult(GRANT_NONE, TARGET_ON_RECEIVE_CONTENT_LISTENER_LINEAR_LAYOUT, 507 RESULT_EXCEPTION); 508 } 509 510 private abstract static class ActivityLaunchModeContext { 511 CrossAppDragAndDropTests mTestCase; 512 assumeDeviceSupportsLaunchMode()513 abstract void assumeDeviceSupportsLaunchMode() throws Exception; 514 launchActivities(ComponentName sourceComponentName, String sourceMode, ComponentName targetComponentName, String targetMode)515 abstract void launchActivities(ComponentName sourceComponentName, 516 String sourceMode, ComponentName targetComponentName, String targetMode) 517 throws Exception; 518 } 519 } 520