1 /* 2 * Copyright (C) 2020 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; 18 19 import static android.app.AppOpsManager.MODE_ALLOWED; 20 import static android.app.AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW; 21 import static android.server.wm.UiDeviceUtils.pressUnlockButton; 22 import static android.server.wm.UiDeviceUtils.pressWakeupButton; 23 import static android.server.wm.WindowManagerState.STATE_RESUMED; 24 import static android.server.wm.overlay.Components.OverlayActivity.EXTRA_TOKEN; 25 26 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 27 28 import static com.google.common.truth.Truth.assertThat; 29 30 import static junit.framework.Assert.assertEquals; 31 import static junit.framework.Assert.assertTrue; 32 import static junit.framework.Assert.fail; 33 34 import android.app.Activity; 35 import android.app.ActivityManager; 36 import android.app.ActivityOptions; 37 import android.app.Instrumentation; 38 import android.app.NotificationManager; 39 import android.content.ComponentName; 40 import android.content.ContentResolver; 41 import android.content.Context; 42 import android.content.Intent; 43 import android.content.res.Resources; 44 import android.graphics.Rect; 45 import android.hardware.input.InputManager; 46 import android.os.Bundle; 47 import android.os.ConditionVariable; 48 import android.os.Handler; 49 import android.os.IBinder; 50 import android.os.Looper; 51 import android.os.SystemClock; 52 import android.platform.test.annotations.Presubmit; 53 import android.provider.Settings; 54 import android.server.wm.overlay.Components; 55 import android.server.wm.overlay.R; 56 import android.server.wm.shared.BlockingResultReceiver; 57 import android.server.wm.shared.IUntrustedTouchTestService; 58 import android.util.ArrayMap; 59 import android.util.ArraySet; 60 import android.view.Display; 61 import android.view.Gravity; 62 import android.view.MotionEvent; 63 import android.view.View; 64 import android.view.WindowManager; 65 import android.view.WindowManager.LayoutParams; 66 import android.widget.Toast; 67 68 import androidx.annotation.AnimRes; 69 import androidx.annotation.Nullable; 70 import androidx.test.rule.ActivityTestRule; 71 72 import com.android.compatibility.common.util.AppOpsUtils; 73 import com.android.compatibility.common.util.SystemUtil; 74 75 import org.junit.After; 76 import org.junit.Before; 77 import org.junit.Rule; 78 import org.junit.Test; 79 import org.junit.rules.TestName; 80 81 import java.util.Map; 82 import java.util.Set; 83 import java.util.concurrent.atomic.AtomicInteger; 84 85 @Presubmit 86 public class WindowUntrustedTouchTest { 87 private static final String TAG = "WindowUntrustedTouchTest"; 88 89 /** 90 * Opacity (or alpha) is represented as a half-precision floating point number (16b) in surface 91 * flinger and the conversion from the single-precision float provided to window manager happens 92 * in Layer::setAlpha() by android::half::ftoh(). So, many small non-zero values provided to 93 * window manager end up becoming zero due to loss of precision (this is fine as long as the 94 * zeros are also used to render the pixels on the screen). So, the minimum opacity possible is 95 * actually the minimum positive value representable in half-precision float, which is 96 * 0_00001_0000000000, whose equivalent in float is 0_01110001_00000000000000000000000. 97 * 98 * Note that from float -> half conversion code we don't produce any subnormal half-precision 99 * floats during conversion. 100 */ 101 public static final float MIN_POSITIVE_OPACITY = 102 Float.intBitsToFloat(0b00111000100000000000000000000000); 103 104 private static final float MAXIMUM_OBSCURING_OPACITY = .8f; 105 private static final long TIMEOUT_MS = 3000L; 106 private static final long MAX_ANIMATION_DURATION_MS = 3000L; 107 private static final long ANIMATION_DURATION_TOLERANCE_MS = 500L; 108 109 private static final int OVERLAY_COLOR = 0xFFFF0000; 110 private static final int ACTIVITY_COLOR = 0xFFFFFFFF; 111 112 private static final int FEATURE_MODE_DISABLED = 0; 113 private static final int FEATURE_MODE_PERMISSIVE = 1; 114 private static final int FEATURE_MODE_BLOCK = 2; 115 116 private static final String APP_SELF = 117 WindowUntrustedTouchTest.class.getPackage().getName() + ".cts"; 118 private static final String APP_A = 119 android.server.wm.second.Components.class.getPackage().getName(); 120 private static final String APP_B = 121 android.server.wm.third.Components.class.getPackage().getName(); 122 private static final String WINDOW_1 = "W1"; 123 private static final String WINDOW_2 = "W2"; 124 125 private static final String[] APPS = {APP_A, APP_B}; 126 127 private static final String SETTING_MAXIMUM_OBSCURING_OPACITY = 128 "maximum_obscuring_opacity_for_touch"; 129 130 private final WindowManagerStateHelper mWmState = new WindowManagerStateHelper(); 131 private final Map<String, FutureConnection<IUntrustedTouchTestService>> mConnections = 132 new ArrayMap<>(); 133 private Instrumentation mInstrumentation; 134 private Context mContext; 135 private Resources mResources; 136 private ContentResolver mContentResolver; 137 private TouchHelper mTouchHelper; 138 private Handler mMainHandler; 139 private InputManager mInputManager; 140 private WindowManager mWindowManager; 141 private ActivityManager mActivityManager; 142 private NotificationManager mNotificationManager; 143 private TestActivity mActivity; 144 private View mContainer; 145 private Toast mToast; 146 private float mPreviousTouchOpacity; 147 private int mPreviousMode; 148 private int mPreviousSawAppOp; 149 private final Set<String> mSawWindowsAdded = new ArraySet<>(); 150 private final AtomicInteger mTouchesReceived = new AtomicInteger(0); 151 152 @Rule 153 public TestName testNameRule = new TestName(); 154 155 @Rule 156 public ActivityTestRule<TestActivity> activityRule = new ActivityTestRule<>(TestActivity.class); 157 158 @Before setUp()159 public void setUp() throws Exception { 160 mActivity = activityRule.getActivity(); 161 mContainer = mActivity.view; 162 mContainer.setOnTouchListener(this::onTouchEvent); 163 mInstrumentation = getInstrumentation(); 164 mContext = mInstrumentation.getContext(); 165 mResources = mContext.getResources(); 166 mContentResolver = mContext.getContentResolver(); 167 mTouchHelper = new TouchHelper(mInstrumentation, mWmState); 168 mMainHandler = new Handler(Looper.getMainLooper()); 169 mInputManager = mContext.getSystemService(InputManager.class); 170 mWindowManager = mContext.getSystemService(WindowManager.class); 171 mActivityManager = mContext.getSystemService(ActivityManager.class); 172 mNotificationManager = mContext.getSystemService(NotificationManager.class); 173 174 mPreviousSawAppOp = AppOpsUtils.getOpMode(APP_SELF, OPSTR_SYSTEM_ALERT_WINDOW); 175 AppOpsUtils.setOpMode(APP_SELF, OPSTR_SYSTEM_ALERT_WINDOW, MODE_ALLOWED); 176 mPreviousTouchOpacity = setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY); 177 mPreviousMode = setBlockUntrustedTouchesMode(FEATURE_MODE_BLOCK); 178 SystemUtil.runWithShellPermissionIdentity( 179 () -> mNotificationManager.setToastRateLimitingEnabled(false)); 180 181 pressWakeupButton(); 182 pressUnlockButton(); 183 } 184 185 @After tearDown()186 public void tearDown() throws Throwable { 187 mWmState.waitForAppTransitionIdleOnDisplay(Display.DEFAULT_DISPLAY); 188 mTouchesReceived.set(0); 189 removeOverlays(); 190 for (FutureConnection<IUntrustedTouchTestService> connection : mConnections.values()) { 191 mContext.unbindService(connection); 192 } 193 mConnections.clear(); 194 for (String app : APPS) { 195 stopPackage(app); 196 } 197 SystemUtil.runWithShellPermissionIdentity( 198 () -> mNotificationManager.setToastRateLimitingEnabled(true)); 199 setBlockUntrustedTouchesMode(mPreviousMode); 200 setMaximumObscuringOpacityForTouch(mPreviousTouchOpacity); 201 AppOpsUtils.setOpMode(APP_SELF, OPSTR_SYSTEM_ALERT_WINDOW, mPreviousSawAppOp); 202 } 203 204 @Test testWhenFeatureInDisabledModeAndActivityWindowAbove_allowsTouch()205 public void testWhenFeatureInDisabledModeAndActivityWindowAbove_allowsTouch() 206 throws Throwable { 207 setBlockUntrustedTouchesMode(FEATURE_MODE_DISABLED); 208 addActivityOverlay(APP_A, /* opacity */ .9f); 209 210 mTouchHelper.tapOnViewCenter(mContainer); 211 212 assertTouchReceived(); 213 } 214 215 @Test testWhenFeatureInPermissiveModeAndActivityWindowAbove_allowsTouch()216 public void testWhenFeatureInPermissiveModeAndActivityWindowAbove_allowsTouch() 217 throws Throwable { 218 setBlockUntrustedTouchesMode(FEATURE_MODE_PERMISSIVE); 219 addActivityOverlay(APP_A, /* opacity */ .9f); 220 221 mTouchHelper.tapOnViewCenter(mContainer); 222 223 assertTouchReceived(); 224 } 225 226 @Test testWhenFeatureInBlockModeAndActivityWindowAbove_blocksTouch()227 public void testWhenFeatureInBlockModeAndActivityWindowAbove_blocksTouch() 228 throws Throwable { 229 setBlockUntrustedTouchesMode(FEATURE_MODE_BLOCK); 230 addActivityOverlay(APP_A, /* opacity */ .9f); 231 232 mTouchHelper.tapOnViewCenter(mContainer); 233 234 assertTouchNotReceived(); 235 } 236 237 @Test testMaximumObscuringOpacity()238 public void testMaximumObscuringOpacity() throws Throwable { 239 // Setting the previous value since we override this on setUp() 240 setMaximumObscuringOpacityForTouch(mPreviousTouchOpacity); 241 242 assertEquals(0.8f, mInputManager.getMaximumObscuringOpacityForTouch()); 243 } 244 245 @Test testAfterSettingThreshold_returnsThresholdSet()246 public void testAfterSettingThreshold_returnsThresholdSet() 247 throws Throwable { 248 float threshold = .123f; 249 setMaximumObscuringOpacityForTouch(threshold); 250 251 assertEquals(threshold, mInputManager.getMaximumObscuringOpacityForTouch()); 252 } 253 254 @Test testAfterSettingFeatureMode_returnsModeSet()255 public void testAfterSettingFeatureMode_returnsModeSet() 256 throws Throwable { 257 // Make sure the previous mode is different 258 setBlockUntrustedTouchesMode(FEATURE_MODE_BLOCK); 259 assertEquals(FEATURE_MODE_BLOCK, mInputManager.getBlockUntrustedTouchesMode(mContext)); 260 setBlockUntrustedTouchesMode(FEATURE_MODE_PERMISSIVE); 261 262 assertEquals(FEATURE_MODE_PERMISSIVE, mInputManager.getBlockUntrustedTouchesMode(mContext)); 263 } 264 265 @Test(expected = IllegalArgumentException.class) testAfterSettingThresholdLessThan0_throws()266 public void testAfterSettingThresholdLessThan0_throws() throws Throwable { 267 setMaximumObscuringOpacityForTouch(-.5f); 268 } 269 270 @Test(expected = IllegalArgumentException.class) testAfterSettingThresholdGreaterThan1_throws()271 public void testAfterSettingThresholdGreaterThan1_throws() throws Throwable { 272 setMaximumObscuringOpacityForTouch(1.5f); 273 } 274 275 /** This is testing what happens if setting is overridden manually */ 276 @Test testAfterSettingThresholdGreaterThan1ViaSettings_previousThresholdIsUsed()277 public void testAfterSettingThresholdGreaterThan1ViaSettings_previousThresholdIsUsed() 278 throws Throwable { 279 setMaximumObscuringOpacityForTouch(.8f); 280 assertEquals(.8f, mInputManager.getMaximumObscuringOpacityForTouch()); 281 SystemUtil.runWithShellPermissionIdentity(() -> { 282 Settings.Global.putFloat(mContentResolver, SETTING_MAXIMUM_OBSCURING_OPACITY, 1.5f); 283 }); 284 addSawOverlay(APP_A, WINDOW_1, 9.f); 285 286 mTouchHelper.tapOnViewCenter(mContainer); 287 288 // Blocks because it's using previous maximum of .8 289 assertTouchNotReceived(); 290 } 291 292 /** This is testing what happens if setting is overridden manually */ 293 @Test testAfterSettingThresholdLessThan0ViaSettings_previousThresholdIsUsed()294 public void testAfterSettingThresholdLessThan0ViaSettings_previousThresholdIsUsed() 295 throws Throwable { 296 setMaximumObscuringOpacityForTouch(.8f); 297 assertEquals(.8f, mInputManager.getMaximumObscuringOpacityForTouch()); 298 SystemUtil.runWithShellPermissionIdentity(() -> { 299 Settings.Global.putFloat(mContentResolver, SETTING_MAXIMUM_OBSCURING_OPACITY, -.5f); 300 }); 301 addSawOverlay(APP_A, WINDOW_1, .7f); 302 303 mTouchHelper.tapOnViewCenter(mContainer); 304 305 // Allows because it's using previous maximum of .8 306 assertTouchReceived(); 307 } 308 309 /** SAWs */ 310 311 @Test testWhenOneSawWindowAboveThreshold_blocksTouch()312 public void testWhenOneSawWindowAboveThreshold_blocksTouch() throws Throwable { 313 addSawOverlay(APP_A, WINDOW_1, .9f); 314 315 mTouchHelper.tapOnViewCenter(mContainer); 316 317 assertTouchNotReceived(); 318 } 319 320 @Test testWhenOneSawWindowBelowThreshold_allowsTouch()321 public void testWhenOneSawWindowBelowThreshold_allowsTouch() throws Throwable { 322 addSawOverlay(APP_A, WINDOW_1, .7f); 323 324 mTouchHelper.tapOnViewCenter(mContainer); 325 326 assertTouchReceived(); 327 } 328 329 @Test testWhenOneSawWindowWithZeroOpacity_allowsTouch()330 public void testWhenOneSawWindowWithZeroOpacity_allowsTouch() throws Throwable { 331 addSawOverlay(APP_A, WINDOW_1, 0f); 332 333 mTouchHelper.tapOnViewCenter(mContainer); 334 335 assertTouchReceived(); 336 } 337 338 @Test testWhenOneSawWindowAtThreshold_allowsTouch()339 public void testWhenOneSawWindowAtThreshold_allowsTouch() throws Throwable { 340 addSawOverlay(APP_A, WINDOW_1, MAXIMUM_OBSCURING_OPACITY); 341 342 mTouchHelper.tapOnViewCenter(mContainer); 343 344 assertTouchReceived(); 345 } 346 347 @Test testWhenTwoSawWindowsFromSameAppTogetherBelowThreshold_allowsTouch()348 public void testWhenTwoSawWindowsFromSameAppTogetherBelowThreshold_allowsTouch() 349 throws Throwable { 350 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75 351 addSawOverlay(APP_A, WINDOW_1, .5f); 352 addSawOverlay(APP_A, WINDOW_2, .5f); 353 354 mTouchHelper.tapOnViewCenter(mContainer); 355 356 assertTouchReceived(); 357 } 358 359 @Test testWhenTwoSawWindowsFromSameAppTogetherAboveThreshold_blocksTouch()360 public void testWhenTwoSawWindowsFromSameAppTogetherAboveThreshold_blocksTouch() 361 throws Throwable { 362 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91 363 addSawOverlay(APP_A, WINDOW_1, .7f); 364 addSawOverlay(APP_A, WINDOW_2, .7f); 365 366 mTouchHelper.tapOnViewCenter(mContainer); 367 368 assertTouchNotReceived(); 369 } 370 371 @Test testWhenTwoSawWindowsFromDifferentAppsEachBelowThreshold_allowsTouch()372 public void testWhenTwoSawWindowsFromDifferentAppsEachBelowThreshold_allowsTouch() 373 throws Throwable { 374 addSawOverlay(APP_A, WINDOW_1, .7f); 375 addSawOverlay(APP_B, WINDOW_2, .7f); 376 377 mTouchHelper.tapOnViewCenter(mContainer); 378 379 assertTouchReceived(); 380 } 381 382 @Test testWhenOneSawWindowAboveThresholdAndSelfSawWindow_blocksTouch()383 public void testWhenOneSawWindowAboveThresholdAndSelfSawWindow_blocksTouch() 384 throws Throwable { 385 addSawOverlay(APP_A, WINDOW_1, .9f); 386 addSawOverlay(APP_SELF, WINDOW_1, .7f); 387 388 mTouchHelper.tapOnViewCenter(mContainer); 389 390 assertTouchNotReceived(); 391 } 392 393 @Test testWhenOneSawWindowBelowThresholdAndSelfSawWindow_allowsTouch()394 public void testWhenOneSawWindowBelowThresholdAndSelfSawWindow_allowsTouch() 395 throws Throwable { 396 addSawOverlay(APP_A, WINDOW_1, .7f); 397 addSawOverlay(APP_SELF, WINDOW_1, .7f); 398 399 mTouchHelper.tapOnViewCenter(mContainer); 400 401 assertTouchReceived(); 402 } 403 404 @Test testWhenTwoSawWindowsTogetherBelowThresholdAndSelfSawWindow_allowsTouch()405 public void testWhenTwoSawWindowsTogetherBelowThresholdAndSelfSawWindow_allowsTouch() 406 throws Throwable { 407 // Resulting opacity for A = 1 - (1 - 0.5)*(1 - 0.5) = .75 408 addSawOverlay(APP_A, WINDOW_1, .5f); 409 addSawOverlay(APP_A, WINDOW_1, .5f); 410 addSawOverlay(APP_SELF, WINDOW_1, .7f); 411 412 mTouchHelper.tapOnViewCenter(mContainer); 413 414 assertTouchReceived(); 415 } 416 417 @Test testWhenThresholdIs0AndSawWindowAtThreshold_allowsTouch()418 public void testWhenThresholdIs0AndSawWindowAtThreshold_allowsTouch() 419 throws Throwable { 420 setMaximumObscuringOpacityForTouch(0); 421 addSawOverlay(APP_A, WINDOW_1, 0); 422 423 mTouchHelper.tapOnViewCenter(mContainer); 424 425 assertTouchReceived(); 426 } 427 428 @Test testWhenThresholdIs0AndSawWindowAboveThreshold_blocksTouch()429 public void testWhenThresholdIs0AndSawWindowAboveThreshold_blocksTouch() 430 throws Throwable { 431 setMaximumObscuringOpacityForTouch(0); 432 addSawOverlay(APP_A, WINDOW_1, .1f); 433 434 mTouchHelper.tapOnViewCenter(mContainer); 435 436 assertTouchNotReceived(); 437 } 438 439 @Test testWhenThresholdIs1AndSawWindowAtThreshold_allowsTouch()440 public void testWhenThresholdIs1AndSawWindowAtThreshold_allowsTouch() 441 throws Throwable { 442 setMaximumObscuringOpacityForTouch(1); 443 addSawOverlay(APP_A, WINDOW_1, 1); 444 445 mTouchHelper.tapOnViewCenter(mContainer); 446 447 assertTouchReceived(); 448 } 449 450 @Test testWhenThresholdIs1AndSawWindowBelowThreshold_allowsTouch()451 public void testWhenThresholdIs1AndSawWindowBelowThreshold_allowsTouch() 452 throws Throwable { 453 setMaximumObscuringOpacityForTouch(1); 454 addSawOverlay(APP_A, WINDOW_1, .9f); 455 456 mTouchHelper.tapOnViewCenter(mContainer); 457 458 assertTouchReceived(); 459 } 460 461 /** Activity windows */ 462 463 @Test testWhenOneActivityWindowBelowThreshold_blocksTouch()464 public void testWhenOneActivityWindowBelowThreshold_blocksTouch() 465 throws Throwable { 466 addActivityOverlay(APP_A, /* opacity */ .5f); 467 468 mTouchHelper.tapOnViewCenter(mContainer); 469 470 assertTouchNotReceived(); 471 } 472 473 @Test testWhenOneActivityWindowAboveThreshold_blocksTouch()474 public void testWhenOneActivityWindowAboveThreshold_blocksTouch() 475 throws Throwable { 476 addActivityOverlay(APP_A, /* opacity */ .9f); 477 478 mTouchHelper.tapOnViewCenter(mContainer); 479 480 assertTouchNotReceived(); 481 } 482 483 @Test testWhenOneActivityWindowWithZeroOpacity_allowsTouch()484 public void testWhenOneActivityWindowWithZeroOpacity_allowsTouch() 485 throws Throwable { 486 addActivityOverlay(APP_A, /* opacity */ 0f); 487 488 mTouchHelper.tapOnViewCenter(mContainer); 489 490 assertTouchReceived(); 491 } 492 493 @Test testWhenOneActivityWindowWithMinPositiveOpacity_blocksTouch()494 public void testWhenOneActivityWindowWithMinPositiveOpacity_blocksTouch() 495 throws Throwable { 496 addActivityOverlay(APP_A, /* opacity */ MIN_POSITIVE_OPACITY); 497 498 mTouchHelper.tapOnViewCenter(mContainer); 499 500 assertTouchNotReceived(); 501 } 502 503 @Test testWhenOneActivityWindowWithSmallOpacity_blocksTouch()504 public void testWhenOneActivityWindowWithSmallOpacity_blocksTouch() 505 throws Throwable { 506 addActivityOverlay(APP_A, /* opacity */ .01f); 507 508 mTouchHelper.tapOnViewCenter(mContainer); 509 510 assertTouchNotReceived(); 511 } 512 513 @Test testWhenOneSelfActivityWindow_allowsTouch()514 public void testWhenOneSelfActivityWindow_allowsTouch() throws Throwable { 515 addActivityOverlay(APP_SELF, /* opacity */ .9f); 516 517 mTouchHelper.tapOnViewCenter(mContainer); 518 519 assertTouchReceived(); 520 } 521 522 @Test testWhenTwoActivityWindowsFromDifferentAppsTogetherBelowThreshold_blocksTouch()523 public void testWhenTwoActivityWindowsFromDifferentAppsTogetherBelowThreshold_blocksTouch() 524 throws Throwable { 525 addActivityOverlay(APP_A, /* opacity */ .7f); 526 addActivityOverlay(APP_B, /* opacity */ .7f); 527 528 mTouchHelper.tapOnViewCenter(mContainer); 529 530 assertTouchNotReceived(); 531 } 532 533 @Test testWhenOneActivityWindowAndOneSawWindowTogetherBelowThreshold_blocksTouch()534 public void testWhenOneActivityWindowAndOneSawWindowTogetherBelowThreshold_blocksTouch() 535 throws Throwable { 536 addActivityOverlay(APP_A, /* opacity */ .5f); 537 addSawOverlay(APP_A, WINDOW_1, .5f); 538 539 mTouchHelper.tapOnViewCenter(mContainer); 540 541 assertTouchNotReceived(); 542 } 543 544 @Test testWhenOneActivityWindowAndOneSelfCustomToastWindow_blocksTouch()545 public void testWhenOneActivityWindowAndOneSelfCustomToastWindow_blocksTouch() 546 throws Throwable { 547 // Toast has to be before otherwise it would be blocked from background 548 addToastOverlay(APP_SELF, /* custom */ true); 549 addActivityOverlay(APP_A, /* opacity */ .5f); 550 551 mTouchHelper.tapOnViewCenter(mContainer); 552 553 assertTouchNotReceived(); 554 } 555 556 @Test testWhenOneActivityWindowAndOneSelfSawWindow_blocksTouch()557 public void testWhenOneActivityWindowAndOneSelfSawWindow_blocksTouch() 558 throws Throwable { 559 addActivityOverlay(APP_A, /* opacity */ .5f); 560 addSawOverlay(APP_SELF, WINDOW_1, .5f); 561 562 mTouchHelper.tapOnViewCenter(mContainer); 563 564 assertTouchNotReceived(); 565 } 566 567 @Test testWhenOneActivityWindowAndOneSawWindowBelowThreshold_blocksTouch()568 public void testWhenOneActivityWindowAndOneSawWindowBelowThreshold_blocksTouch() 569 throws Throwable { 570 addActivityOverlay(APP_A, /* opacity */ .5f); 571 addSawOverlay(APP_A, WINDOW_1, .5f); 572 573 mTouchHelper.tapOnViewCenter(mContainer); 574 575 assertTouchNotReceived(); 576 } 577 578 @Test testWhenOneActivityWindowAndOneSawWindowBelowThresholdFromDifferentApp_blocksTouch()579 public void testWhenOneActivityWindowAndOneSawWindowBelowThresholdFromDifferentApp_blocksTouch() 580 throws Throwable { 581 addActivityOverlay(APP_A, /* opacity */ .5f); 582 addSawOverlay(APP_B, WINDOW_1, .5f); 583 584 mTouchHelper.tapOnViewCenter(mContainer); 585 586 assertTouchNotReceived(); 587 } 588 589 /** Activity-type child windows on same activity */ 590 591 @Test testWhenActivityChildWindowWithSameTokenFromDifferentApp_allowsTouch()592 public void testWhenActivityChildWindowWithSameTokenFromDifferentApp_allowsTouch() 593 throws Exception { 594 IBinder token = mActivity.getWindow().getAttributes().token; 595 addActivityChildWindow(APP_A, WINDOW_1, token); 596 597 mTouchHelper.tapOnViewCenter(mContainer); 598 599 assertTouchReceived(); 600 } 601 602 @Test testWhenActivityChildWindowWithDifferentTokenFromDifferentApp_blocksTouch()603 public void testWhenActivityChildWindowWithDifferentTokenFromDifferentApp_blocksTouch() 604 throws Exception { 605 // Creates a new activity with 0 opacity 606 BlockingResultReceiver receiver = new BlockingResultReceiver(); 607 addActivityOverlay(APP_A, /* opacity */ 0f, receiver); 608 // Verify it allows touches 609 mTouchHelper.tapOnViewCenter(mContainer); 610 assertTouchReceived(); 611 // Now get its token and put a child window from another app with it 612 IBinder token = receiver.getData(TIMEOUT_MS).getBinder(EXTRA_TOKEN); 613 addActivityChildWindow(APP_B, WINDOW_1, token); 614 615 mTouchHelper.tapOnViewCenter(mContainer); 616 617 assertTouchNotReceived(); 618 } 619 620 @Test testWhenActivityChildWindowWithDifferentTokenFromSameApp_allowsTouch()621 public void testWhenActivityChildWindowWithDifferentTokenFromSameApp_allowsTouch() 622 throws Exception { 623 // Creates a new activity with 0 opacity 624 BlockingResultReceiver receiver = new BlockingResultReceiver(); 625 addActivityOverlay(APP_A, /* opacity */ 0f, receiver); 626 // Now get its token and put a child window owned by us 627 IBinder token = receiver.getData(TIMEOUT_MS).getBinder(EXTRA_TOKEN); 628 addActivityChildWindow(APP_SELF, WINDOW_1, token); 629 630 mTouchHelper.tapOnViewCenter(mContainer); 631 632 assertTouchReceived(); 633 } 634 635 /** Activity transitions */ 636 637 @Test testLongEnterAnimations_areLimited()638 public void testLongEnterAnimations_areLimited() { 639 long durationSet = mResources.getInteger(R.integer.long_animation_duration); 640 assertThat(durationSet).isGreaterThan( 641 MAX_ANIMATION_DURATION_MS + ANIMATION_DURATION_TOLERANCE_MS); 642 addAnimatedActivityOverlay(APP_A, /* touchable */ false, R.anim.long_alpha_0_7, 643 R.anim.long_alpha_1); 644 assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY)); 645 long start = SystemClock.elapsedRealtime(); 646 647 assertTrue(mWmState.waitForAppTransitionIdleOnDisplay(Display.DEFAULT_DISPLAY)); 648 long duration = SystemClock.elapsedRealtime() - start; 649 assertThat(duration).isAtMost(MAX_ANIMATION_DURATION_MS + ANIMATION_DURATION_TOLERANCE_MS); 650 } 651 652 @Test testLongExitAnimations_areLimited()653 public void testLongExitAnimations_areLimited() { 654 long durationSet = mResources.getInteger(R.integer.long_animation_duration); 655 assertThat(durationSet).isGreaterThan( 656 MAX_ANIMATION_DURATION_MS + ANIMATION_DURATION_TOLERANCE_MS); 657 addExitAnimationActivity(APP_A); 658 sendFinishToExitAnimationActivity(APP_A, 659 Components.ExitAnimationActivityReceiver.EXTRA_VALUE_LONG_ANIMATION_0_7); 660 assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY)); 661 long start = SystemClock.elapsedRealtime(); 662 663 assertTrue(mWmState.waitForAppTransitionIdleOnDisplay(Display.DEFAULT_DISPLAY)); 664 long duration = SystemClock.elapsedRealtime() - start; 665 assertThat(duration).isAtMost(MAX_ANIMATION_DURATION_MS + ANIMATION_DURATION_TOLERANCE_MS); 666 } 667 668 @Test testWhenEnterAnimationAboveThresholdAndNewActivityNotTouchable_blocksTouch()669 public void testWhenEnterAnimationAboveThresholdAndNewActivityNotTouchable_blocksTouch() { 670 addAnimatedActivityOverlay(APP_A, /* touchable */ false, R.anim.alpha_0_9, R.anim.alpha_1); 671 assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY)); 672 673 mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false); 674 675 assertAnimationRunning(); 676 assertTouchNotReceived(); 677 } 678 679 @Test testWhenEnterAnimationBelowThresholdAndNewActivityNotTouchable_allowsTouch()680 public void testWhenEnterAnimationBelowThresholdAndNewActivityNotTouchable_allowsTouch() { 681 addAnimatedActivityOverlay(APP_A, /* touchable */ false, R.anim.alpha_0_7, R.anim.alpha_1); 682 assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY)); 683 684 mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false); 685 686 assertAnimationRunning(); 687 assertTouchReceived(); 688 } 689 690 @Test testWhenEnterAnimationBelowThresholdAndNewActivityTouchable_blocksTouch()691 public void testWhenEnterAnimationBelowThresholdAndNewActivityTouchable_blocksTouch() { 692 addAnimatedActivityOverlay(APP_A, /* touchable */ true, R.anim.alpha_0_7, R.anim.alpha_1); 693 assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY)); 694 695 mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false); 696 697 assertAnimationRunning(); 698 assertTouchNotReceived(); 699 } 700 701 @Test testWhenExitAnimationBelowThreshold_allowsTouch()702 public void testWhenExitAnimationBelowThreshold_allowsTouch() { 703 addExitAnimationActivity(APP_A); 704 sendFinishToExitAnimationActivity(APP_A, 705 Components.ExitAnimationActivityReceiver.EXTRA_VALUE_ANIMATION_0_7); 706 assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY)); 707 708 mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false); 709 710 assertAnimationRunning(); 711 assertTouchReceived(); 712 } 713 714 @Test testWhenExitAnimationAboveThreshold_blocksTouch()715 public void testWhenExitAnimationAboveThreshold_blocksTouch() { 716 addExitAnimationActivity(APP_A); 717 sendFinishToExitAnimationActivity(APP_A, 718 Components.ExitAnimationActivityReceiver.EXTRA_VALUE_ANIMATION_0_9); 719 assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY)); 720 721 mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false); 722 723 assertAnimationRunning(); 724 assertTouchNotReceived(); 725 } 726 727 @Test testWhenExitAnimationAboveThresholdFromSameUid_allowsTouch()728 public void testWhenExitAnimationAboveThresholdFromSameUid_allowsTouch() { 729 addExitAnimationActivity(APP_SELF); 730 sendFinishToExitAnimationActivity(APP_SELF, 731 Components.ExitAnimationActivityReceiver.EXTRA_VALUE_ANIMATION_0_9); 732 assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY)); 733 734 mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false); 735 736 assertAnimationRunning(); 737 assertTouchReceived(); 738 } 739 740 /** Toast windows */ 741 742 @Test testWhenSelfTextToastWindow_allowsTouch()743 public void testWhenSelfTextToastWindow_allowsTouch() throws Throwable { 744 addToastOverlay(APP_SELF, /* custom */ false); 745 Rect toast = mWmState.waitForResult("toast bounds", 746 state -> state.findFirstWindowWithType(LayoutParams.TYPE_TOAST).getFrame()); 747 748 mTouchHelper.tapOnCenter(toast, mActivity.getDisplayId()); 749 750 assertTouchReceived(); 751 } 752 753 @Test testWhenTextToastWindow_allowsTouch()754 public void testWhenTextToastWindow_allowsTouch() throws Throwable { 755 addToastOverlay(APP_A, /* custom */ false); 756 Rect toast = mWmState.waitForResult("toast bounds", 757 state -> state.findFirstWindowWithType(LayoutParams.TYPE_TOAST).getFrame()); 758 759 mTouchHelper.tapOnCenter(toast, mActivity.getDisplayId()); 760 761 assertTouchReceived(); 762 } 763 764 @Test testWhenOneCustomToastWindow_blocksTouch()765 public void testWhenOneCustomToastWindow_blocksTouch() throws Throwable { 766 addToastOverlay(APP_A, /* custom */ true); 767 768 mTouchHelper.tapOnViewCenter(mContainer); 769 770 assertTouchNotReceived(); 771 } 772 773 @Test testWhenOneSelfCustomToastWindow_allowsTouch()774 public void testWhenOneSelfCustomToastWindow_allowsTouch() throws Throwable { 775 addToastOverlay(APP_SELF, /* custom */ true); 776 777 mTouchHelper.tapOnViewCenter(mContainer); 778 779 assertTouchReceived(); 780 } 781 782 @Test testWhenOneCustomToastWindowAndOneSelfSawWindow_blocksTouch()783 public void testWhenOneCustomToastWindowAndOneSelfSawWindow_blocksTouch() 784 throws Throwable { 785 addSawOverlay(APP_SELF, WINDOW_1, .9f); 786 addToastOverlay(APP_A, /* custom */ true); 787 788 mTouchHelper.tapOnViewCenter(mContainer); 789 790 assertTouchNotReceived(); 791 } 792 793 @Test testWhenOneCustomToastWindowAndOneSawWindowBelowThreshold_blocksTouch()794 public void testWhenOneCustomToastWindowAndOneSawWindowBelowThreshold_blocksTouch() 795 throws Throwable { 796 addSawOverlay(APP_A, WINDOW_1, .5f); 797 addToastOverlay(APP_A, /* custom */ true); 798 799 mTouchHelper.tapOnViewCenter(mContainer); 800 801 assertTouchNotReceived(); 802 } 803 804 @Test testWhenOneCustomToastWindowAndOneSawWindowBelowThresholdFromDifferentApp_blocksTouch()805 public void testWhenOneCustomToastWindowAndOneSawWindowBelowThresholdFromDifferentApp_blocksTouch() 806 throws Throwable { 807 addSawOverlay(APP_A, WINDOW_1, .5f); 808 addToastOverlay(APP_B, /* custom */ true); 809 810 mTouchHelper.tapOnViewCenter(mContainer); 811 812 assertTouchNotReceived(); 813 } 814 815 @Test testWhenOneSelfCustomToastWindowOneSelfActivityWindowAndOneSawBelowThreshold_allowsTouch()816 public void testWhenOneSelfCustomToastWindowOneSelfActivityWindowAndOneSawBelowThreshold_allowsTouch() 817 throws Throwable { 818 addActivityOverlay(APP_SELF, /* opacity */ .9f); 819 addSawOverlay(APP_A, WINDOW_1, .5f); 820 addToastOverlay(APP_SELF, /* custom */ true); 821 822 mTouchHelper.tapOnViewCenter(mContainer); 823 824 assertTouchReceived(); 825 } 826 onTouchEvent(View view, MotionEvent event)827 private boolean onTouchEvent(View view, MotionEvent event) { 828 if (event.getAction() == MotionEvent.ACTION_DOWN) { 829 mTouchesReceived.incrementAndGet(); 830 } 831 return true; 832 } 833 assertTouchReceived()834 private void assertTouchReceived() { 835 mInstrumentation.waitForIdleSync(); 836 assertThat(mTouchesReceived.get()).isEqualTo(1); 837 mTouchesReceived.set(0); 838 } 839 assertTouchNotReceived()840 private void assertTouchNotReceived() { 841 mInstrumentation.waitForIdleSync(); 842 assertThat(mTouchesReceived.get()).isEqualTo(0); 843 mTouchesReceived.set(0); 844 } 845 assertAnimationRunning()846 private void assertAnimationRunning() { 847 assertThat(mWmState.getDisplay(Display.DEFAULT_DISPLAY).getAppTransitionState()).isEqualTo( 848 WindowManagerStateHelper.APP_STATE_RUNNING); 849 } 850 addToastOverlay(String packageName, boolean custom)851 private void addToastOverlay(String packageName, boolean custom) throws Exception { 852 // Making sure there are no toasts currently since we can only check for the presence of 853 // *any* toast afterwards and we don't want to be in a situation where this method returned 854 // because another toast was being displayed. 855 waitForNoToastOverlays(); 856 if (custom) { 857 if (packageName.equals(APP_SELF)) { 858 // We add the custom toast here because we already have foreground status due to 859 // the activity rule, so no need to start another activity. 860 addMyCustomToastOverlay(); 861 } else { 862 // We have to use an activity that will display the toast then finish itself because 863 // custom toasts cannot be posted from the background. 864 Intent intent = new Intent(); 865 intent.setComponent(repackage(packageName, Components.ToastActivity.COMPONENT)); 866 mActivity.startActivity(intent); 867 } 868 } else { 869 getService(packageName).showToast(); 870 } 871 String message = "Toast from app " + packageName + " did not appear on time"; 872 // TODO: WindowStateProto does not have package/UID information from the window, the current 873 // package test relies on the window name, which is not how toast windows are named. We 874 // should ideally incorporate that information in WindowStateProto and use here. 875 if (!mWmState.waitFor("toast window", this::hasVisibleToast)) { 876 fail(message); 877 } 878 } 879 hasVisibleToast(WindowManagerState state)880 private boolean hasVisibleToast(WindowManagerState state) { 881 return !state.getMatchingWindowType(LayoutParams.TYPE_TOAST).isEmpty() 882 && state.findFirstWindowWithType(LayoutParams.TYPE_TOAST).isSurfaceShown(); 883 } 884 addMyCustomToastOverlay()885 private void addMyCustomToastOverlay() { 886 mActivity.runOnUiThread(() -> { 887 mToast = new Toast(mContext); 888 View view = new View(mContext); 889 view.setBackgroundColor(OVERLAY_COLOR); 890 mToast.setView(view); 891 mToast.setGravity(Gravity.FILL, 0, 0); 892 mToast.setDuration(Toast.LENGTH_LONG); 893 mToast.show(); 894 }); 895 mInstrumentation.waitForIdleSync(); 896 } 897 removeMyCustomToastOverlay()898 private void removeMyCustomToastOverlay() { 899 mActivity.runOnUiThread(() -> { 900 if (mToast != null) { 901 mToast.cancel(); 902 mToast = null; 903 } 904 }); 905 mInstrumentation.waitForIdleSync(); 906 } 907 waitForNoToastOverlays()908 private void waitForNoToastOverlays() { 909 waitForNoToastOverlays("Toast windows did not hide on time"); 910 } 911 waitForNoToastOverlays(String message)912 private void waitForNoToastOverlays(String message) { 913 if (!mWmState.waitFor("no toast windows", 914 state -> state.getMatchingWindowType(LayoutParams.TYPE_TOAST).isEmpty())) { 915 fail(message); 916 } 917 } 918 addExitAnimationActivity(String packageName)919 private void addExitAnimationActivity(String packageName) { 920 // This activity responds to broadcasts to exit with animations and it's opaque (translucent 921 // activities don't honor custom exit animations). 922 addActivity(repackage(packageName, Components.ExitAnimationActivity.COMPONENT), 923 /* extras */ null, /* options */ null); 924 } 925 sendFinishToExitAnimationActivity(String packageName, int exitAnimation)926 private void sendFinishToExitAnimationActivity(String packageName, int exitAnimation) { 927 Intent intent = new Intent(Components.ExitAnimationActivityReceiver.ACTION_FINISH); 928 intent.setPackage(packageName); 929 intent.putExtra(Components.ExitAnimationActivityReceiver.EXTRA_ANIMATION, exitAnimation); 930 mContext.sendBroadcast(intent); 931 } 932 addAnimatedActivityOverlay(String packageName, boolean touchable, @AnimRes int enterAnim, @AnimRes int exitAnim)933 private void addAnimatedActivityOverlay(String packageName, boolean touchable, 934 @AnimRes int enterAnim, @AnimRes int exitAnim) { 935 ConditionVariable animationsStarted = new ConditionVariable(false); 936 ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, enterAnim, exitAnim, 937 mMainHandler, animationsStarted::open, /* finishedListener */ null); 938 // We're testing the opacity coming from the animation here, not the one declared in the 939 // activity, so we set its opacity to 1 940 addActivityOverlay(packageName, /* opacity */ 1, touchable, options.toBundle()); 941 animationsStarted.block(); 942 } 943 addActivityChildWindow(String packageName, String windowSuffix, IBinder token)944 private void addActivityChildWindow(String packageName, String windowSuffix, IBinder token) 945 throws Exception { 946 String name = getWindowName(packageName, windowSuffix); 947 getService(packageName).showActivityChildWindow(name, token); 948 if (!mWmState.waitFor("activity child window " + name, 949 state -> state.isWindowVisible(name) && state.isWindowSurfaceShown(name))) { 950 fail("Activity child window " + name + " did not appear on time"); 951 } 952 } 953 addActivityOverlay(String packageName, float opacity)954 private void addActivityOverlay(String packageName, float opacity) { 955 addActivityOverlay(packageName, opacity, /* touchable */ false, /* options */ null); 956 } 957 addActivityOverlay(String packageName, float opacity, boolean touchable, @Nullable Bundle options)958 private void addActivityOverlay(String packageName, float opacity, boolean touchable, 959 @Nullable Bundle options) { 960 Bundle extras = new Bundle(); 961 extras.putFloat(Components.OverlayActivity.EXTRA_OPACITY, opacity); 962 extras.putBoolean(Components.OverlayActivity.EXTRA_TOUCHABLE, touchable); 963 addActivityOverlay(packageName, extras, options); 964 } 965 addActivityOverlay(String packageName, float opacity, BlockingResultReceiver tokenReceiver)966 private void addActivityOverlay(String packageName, float opacity, 967 BlockingResultReceiver tokenReceiver) { 968 Bundle extras = new Bundle(); 969 extras.putFloat(Components.OverlayActivity.EXTRA_OPACITY, opacity); 970 extras.putParcelable(Components.OverlayActivity.EXTRA_TOKEN_RECEIVER, tokenReceiver); 971 addActivityOverlay(packageName, extras, /* options */ null); 972 } 973 addActivityOverlay(String packageName, @Nullable Bundle extras, @Nullable Bundle options)974 private void addActivityOverlay(String packageName, @Nullable Bundle extras, 975 @Nullable Bundle options) { 976 addActivity(repackage(packageName, Components.OverlayActivity.COMPONENT), extras, options); 977 } 978 addActivity(ComponentName component, @Nullable Bundle extras, @Nullable Bundle options)979 private void addActivity(ComponentName component, @Nullable Bundle extras, 980 @Nullable Bundle options) { 981 Intent intent = new Intent(); 982 intent.setComponent(component); 983 if (extras != null) { 984 intent.putExtras(extras); 985 } 986 mActivity.startActivity(intent, options); 987 String packageName = component.getPackageName(); 988 String activity = ComponentNameUtils.getActivityName(component); 989 if (!mWmState.waitFor("activity window " + activity, 990 state -> activity.equals(state.getFocusedActivity()) 991 && state.hasActivityState(component, STATE_RESUMED))) { 992 fail("Activity from app " + packageName + " did not appear on time"); 993 } 994 } 995 removeActivityOverlays()996 private void removeActivityOverlays() { 997 Intent intent = new Intent(mContext, mActivity.getClass()); 998 // Will clear any activity on top of it and it will become the new top 999 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 1000 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 1001 mActivity.startActivity(intent); 1002 } 1003 waitForNoActivityOverlays(String message)1004 private void waitForNoActivityOverlays(String message) { 1005 // Base activity focused means no activities on top 1006 ComponentName component = mActivity.getComponentName(); 1007 String name = ComponentNameUtils.getActivityName(component); 1008 if (!mWmState.waitFor("test rule activity focused", 1009 state -> name.equals(state.getFocusedActivity()) 1010 && state.hasActivityState(component, STATE_RESUMED))) { 1011 fail(message); 1012 } 1013 } 1014 addSawOverlay(String packageName, String windowSuffix, float opacity)1015 private void addSawOverlay(String packageName, String windowSuffix, float opacity) 1016 throws Throwable { 1017 String name = getWindowName(packageName, windowSuffix); 1018 getService(packageName).showSystemAlertWindow(name, opacity); 1019 mSawWindowsAdded.add(name); 1020 if (!mWmState.waitFor("saw window " + name, 1021 state -> state.isWindowVisible(name) && state.isWindowSurfaceShown(name))) { 1022 fail("Saw window " + name + " did not appear on time"); 1023 } 1024 } 1025 waitForNoSawOverlays(String message)1026 private void waitForNoSawOverlays(String message) { 1027 if (!mWmState.waitFor("no SAW windows", 1028 state -> mSawWindowsAdded.stream().allMatch(w -> !state.isWindowVisible(w)))) { 1029 fail(message); 1030 } 1031 mSawWindowsAdded.clear(); 1032 } 1033 removeOverlays()1034 private void removeOverlays() throws Throwable { 1035 for (FutureConnection<IUntrustedTouchTestService> connection : mConnections.values()) { 1036 connection.getCurrent().removeOverlays(); 1037 } 1038 // We need to stop the app because not every overlay is created via the service (eg. 1039 // activity overlays and custom toasts) 1040 for (String app : APPS) { 1041 stopPackage(app); 1042 } 1043 waitForNoSawOverlays("SAWs not removed on time"); 1044 removeActivityOverlays(); 1045 waitForNoActivityOverlays("Activities not removed on time"); 1046 removeMyCustomToastOverlay(); 1047 waitForNoToastOverlays("Toasts not removed on time"); 1048 } 1049 stopPackage(String packageName)1050 private void stopPackage(String packageName) { 1051 SystemUtil.runWithShellPermissionIdentity( 1052 () -> mActivityManager.forceStopPackage(packageName)); 1053 } 1054 setBlockUntrustedTouchesMode(int mode)1055 private int setBlockUntrustedTouchesMode(int mode) throws Exception { 1056 return SystemUtil.callWithShellPermissionIdentity(() -> { 1057 int previous = mInputManager.getBlockUntrustedTouchesMode(mContext); 1058 mInputManager.setBlockUntrustedTouchesMode(mContext, mode); 1059 return previous; 1060 }); 1061 } 1062 setMaximumObscuringOpacityForTouch(float opacity)1063 private float setMaximumObscuringOpacityForTouch(float opacity) throws Exception { 1064 return SystemUtil.callWithShellPermissionIdentity(() -> { 1065 float previous = mInputManager.getMaximumObscuringOpacityForTouch(); 1066 mInputManager.setMaximumObscuringOpacityForTouch(opacity); 1067 return previous; 1068 }); 1069 } 1070 1071 private IUntrustedTouchTestService getService(String packageName) throws Exception { 1072 return mConnections.computeIfAbsent(packageName, this::connect).get(TIMEOUT_MS); 1073 } 1074 1075 private FutureConnection<IUntrustedTouchTestService> connect(String packageName) { 1076 FutureConnection<IUntrustedTouchTestService> connection = 1077 new FutureConnection<>(IUntrustedTouchTestService.Stub::asInterface); 1078 Intent intent = new Intent(); 1079 intent.setComponent(repackage(packageName, Components.UntrustedTouchTestService.COMPONENT)); 1080 assertTrue(mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE)); 1081 return connection; 1082 } 1083 1084 private static String getWindowName(String packageName, String windowSuffix) { 1085 return packageName + "." + windowSuffix; 1086 } 1087 1088 private static ComponentName repackage(String packageName, ComponentName baseComponent) { 1089 return new ComponentName(packageName, baseComponent.getClassName()); 1090 } 1091 1092 public static class TestActivity extends Activity { 1093 public View view; 1094 1095 @Override 1096 protected void onCreate(@Nullable Bundle savedInstanceState) { 1097 super.onCreate(savedInstanceState); 1098 view = new View(this); 1099 view.setBackgroundColor(ACTIVITY_COLOR); 1100 setContentView(view); 1101 } 1102 } 1103 } 1104