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.permissionui.cts 18 19 import android.Manifest.permission.ACCESS_FINE_LOCATION 20 import android.content.Intent 21 import android.content.pm.PackageManager 22 import android.graphics.Point 23 import android.os.Build 24 import androidx.test.filters.FlakyTest 25 import androidx.test.filters.SdkSuppress 26 import androidx.test.uiautomator.By 27 import com.android.compatibility.common.util.SystemUtil 28 import org.junit.Assume.assumeFalse 29 import org.junit.Before 30 import org.junit.Test 31 32 /** Tests permissions can't be tapjacked */ 33 @FlakyTest 34 class PermissionTapjackingTest : BaseUsePermissionTest() { 35 36 @Before installAppLatestnull37 fun installAppLatest() { 38 installPackage(APP_APK_PATH_WITH_OVERLAY) 39 } 40 41 @Test testTapjackGrantDialog_fullOverlaynull42 fun testTapjackGrantDialog_fullOverlay() { 43 // PermissionController for television uses a floating window. 44 assumeFalse(isTv) 45 46 // Automotive split-screen multitasking uses multi-window mode 47 assumeFalse(isAutomotiveSplitscreen) 48 49 assertAppHasPermission(ACCESS_FINE_LOCATION, false) 50 requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {} 51 52 val buttonCenter = 53 waitFindObject(By.text(getPermissionControllerString(ALLOW_FOREGROUND_BUTTON_TEXT))) 54 .visibleCenter 55 56 // Wait for overlay to hide the dialog 57 context.sendBroadcast(Intent(ACTION_SHOW_OVERLAY).putExtra(EXTRA_FULL_OVERLAY, true)) 58 waitFindObject(By.res("android.permissionui.cts.usepermission:id/overlay")) 59 60 tryClicking(buttonCenter) 61 } 62 63 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 64 @Test testTapjackGrantDialog_partialOverlaynull65 fun testTapjackGrantDialog_partialOverlay() { 66 // PermissionController for television uses a floating window. 67 assumeFalse(isTv) 68 69 // Automotive split-screen multitasking uses multi-window mode 70 assumeFalse(isAutomotiveSplitscreen) 71 72 assertAppHasPermission(ACCESS_FINE_LOCATION, false) 73 requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {} 74 75 val foregroundButtonCenter = 76 waitFindObject(By.text(getPermissionControllerString(ALLOW_FOREGROUND_BUTTON_TEXT))) 77 .visibleCenter 78 val oneTimeButton = 79 waitFindObjectOrNull(By.text(getPermissionControllerString(ALLOW_ONE_TIME_BUTTON_TEXT))) 80 // If one-time button is not available, fallback to deny button 81 val overlayButtonBounds = 82 oneTimeButton?.visibleBounds 83 ?: waitFindObject(By.text(getPermissionControllerString(DENY_BUTTON_TEXT))) 84 .visibleBounds 85 86 // Wait for overlay to hide the dialog 87 context.sendBroadcast( 88 Intent(ACTION_SHOW_OVERLAY) 89 .putExtra(EXTRA_FULL_OVERLAY, false) 90 .putExtra(OVERLAY_LEFT, overlayButtonBounds.left) 91 .putExtra(OVERLAY_TOP, overlayButtonBounds.top) 92 .putExtra(OVERLAY_RIGHT, overlayButtonBounds.right) 93 .putExtra(OVERLAY_BOTTOM, overlayButtonBounds.bottom) 94 ) 95 waitFindObject(By.res("android.permissionui.cts.usepermission:id/overlay")) 96 97 tryClicking(foregroundButtonCenter) 98 } 99 tryClickingnull100 private fun tryClicking(buttonCenter: Point) { 101 try { 102 // Try to grant the permission, this should fail 103 SystemUtil.eventually( 104 { 105 if ( 106 packageManager.checkPermission(ACCESS_FINE_LOCATION, APP_PACKAGE_NAME) == 107 PackageManager.PERMISSION_DENIED 108 ) { 109 uiDevice.click(buttonCenter.x, buttonCenter.y) 110 Thread.sleep(100) 111 } 112 assertAppHasPermission(ACCESS_FINE_LOCATION, true) 113 }, 114 10000 115 ) 116 } catch (e: RuntimeException) { 117 // expected 118 } 119 // Permission should not be granted 120 assertAppHasPermission(ACCESS_FINE_LOCATION, false) 121 122 // Verify that clicking the dialog without the overlay still works 123 context.sendBroadcast(Intent(ACTION_HIDE_OVERLAY)) 124 SystemUtil.eventually( 125 { 126 if ( 127 packageManager.checkPermission(ACCESS_FINE_LOCATION, APP_PACKAGE_NAME) == 128 PackageManager.PERMISSION_DENIED 129 ) { 130 uiDevice.click(buttonCenter.x, buttonCenter.y) 131 Thread.sleep(100) 132 } 133 assertAppHasPermission(ACCESS_FINE_LOCATION, true) 134 }, 135 10000 136 ) 137 } 138 139 companion object { 140 const val ACTION_SHOW_OVERLAY = "android.permissionui.cts.usepermission.ACTION_SHOW_OVERLAY" 141 const val ACTION_HIDE_OVERLAY = "android.permissionui.cts.usepermission.ACTION_HIDE_OVERLAY" 142 143 const val EXTRA_FULL_OVERLAY = "android.permissionui.cts.usepermission.extra.FULL_OVERLAY" 144 145 const val OVERLAY_LEFT = "android.permissionui.cts.usepermission.extra.OVERLAY_LEFT" 146 const val OVERLAY_TOP = "android.permissionui.cts.usepermission.extra.OVERLAY_TOP" 147 const val OVERLAY_RIGHT = "android.permissionui.cts.usepermission.extra.OVERLAY_RIGHT" 148 const val OVERLAY_BOTTOM = "android.permissionui.cts.usepermission.extra.OVERLAY_BOTTOM" 149 } 150 } 151