1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.activityrecognition.cts 17 18 import android.Manifest 19 import android.app.AppOpsManager 20 import android.app.Instrumentation 21 import android.app.UiAutomation 22 import android.app.role.RoleManager 23 import android.content.Context 24 import android.os.Process 25 import android.os.UserHandle 26 import android.platform.test.annotations.AppModeFull 27 import androidx.test.platform.app.InstrumentationRegistry 28 import com.android.compatibility.common.util.SystemUtil 29 import org.junit.After 30 import org.junit.Assert.fail 31 import org.junit.Before 32 import org.junit.Test 33 import java.util.concurrent.CountDownLatch 34 import java.util.concurrent.TimeUnit 35 36 @AppModeFull(reason="Instant apps have no access to the RoleManager") 37 class RenouncedPermissionsTest { 38 39 var oldActivityRecognizers: List<String>? = null 40 get() { return field } 41 set(value) { field = value } 42 43 @Before makeSelfActivityRecognizernull44 fun makeSelfActivityRecognizer() { 45 SystemUtil.runWithShellPermissionIdentity { 46 val roleManager = context.getSystemService(RoleManager::class.java)!! 47 oldActivityRecognizers = roleManager.getRoleHolders( 48 RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER) 49 roleManager.isBypassingRoleQualification = true 50 addActivityRecognizer(context.packageName) 51 } 52 } 53 54 @After restoreActivityRecognizersnull55 fun restoreActivityRecognizers() { 56 if (oldActivityRecognizers != null) { 57 SystemUtil.runWithShellPermissionIdentity { 58 for (oldActivityRecongizer in oldActivityRecognizers!!) { 59 addActivityRecognizer(oldActivityRecongizer) 60 } 61 val roleManager = context.getSystemService(RoleManager::class.java)!! 62 roleManager.isBypassingRoleQualification = false 63 } 64 } 65 } 66 67 @Before setUpTestnull68 fun setUpTest() { 69 val appOpsManager = context.getSystemService(AppOpsManager::class.java)!! 70 SystemUtil.runWithShellPermissionIdentity { 71 appOpsManager.resetPackageOpsNoHistory(context.packageName) 72 } 73 } 74 addActivityRecognizernull75 fun addActivityRecognizer(activityRecognizer: String) { 76 val latch = CountDownLatch(1) 77 val roleManager = context.getSystemService(RoleManager::class.java)!! 78 roleManager.addRoleHolderAsUser(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER, 79 activityRecognizer, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, 80 UserHandle.SYSTEM, context.mainExecutor) { 81 latch.countDown() 82 } 83 latch.await(5, TimeUnit.SECONDS) 84 } 85 86 @Test testActivityRecognitionAttributionTagBlamingnull87 fun testActivityRecognitionAttributionTagBlaming() { 88 // Using an AR allow listed tag 89 var timeBeforeArAccess = System.currentTimeMillis() 90 accessActivityRecognition(VALID_AR_ATTRIBUTION_TAG) 91 assertNotedOpsSinceLastArAccess(timeBeforeArAccess, /*expectedOp*/ 92 AppOpsManager.OPSTR_ACTIVITY_RECOGNITION_SOURCE, /*unexpectedOp*/ 93 AppOpsManager.OPSTR_ACTIVITY_RECOGNITION) 94 95 // Using an AR not allow listed tag 96 timeBeforeArAccess = System.currentTimeMillis() 97 accessActivityRecognition(INVALID_AR_ATTRIBUTION_TAG) 98 assertNotedOpsSinceLastArAccess(timeBeforeArAccess, /*expectedOp*/ 99 AppOpsManager.OPSTR_ACTIVITY_RECOGNITION, /*unexpectedOp*/ 100 AppOpsManager.OPSTR_ACTIVITY_RECOGNITION_SOURCE) 101 } 102 accessActivityRecognitionnull103 fun accessActivityRecognition(attributionTag: String) { 104 val appOpsManager = context.getSystemService(AppOpsManager::class.java) 105 appOpsManager?.noteOp(AppOpsManager.OPSTR_ACTIVITY_RECOGNITION, Process.myUid(), 106 context.packageName, attributionTag, /*message*/ null) 107 } 108 assertNotedOpsSinceLastArAccessnull109 fun assertNotedOpsSinceLastArAccess(timeBeforeArAccess: Long, 110 expectedOp: String, unexpectedOp: String) { 111 val automation: UiAutomation = instrumentation.getUiAutomation() 112 automation.adoptShellPermissionIdentity(Manifest.permission.GET_APP_OPS_STATS) 113 try { 114 val appOpsManager: AppOpsManager = context.getSystemService(AppOpsManager::class.java)!! 115 val affectedPackageOps = appOpsManager.getPackagesForOps( 116 arrayOf(expectedOp, unexpectedOp)) 117 val packageCount = affectedPackageOps.size 118 for (i in 0 until packageCount) { 119 val packageOps = affectedPackageOps[i] 120 if (!context.getPackageName().equals(packageOps.packageName)) { 121 continue 122 } 123 // We are pulling stats only for one app op. 124 val opEntries = packageOps.ops 125 val opEntryCount = opEntries.size 126 for (j in 0 until opEntryCount) { 127 val opEntry = opEntries[j] 128 if (unexpectedOp == opEntry.opStr) { 129 fail("Unexpected access to $unexpectedOp") 130 } else if (expectedOp == opEntry.opStr) { 131 if (opEntry.getLastAccessTime(AppOpsManager.OP_FLAGS_ALL_TRUSTED) >= 132 timeBeforeArAccess) { 133 return 134 } 135 break 136 } 137 } 138 } 139 fail("No expected access to $expectedOp") 140 } finally { 141 automation.dropShellPermissionIdentity() 142 } 143 } 144 145 companion object { 146 val VALID_AR_ATTRIBUTION_TAG = "valid_ar_attribution_tag" 147 val INVALID_AR_ATTRIBUTION_TAG = "invalid_ar_attribution_tag" 148 149 private val context: Context 150 get () = InstrumentationRegistry.getInstrumentation().getContext() 151 152 private val instrumentation: Instrumentation 153 get () = InstrumentationRegistry.getInstrumentation() 154 } 155 } 156