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