1 package android.app.appops.cts
2 
3 /*
4  * Copyright (C) 2014 The Android Open Source Project
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License")
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 import android.Manifest.permission
20 import android.app.AppOpsManager
21 import android.app.AppOpsManager.MODE_ALLOWED
22 import android.app.AppOpsManager.MODE_DEFAULT
23 import android.app.AppOpsManager.MODE_ERRORED
24 import android.app.AppOpsManager.MODE_IGNORED
25 import android.app.AppOpsManager.OPSTR_RESERVED_FOR_TESTING
26 import android.app.AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS
27 import android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA
28 import android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE
29 import android.app.AppOpsManager.OPSTR_PICTURE_IN_PICTURE
30 import android.app.AppOpsManager.OPSTR_VIBRATE
31 import android.app.AppOpsManager.OPSTR_WIFI_SCAN
32 import android.app.AppOpsManager.OP_FLAG_SELF
33 import android.app.AppOpsManager.OnOpChangedListener
34 import android.app.AppOpsManager.OnOpNotedListener
35 import android.companion.virtual.VirtualDeviceManager
36 import android.content.Context
37 import android.content.pm.PackageManager
38 import android.os.Process
39 import android.os.UserHandle
40 import android.permission.flags.Flags
41 import android.platform.test.annotations.AppModeFull
42 import android.platform.test.annotations.RequiresFlagsEnabled
43 import android.platform.test.flag.junit.DeviceFlagsValueProvider
44 import android.util.Log
45 import androidx.test.InstrumentationRegistry
46 import androidx.test.filters.FlakyTest
47 import androidx.test.runner.AndroidJUnit4
48 import com.google.common.base.Objects
49 import java.util.concurrent.LinkedBlockingQueue
50 import com.android.compatibility.common.util.PollingCheck
51 import com.google.common.truth.Truth.assertThat
52 import java.util.concurrent.CompletableFuture
53 import java.util.concurrent.Executor
54 import java.util.concurrent.LinkedBlockingDeque
55 import java.util.concurrent.TimeUnit
56 import org.junit.Assert
57 import org.junit.Assert.assertEquals
58 import org.junit.Assert.assertFalse
59 import org.junit.Assert.assertNotNull
60 import org.junit.Assert.assertNull
61 import org.junit.Assert.assertSame
62 import org.junit.Assert.assertTrue
63 import org.junit.Assert.fail
64 import org.junit.Assume.assumeTrue
65 import org.junit.Before
66 import org.junit.Ignore
67 import org.junit.Rule
68 import org.junit.Test
69 import org.junit.runner.RunWith
70 
71 @RunWith(AndroidJUnit4::class)
72 class AppOpsTest {
73     private lateinit var mAppOps: AppOpsManager
74     private lateinit var mContext: Context
75     private lateinit var mOpPackageName: String
76     private val mMyUid = Process.myUid()
77 
78     @get:Rule val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
79 
80     companion object {
81         // These permissions and opStrs must map to the same op codes.
82         val permissionToOpStr = HashMap<String, String>()
83         private val TIMEOUT_MS = 10000L
84         private val SHELL_PACKAGE_NAME = "com.android.shell"
85         private val TEST_ATTRIBUTION = "testAttribution"
86         private val LOG_TAG = AppOpsTest::class.java.simpleName
87 
88         init {
89             permissionToOpStr[permission.ACCESS_COARSE_LOCATION] =
90                     AppOpsManager.OPSTR_COARSE_LOCATION
91             permissionToOpStr[permission.ACCESS_FINE_LOCATION] =
92                     AppOpsManager.OPSTR_FINE_LOCATION
93             permissionToOpStr[permission.READ_CONTACTS] =
94                     AppOpsManager.OPSTR_READ_CONTACTS
95             permissionToOpStr[permission.WRITE_CONTACTS] =
96                     AppOpsManager.OPSTR_WRITE_CONTACTS
97             permissionToOpStr[permission.READ_CALL_LOG] =
98                     AppOpsManager.OPSTR_READ_CALL_LOG
99             permissionToOpStr[permission.WRITE_CALL_LOG] =
100                     AppOpsManager.OPSTR_WRITE_CALL_LOG
101             permissionToOpStr[permission.READ_CALENDAR] =
102                     AppOpsManager.OPSTR_READ_CALENDAR
103             permissionToOpStr[permission.WRITE_CALENDAR] =
104                     AppOpsManager.OPSTR_WRITE_CALENDAR
105             permissionToOpStr[permission.CALL_PHONE] =
106                     AppOpsManager.OPSTR_CALL_PHONE
107             permissionToOpStr[permission.READ_SMS] =
108                     AppOpsManager.OPSTR_READ_SMS
109             permissionToOpStr[permission.RECEIVE_SMS] =
110                     AppOpsManager.OPSTR_RECEIVE_SMS
111             permissionToOpStr[permission.RECEIVE_MMS] =
112                     AppOpsManager.OPSTR_RECEIVE_MMS
113             permissionToOpStr[permission.RECEIVE_WAP_PUSH] =
114                     AppOpsManager.OPSTR_RECEIVE_WAP_PUSH
115             permissionToOpStr[permission.SEND_SMS] =
116                     AppOpsManager.OPSTR_SEND_SMS
117             permissionToOpStr[permission.READ_SMS] =
118                     AppOpsManager.OPSTR_READ_SMS
119             permissionToOpStr[permission.WRITE_SETTINGS] =
120                     AppOpsManager.OPSTR_WRITE_SETTINGS
121             permissionToOpStr[permission.SYSTEM_ALERT_WINDOW] =
122                     AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW
123             permissionToOpStr[permission.ACCESS_NOTIFICATIONS] =
124                     AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS
125             permissionToOpStr[permission.CAMERA] =
126                     AppOpsManager.OPSTR_CAMERA
127             permissionToOpStr[permission.RECORD_AUDIO] =
128                     AppOpsManager.OPSTR_RECORD_AUDIO
129             permissionToOpStr[permission.READ_PHONE_STATE] =
130                     AppOpsManager.OPSTR_READ_PHONE_STATE
131             permissionToOpStr[permission.ADD_VOICEMAIL] =
132                     AppOpsManager.OPSTR_ADD_VOICEMAIL
133             permissionToOpStr[permission.USE_SIP] =
134                     AppOpsManager.OPSTR_USE_SIP
135             permissionToOpStr[permission.PROCESS_OUTGOING_CALLS] =
136                     AppOpsManager.OPSTR_PROCESS_OUTGOING_CALLS
137             permissionToOpStr[permission.BODY_SENSORS] =
138                     AppOpsManager.OPSTR_BODY_SENSORS
139             permissionToOpStr[permission.READ_CELL_BROADCASTS] =
140                     AppOpsManager.OPSTR_READ_CELL_BROADCASTS
141             permissionToOpStr[permission.READ_EXTERNAL_STORAGE] =
142                     AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE
143             permissionToOpStr[permission.WRITE_EXTERNAL_STORAGE] =
144                     AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE
145             permissionToOpStr[permission.INTERACT_ACROSS_PROFILES] =
146                     AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES
147         }
148 
149         val USER_SHELL_UID = UserHandle.getUid(Process.myUserHandle().identifier,
150                 UserHandle.getAppId(Process.SHELL_UID))
151     }
152 
153     @Before
setUpnull154     fun setUp() {
155         mContext = InstrumentationRegistry.getContext()
156         mAppOps = mContext.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
157         mOpPackageName = mContext.opPackageName
158         assertNotNull(mAppOps)
159         // Reset app ops state for this test package to the system default.
160         reset(mOpPackageName)
161     }
162 
163     @Test
testNoteOpAndCheckOpnull164     fun testNoteOpAndCheckOp() {
165         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_ALLOWED)
166         assertEquals(MODE_ALLOWED, mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
167                 Process.myUid(), mOpPackageName))
168         assertEquals(MODE_ALLOWED, mAppOps.noteOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
169                 Process.myUid(), mOpPackageName))
170         assertEquals(MODE_ALLOWED, mAppOps.unsafeCheckOp(OPSTR_RESERVED_FOR_TESTING,
171                 Process.myUid(), mOpPackageName))
172         assertEquals(MODE_ALLOWED, mAppOps.unsafeCheckOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
173                 Process.myUid(), mOpPackageName))
174 
175         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_IGNORED)
176         assertEquals(MODE_IGNORED, mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
177                 Process.myUid(), mOpPackageName))
178         assertEquals(MODE_IGNORED, mAppOps.noteOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
179                 Process.myUid(), mOpPackageName))
180         assertEquals(MODE_IGNORED, mAppOps.unsafeCheckOp(OPSTR_RESERVED_FOR_TESTING,
181                 Process.myUid(), mOpPackageName))
182         assertEquals(MODE_IGNORED, mAppOps.unsafeCheckOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
183                 Process.myUid(), mOpPackageName))
184 
185         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_DEFAULT)
186         assertEquals(MODE_DEFAULT, mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
187                 Process.myUid(), mOpPackageName))
188         assertEquals(MODE_DEFAULT, mAppOps.noteOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
189                 Process.myUid(), mOpPackageName))
190         assertEquals(MODE_DEFAULT, mAppOps.unsafeCheckOp(OPSTR_RESERVED_FOR_TESTING,
191                 Process.myUid(), mOpPackageName))
192         assertEquals(MODE_DEFAULT, mAppOps.unsafeCheckOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
193                 Process.myUid(), mOpPackageName))
194 
195         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_ERRORED)
196         assertEquals(MODE_ERRORED, mAppOps.noteOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
197                 Process.myUid(), mOpPackageName))
198         assertEquals(MODE_ERRORED, mAppOps.unsafeCheckOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
199                 Process.myUid(), mOpPackageName))
200         try {
201             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName)
202             fail("SecurityException expected")
203         } catch (expected: SecurityException) {
204         }
205         try {
206             mAppOps.unsafeCheckOp(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName)
207             fail("SecurityException expected")
208         } catch (expected: SecurityException) {
209         }
210     }
211 
212     @Test
testStartOpAndFinishOpnull213     fun testStartOpAndFinishOp() {
214         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_ALLOWED)
215         assertEquals(MODE_ALLOWED, mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING,
216                 Process.myUid(), mOpPackageName))
217         mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName)
218         assertEquals(MODE_ALLOWED, mAppOps.startOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
219                 Process.myUid(), mOpPackageName))
220         mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING,
221                 Process.myUid(), mOpPackageName)
222 
223         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_IGNORED)
224         assertEquals(MODE_IGNORED, mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING,
225                 Process.myUid(), mOpPackageName))
226         assertEquals(MODE_IGNORED, mAppOps.startOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
227                 Process.myUid(), mOpPackageName))
228 
229         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_DEFAULT)
230         assertEquals(MODE_DEFAULT, mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING,
231                 Process.myUid(), mOpPackageName))
232         assertEquals(MODE_DEFAULT, mAppOps.startOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
233                 Process.myUid(), mOpPackageName))
234 
235         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_ERRORED)
236         assertEquals(MODE_ERRORED, mAppOps.startOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
237                 Process.myUid(), mOpPackageName))
238         try {
239             mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName)
240             fail("SecurityException expected")
241         } catch (expected: SecurityException) {
242         }
243     }
244 
245     @Test
246     @AppModeFull(reason = "Instant app cannot query for the shell package")
overlappingActiveAttributionOpsnull247     fun overlappingActiveAttributionOps() {
248         val activeChangedQueue = LinkedBlockingQueue<Boolean>()
249         runWithShellPermissionIdentity {
250             val activeWatcher =
251                 object: AppOpsManager.OnOpActiveChangedListener {
252                     override fun onOpActiveChanged(op: String,
253                         uid: Int,
254                         packageName: String,
255                         active: Boolean) {
256                         if (packageName == SHELL_PACKAGE_NAME) {
257                             activeChangedQueue.put(active)
258                         }
259                     }
260                 }
261 
262             mAppOps.startWatchingActive(arrayOf(OPSTR_RESERVED_FOR_TESTING), { it.run() },
263                 activeWatcher)
264             try {
265                 mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, "firstAttribution",
266                         null)
267 
268                 assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, USER_SHELL_UID,
269                         SHELL_PACKAGE_NAME))
270                 var activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
271                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
272                     activeState)
273                 assertTrue(activeState!!)
274 
275                 mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName,
276                     "secondAttribution", null)
277 
278                 assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, USER_SHELL_UID,
279                         SHELL_PACKAGE_NAME))
280                 var exception = try {
281                     assertNotNull("Unexpected onOpChanged callback received",
282                         activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
283                     null
284                 } catch (e: AssertionError) {
285                     e
286                 }
287                 assertNotNull(exception)
288 
289                 mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, USER_SHELL_UID, SHELL_PACKAGE_NAME,
290                     "firstAttribution")
291 
292                 assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, USER_SHELL_UID,
293                         SHELL_PACKAGE_NAME))
294                 exception = try {
295                     assertNotNull("Unexpected onOpChanged callback received",
296                         activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
297                     null
298                 } catch (e: AssertionError) {
299                     e
300                 }
301                 assertNotNull(exception)
302 
303                 mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, USER_SHELL_UID, SHELL_PACKAGE_NAME,
304                     "secondAttribution")
305 
306                 assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, USER_SHELL_UID,
307                         SHELL_PACKAGE_NAME))
308                 activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
309                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
310                     activeState)
311                 assertFalse(activeState!!)
312             } finally {
313                 mAppOps.stopWatchingActive(activeWatcher)
314             }
315         }
316     }
317 
318     @Test
319     @AppModeFull(reason = "Instant app cannot query for the shell package")
startOpTwiceAndVerifyChangeListenernull320     fun startOpTwiceAndVerifyChangeListener() {
321         runWithShellPermissionIdentity {
322             val activeChangedQueue = LinkedBlockingQueue<Boolean>()
323             val activeWatcher =
324                     object: AppOpsManager.OnOpActiveChangedListener {
325                         override fun onOpActiveChanged(op: String,
326                             uid: Int,
327                             packageName: String,
328                             active: Boolean) {
329                             if (packageName == SHELL_PACKAGE_NAME && uid == USER_SHELL_UID) {
330                                 activeChangedQueue.put(active)
331                             }
332                         }
333                     }
334             mAppOps.startWatchingActive(arrayOf(OPSTR_WIFI_SCAN), { it.run() },
335                     activeWatcher)
336             try {
337                 mAppOps.startOp(OPSTR_WIFI_SCAN, mMyUid, mOpPackageName, null, null)
338 
339                 var activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
340                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
341                     activeState)
342                 assertTrue(activeState!!)
343 
344                 mAppOps.finishOp(OPSTR_WIFI_SCAN, USER_SHELL_UID, SHELL_PACKAGE_NAME, null)
345 
346                 activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
347                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
348                     activeState)
349                 assertFalse(activeState!!)
350 
351                 mAppOps.startOp(OPSTR_WIFI_SCAN, mMyUid, mOpPackageName, null, null)
352                 activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
353                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
354                     activeState)
355                 assertTrue(activeState!!)
356 
357                 mAppOps.finishOp(OPSTR_WIFI_SCAN, USER_SHELL_UID, SHELL_PACKAGE_NAME, null)
358 
359                 activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
360                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
361                     activeState)
362                 assertFalse(activeState!!)
363             } finally {
364                 mAppOps.stopWatchingActive(activeWatcher)
365             }
366         }
367     }
368 
369     @Test
370     @AppModeFull(reason = "Instant app cannot query for the shell package")
371     @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
startOpTwiceAndVerifyDeviceAttributedChangeListenernull372     fun startOpTwiceAndVerifyDeviceAttributedChangeListener() {
373         runWithShellPermissionIdentity {
374             val activeChangedQueue = LinkedBlockingQueue<Boolean>()
375             val activeWatcher =
376                     object: AppOpsManager.OnOpActiveChangedListener {
377                         override fun onOpActiveChanged(op: String,
378                             uid: Int,
379                             packageName: String,
380                             active: Boolean) {}
381 
382                         override fun onOpActiveChanged(op: String,
383                             uid: Int,
384                             packageName: String,
385                             attributionTag: String?,
386                             virtualDeviceId: Int,
387                             active: Boolean,
388                             attributionFlags: Int,
389                             attributionChainId: Int) {
390                             if (packageName == SHELL_PACKAGE_NAME && uid == USER_SHELL_UID
391                                 && virtualDeviceId == Context.DEVICE_ID_DEFAULT) {
392                                 activeChangedQueue.put(active)
393                             }
394                         }
395                     }
396             mAppOps.startWatchingActive(arrayOf(OPSTR_WIFI_SCAN), { it.run() },
397                     activeWatcher)
398             try {
399                 mAppOps.startOp(OPSTR_WIFI_SCAN, mMyUid, mOpPackageName, null, null)
400 
401                 var activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
402                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
403                     activeState)
404                 assertTrue(activeState!!)
405 
406                 mAppOps.finishOp(OPSTR_WIFI_SCAN, USER_SHELL_UID, SHELL_PACKAGE_NAME, null)
407 
408                 activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
409                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
410                     activeState)
411                 assertFalse(activeState!!)
412 
413                 mAppOps.startOp(OPSTR_WIFI_SCAN, mMyUid, mOpPackageName, null, null)
414                 activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
415                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
416                     activeState)
417                 assertTrue(activeState!!)
418 
419                 mAppOps.finishOp(OPSTR_WIFI_SCAN, USER_SHELL_UID, SHELL_PACKAGE_NAME, null)
420 
421                 activeState = activeChangedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)
422                 assertNotNull("Did not receive onOpChanged callback within $TIMEOUT_MS ms",
423                     activeState)
424                 assertFalse(activeState!!)
425             } finally {
426                 mAppOps.stopWatchingActive(activeWatcher)
427             }
428         }
429     }
430 
431     @Test
finishOpWithoutStartOpnull432     fun finishOpWithoutStartOp() {
433         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
434 
435         mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null)
436         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
437     }
438 
439     @Test
doubleFinishOpStartOpnull440     fun doubleFinishOpStartOp() {
441         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
442 
443         mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null, null)
444         assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
445 
446         mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null)
447         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
448         mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null)
449         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
450     }
451 
452     @Test
doubleFinishOpAfterDoubleStartOpnull453     fun doubleFinishOpAfterDoubleStartOp() {
454         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
455 
456         mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null, null)
457         assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
458         mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null, null)
459         assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
460 
461         mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null)
462         assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
463         mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null)
464         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
465     }
466 
467     @Test
noteOpWhileOpIsActivenull468     fun noteOpWhileOpIsActive() {
469         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
470 
471         mAppOps.startOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null, null)
472         assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
473 
474         mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null, null)
475         assertTrue(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
476 
477         mAppOps.finishOp(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName, null)
478         assertFalse(mAppOps.isOpActive(OPSTR_RESERVED_FOR_TESTING, mMyUid, mOpPackageName))
479     }
480 
481     @Test
testCheckPackagePassesChecknull482     fun testCheckPackagePassesCheck() {
483         mAppOps.checkPackage(Process.myUid(), mOpPackageName)
484         mAppOps.checkPackage(Process.SYSTEM_UID, "android")
485     }
486 
487     @Test
testCheckPackageDoesntPassChecknull488     fun testCheckPackageDoesntPassCheck() {
489         try {
490             // Package name doesn't match UID.
491             mAppOps.checkPackage(Process.SYSTEM_UID, mOpPackageName)
492             fail("SecurityException expected")
493         } catch (expected: SecurityException) {
494         }
495 
496         try {
497             // Package name doesn't match UID.
498             mAppOps.checkPackage(Process.myUid(), "android")
499             fail("SecurityException expected")
500         } catch (expected: SecurityException) {
501         }
502 
503         try {
504             // Package name missing
505             mAppOps.checkPackage(Process.myUid(), "")
506             fail("SecurityException expected")
507         } catch (expected: SecurityException) {
508         }
509     }
510 
511     @Test
testWatchingMode_receivesCallbacknull512     fun testWatchingMode_receivesCallback() {
513         val changedQueue = LinkedBlockingQueue<Int>()
514         val onOpChangeWatcher = object: OnOpChangedListener {
515             private var onOpChangedCount = 0
516             override fun onOpChanged(op: String?, packageName: String?) {
517                 if (Objects.equal(op, OPSTR_RESERVED_FOR_TESTING)
518                     && Objects.equal(packageName, mOpPackageName)) {
519                     changedQueue.put(onOpChangedCount++)
520                     return
521                 }
522                 Log.w(LOG_TAG,
523                     "Received unexpected onOpChanged callback for op $op packageName $packageName")
524             }
525         }
526 
527         try {
528             runWithShellPermissionIdentity {
529                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ALLOWED)
530                 mAppOps.startWatchingMode(OPSTR_RESERVED_FOR_TESTING, mOpPackageName, onOpChangeWatcher)
531 
532                 // After start watching, change op mode should trigger callback
533                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ERRORED)
534                 assertEquals("onOpChanged callback count unexpected",
535                     changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS), 0)
536 
537                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ALLOWED)
538                 assertEquals("onOpChanged callback count unexpected",
539                     changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS), 1)
540 
541                 // If mode doesn't change, no callback expected
542                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ALLOWED)
543                 assertNull(changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
544 
545                 mAppOps.stopWatchingMode(onOpChangeWatcher)
546 
547                 // After stop watching no callback expected when mode changes
548                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ERRORED)
549                 assertNull(changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
550             }
551         } finally {
552             mAppOps.stopWatchingMode(onOpChangeWatcher)
553         }
554     }
555 
556     @Test
557     @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
testWatchingMode_receivesDeviceAttributedCallbacknull558     fun testWatchingMode_receivesDeviceAttributedCallback() {
559         val changedQueue = LinkedBlockingQueue<Int>()
560         val onOpChangeWatcher = object: OnOpChangedListener{
561             private var onOpChangedCount = 0
562             override fun onOpChanged(op: String?, packageName: String?) {}
563 
564             override fun onOpChanged(op: String,
565                 packageName: String,
566                 userId: Int,
567                 persistentDeviceId: String) {
568                 if (Objects.equal(op, OPSTR_RESERVED_FOR_TESTING)
569                     && Objects.equal(packageName, mOpPackageName)
570                     && Objects.equal(persistentDeviceId,
571                         VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)) {
572                     changedQueue.put(onOpChangedCount++)
573                     return
574                 }
575                 Log.w(LOG_TAG,
576                     "Received unexpected onOpChanged callback for op $op packageName $packageName")
577             }
578         }
579         try {
580             runWithShellPermissionIdentity {
581                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ALLOWED)
582                 mAppOps.startWatchingMode(OPSTR_RESERVED_FOR_TESTING, mOpPackageName, onOpChangeWatcher)
583 
584                 // After start watching, change op mode should trigger callback
585                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ERRORED)
586                 assertEquals("onOpChanged callback count unexpected",
587                     changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
588                     0)
589 
590                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ALLOWED)
591                 assertEquals("onOpChanged callback count unexpected",
592                     changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS), 1)
593 
594                 // If mode doesn't change, no callback expected
595                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ALLOWED)
596                 assertNull(changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
597 
598                 mAppOps.stopWatchingMode(onOpChangeWatcher)
599 
600                 // After stop watching no callback expected when mode changes
601                 mAppOps.setMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName, MODE_ERRORED)
602                 assertNull(changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
603             }
604         } finally {
605             mAppOps.stopWatchingMode(onOpChangeWatcher)
606         }
607     }
608 
609     @Test
startWatchingNoted_withoutExecutor_whenOpNoted_receivesCallbacknull610     fun startWatchingNoted_withoutExecutor_whenOpNoted_receivesCallback() {
611         val notedQueue = LinkedBlockingQueue<Int>()
612         val notedWatcher = object: OnOpNotedListener{
613             var opNotedCount = 0
614             override fun onOpNoted(op: String,
615                 uid: Int,
616                 packageName: String,
617                 attributionTag: String?,
618                 flags: Int,
619                 result: Int) {
620                 if (Objects.equal(op, OPSTR_RESERVED_FOR_TESTING)
621                     && uid == mMyUid && Objects.equal(packageName, mOpPackageName)
622                     && attributionTag == null
623                     && flags == OP_FLAG_SELF && result == MODE_ALLOWED) {
624                     notedQueue.put(opNotedCount++)
625                 }
626             }
627         }
628         try {
629             mAppOps.startWatchingNoted(arrayOf(OPSTR_RESERVED_FOR_TESTING), notedWatcher)
630 
631             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
632                 mMyUid, mOpPackageName,
633                     /* attributionTag = */ null,
634                 /* message = */ null)
635 
636             assertEquals("onOpNoted callback count unexpected",
637                 notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
638                 0)
639 
640             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
641                 mMyUid,
642                 mOpPackageName,
643                     /* attributionTag = */ null,
644                 /* message = */ null)
645 
646             assertEquals("onOpNoted callback count unexpected",
647                 notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
648                 1)
649 
650             mAppOps.stopWatchingNoted(notedWatcher)
651 
652             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
653                 mMyUid,
654                 mOpPackageName,
655                     /* attributionTag = */ null,
656                 /* message = */ null)
657 
658             val exception = try {
659                 assertNotNull(notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
660                 null
661             } catch (e: AssertionError) {
662                 e
663             }
664             assertNotNull("Unexpected onOpNoted callback received", exception)
665         } finally {
666             mAppOps.stopWatchingNoted(notedWatcher)
667         }
668     }
669 
670     @Test
startWatchingNoted_withExecutor_whenOpNoted_receivesCallbacknull671     fun startWatchingNoted_withExecutor_whenOpNoted_receivesCallback() {
672         val notedQueue = LinkedBlockingQueue<Int>()
673         val notedWatcher = object: OnOpNotedListener{
674             var opNotedCount = 0
675             override fun onOpNoted(op: String,
676                 uid: Int,
677                 packageName: String,
678                 attributionTag: String?,
679                 flags: Int,
680                 result: Int) {
681                 if (Objects.equal(op, OPSTR_RESERVED_FOR_TESTING)
682                     && uid == mMyUid && Objects.equal(packageName, mOpPackageName)
683                     && Objects.equal(attributionTag, TEST_ATTRIBUTION)
684                     && flags == OP_FLAG_SELF && result == MODE_ALLOWED) {
685                     notedQueue.put(opNotedCount++)
686                 }
687             }
688         }
689         try {
690             mAppOps.startWatchingNoted(arrayOf(OPSTR_RESERVED_FOR_TESTING), { it.run() }, notedWatcher)
691 
692             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
693                 mMyUid, mOpPackageName,
694                 TEST_ATTRIBUTION,
695                 /* message = */ null)
696 
697             assertEquals("onOpNoted callback count unexpected",
698                 notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
699                 0)
700 
701             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
702                 mMyUid,
703                 mOpPackageName,
704                 TEST_ATTRIBUTION,
705                 /* message = */ null)
706 
707             assertEquals("onOpNoted callback count unexpected",
708                 notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
709                 1)
710 
711             mAppOps.stopWatchingNoted(notedWatcher)
712 
713             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
714                 mMyUid,
715                 mOpPackageName,
716                 TEST_ATTRIBUTION,
717                 /* message = */ null)
718 
719             val exception = try {
720                 assertNotNull(notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
721                 null
722             } catch (e: AssertionError) {
723                 e
724             }
725             assertNotNull("Unexpected onOpNoted callback received", exception)
726         } finally {
727             mAppOps.stopWatchingNoted(notedWatcher)
728         }
729     }
730 
731     @Test
732     @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
startWatchingNoted_withoutExecutor_whenOpNoted_receivesDeviceAttributedCallbacknull733     fun startWatchingNoted_withoutExecutor_whenOpNoted_receivesDeviceAttributedCallback() {
734         val notedQueue = LinkedBlockingQueue<Int>()
735         val notedWatcher = object: OnOpNotedListener{
736             var opNotedCount = 0
737             override fun onOpNoted(op: String,
738                 uid: Int,
739                 packageName: String,
740                 attributionTag: String?,
741                 flags: Int,
742                 result: Int) {}
743 
744             override fun onOpNoted(op: String,
745                 uid: Int,
746                 packageName: String,
747                 attributionTag: String?,
748                 virtualDeviceId: Int,
749                 flags: Int,
750                 result: Int) {
751                 if (Objects.equal(op, OPSTR_RESERVED_FOR_TESTING)
752                     && uid == mMyUid && Objects.equal(packageName, mOpPackageName)
753                     && Objects.equal(attributionTag, TEST_ATTRIBUTION)
754                     && virtualDeviceId == Context.DEVICE_ID_DEFAULT
755                     && flags == OP_FLAG_SELF && result == MODE_ALLOWED) {
756                     notedQueue.put(opNotedCount++)
757                 }
758             }
759         }
760 
761         try {
762             mAppOps.startWatchingNoted(arrayOf(OPSTR_RESERVED_FOR_TESTING), notedWatcher)
763 
764             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
765                 mMyUid, mOpPackageName,
766                 TEST_ATTRIBUTION,
767                 /* message = */ null)
768 
769             assertEquals("onOpNoted callback count unexpected",
770                 notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
771                 0)
772 
773             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
774                 mMyUid,
775                 mOpPackageName,
776                 TEST_ATTRIBUTION,
777                 /* message = */ null)
778 
779             assertEquals("onOpNoted callback count unexpected",
780                 notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
781                 1)
782 
783             mAppOps.stopWatchingNoted(notedWatcher)
784 
785             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
786                 mMyUid,
787                 mOpPackageName,
788                 TEST_ATTRIBUTION,
789                 /* message = */ null)
790 
791             val exception = try {
792                 assertNotNull(notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
793                 null
794             } catch (e: AssertionError) {
795                 e
796             }
797             assertNotNull("Unexpected onOpNoted callback received", exception)
798         } finally {
799             mAppOps.stopWatchingNoted(notedWatcher)
800         }
801     }
802 
803     @Test
804     @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
startWatchingNoted_withExecutor_whenOpNoted_receivesDeviceAttributedCallbacknull805     fun startWatchingNoted_withExecutor_whenOpNoted_receivesDeviceAttributedCallback() {
806         val notedQueue = LinkedBlockingQueue<Int>()
807         val notedWatcher = object: OnOpNotedListener{
808             var opNotedCount = 0
809             override fun onOpNoted(op: String,
810                 uid: Int,
811                 packageName: String,
812                 attributionTag: String?,
813                 flags: Int,
814                 result: Int) {}
815 
816             override fun onOpNoted(op: String,
817                 uid: Int,
818                 packageName: String,
819                 attributionTag: String?,
820                 virtualDeviceId: Int,
821                 flags: Int,
822                 result: Int) {
823                 if (Objects.equal(op, OPSTR_RESERVED_FOR_TESTING)
824                     && uid == mMyUid && Objects.equal(packageName, mOpPackageName)
825                     && attributionTag == null
826                     && virtualDeviceId == Context.DEVICE_ID_DEFAULT
827                     && flags == OP_FLAG_SELF && result == MODE_ALLOWED) {
828                     notedQueue.put(opNotedCount++)
829                 }
830             }
831         }
832         try {
833             mAppOps.startWatchingNoted(arrayOf(OPSTR_RESERVED_FOR_TESTING), { it.run() }, notedWatcher)
834 
835             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
836                 mMyUid, mOpPackageName,
837                 /* attributionTag = */ null,
838                 /* message = */ null)
839 
840             assertEquals("onOpNoted callback count unexpected",
841                 notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
842                 0)
843 
844             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
845                 mMyUid,
846                 mOpPackageName,
847                 /* attributionTag = */ null,
848                 /* message = */ null)
849 
850             assertEquals("onOpNoted callback count unexpected",
851                 notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
852                 1)
853 
854             mAppOps.stopWatchingNoted(notedWatcher)
855 
856             mAppOps.noteOp(OPSTR_RESERVED_FOR_TESTING,
857                 mMyUid,
858                 mOpPackageName,
859                 /* attributionTag = */ null,
860                 /* message = */ null)
861 
862             val exception = try {
863                 assertNotNull(notedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
864                 null
865             } catch (e: AssertionError) {
866                 e
867             }
868             assertNotNull("Unexpected onOpNoted callback received", exception)
869         } finally {
870             mAppOps.stopWatchingNoted(notedWatcher)
871         }
872     }
873 
874     @Test
testAllOpsHaveOpStringnull875     fun testAllOpsHaveOpString() {
876         val opStrs = HashSet<String>()
877         for (opStr in AppOpsManager.getOpStrs()) {
878             assertNotNull("Each app op must have an operation string defined", opStr)
879             opStrs.add(opStr)
880         }
881         assertEquals("Not all op strings are unique", AppOpsManager.getNumOps(), opStrs.size)
882     }
883 
884     @Test
testOpCodesUniquenull885     fun testOpCodesUnique() {
886         val opStrs = AppOpsManager.getOpStrs()
887         val opCodes = HashSet<Int>()
888         for (opStr in opStrs) {
889             opCodes.add(AppOpsManager.strOpToOp(opStr))
890         }
891         assertEquals("Not all app op codes are unique", opStrs.size, opCodes.size)
892     }
893 
894     @Test
testPermissionMappingnull895     fun testPermissionMapping() {
896         for (entry in permissionToOpStr) {
897             testPermissionMapping(entry.key, entry.value)
898         }
899     }
900 
testPermissionMappingnull901     private fun testPermissionMapping(permission: String, opStr: String) {
902         // Do the permission => op lookups.
903         val mappedOpStr = AppOpsManager.permissionToOp(permission)!!
904         assertEquals(opStr, mappedOpStr)
905         val opCode = AppOpsManager.strOpToOp(opStr)
906         val mappedOpCode = AppOpsManager.permissionToOpCode(permission)
907         assertEquals(opCode, mappedOpCode)
908 
909         // Do the op => permission lookups.
910         val strMappedPermission = AppOpsManager.opToPermission(opStr)
911         assertEquals(permission, strMappedPermission)
912         val codeMappedPermission = AppOpsManager.opToPermission(opCode)
913         assertEquals(permission, codeMappedPermission)
914     }
915 
916     /**
917      * Test that the app can not change the app op mode for itself.
918      */
919     @Test
testCantSetModeForSelfnull920     fun testCantSetModeForSelf() {
921         try {
922             val writeSmsOp = AppOpsManager.permissionToOpCode("android.permission.WRITE_SMS")
923             mAppOps.setMode(writeSmsOp, Process.myUid(), mOpPackageName, AppOpsManager.MODE_ALLOWED)
924             fail("Was able to set mode for self")
925         } catch (expected: SecurityException) {
926         }
927     }
928 
929     @Test
testGetOpsForPackageOpsAreLoggednull930     fun testGetOpsForPackageOpsAreLogged() {
931         // This test checks if operations get logged by the system. It needs to start with a clean
932         // slate, i.e. these ops can't have been logged previously for this test package. The reason
933         // is that there's no API for clearing the app op logs before a test run. However, the op
934         // logs are cleared when this test package is reinstalled between test runs. To make sure
935         // that other test methods in this class don't affect this test method, here we use
936         // operations that are not used by any other test cases.
937         val mustNotBeLogged = "Operation mustn't be logged before the test runs"
938         assumeTrue(mustNotBeLogged, !allowedOperationLogged(mOpPackageName, OPSTR_VIBRATE))
939         assumeTrue(mustNotBeLogged,
940             !allowedOperationLogged(mOpPackageName, OPSTR_RESERVED_FOR_TESTING))
941 
942         setOpMode(mOpPackageName, OPSTR_VIBRATE, MODE_ALLOWED)
943         setOpMode(mOpPackageName, OPSTR_RESERVED_FOR_TESTING, MODE_ERRORED)
944 
945         // Note an op that's allowed.
946         mAppOps.noteOp(OPSTR_VIBRATE, Process.myUid(), mOpPackageName)
947         val mustBeLogged = "Operation must be logged"
948         assertTrue(mustBeLogged, allowedOperationLogged(mOpPackageName, OPSTR_VIBRATE))
949 
950         // Note another op that's not allowed.
951         mAppOps.noteOpNoThrow(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), mOpPackageName)
952         assertTrue(mustBeLogged, allowedOperationLogged(mOpPackageName, OPSTR_VIBRATE))
953         assertTrue(mustBeLogged,
954             rejectedOperationLogged(mOpPackageName, OPSTR_RESERVED_FOR_TESTING))
955     }
956 
957     @Test
testNonHistoricalStatePersistencenull958     fun testNonHistoricalStatePersistence() {
959         // Put a package and uid level data
960         runWithShellPermissionIdentity {
961             mAppOps.setMode(OPSTR_PICTURE_IN_PICTURE, Process.myUid(),
962                     mOpPackageName, MODE_IGNORED)
963             mAppOps.setUidMode(OPSTR_PICTURE_IN_PICTURE, Process.myUid(), MODE_ERRORED)
964 
965             // Write the data to disk and read it
966             mAppOps.reloadNonHistoricalState()
967         }
968 
969         // Verify the uid state is preserved
970         assertSame(mAppOps.unsafeCheckOpNoThrow(OPSTR_PICTURE_IN_PICTURE,
971                 Process.myUid(), mOpPackageName), MODE_ERRORED)
972 
973         runWithShellPermissionIdentity {
974             // Clear the uid state
975             mAppOps.setUidMode(OPSTR_PICTURE_IN_PICTURE, Process.myUid(),
976                     AppOpsManager.opToDefaultMode(OPSTR_PICTURE_IN_PICTURE))
977         }
978 
979         // Verify the package state is preserved
980         assertSame(mAppOps.unsafeCheckOpNoThrow(OPSTR_PICTURE_IN_PICTURE,
981                 Process.myUid(), mOpPackageName), MODE_IGNORED)
982 
983         runWithShellPermissionIdentity {
984             // Clear the uid state
985             val defaultMode = AppOpsManager.opToDefaultMode(OPSTR_PICTURE_IN_PICTURE)
986             mAppOps.setUidMode(OPSTR_PICTURE_IN_PICTURE, Process.myUid(), defaultMode)
987             mAppOps.setMode(OPSTR_PICTURE_IN_PICTURE, Process.myUid(),
988                     mOpPackageName, defaultMode)
989         }
990     }
991 
992     @Test
noteOpForBadUidnull993     fun noteOpForBadUid() {
994         runWithShellPermissionIdentity {
995             val mode = mAppOps.noteOpNoThrow(OPSTR_RESERVED_FOR_TESTING, Process.myUid() + 1,
996                     mOpPackageName)
997             assertEquals(mode, MODE_ERRORED)
998         }
999     }
1000 
1001     @Test
startOpForBadUidnull1002     fun startOpForBadUid() {
1003         runWithShellPermissionIdentity {
1004             val mode = mAppOps.startOpNoThrow(OPSTR_RESERVED_FOR_TESTING, Process.myUid() + 1,
1005                     mOpPackageName)
1006             assertEquals(mode, MODE_ERRORED)
1007         }
1008     }
1009 
1010     @Test
checkOpForBadUidnull1011     fun checkOpForBadUid() {
1012         val defaultMode = AppOpsManager.opToDefaultMode(OPSTR_RESERVED_FOR_TESTING)
1013 
1014         runWithShellPermissionIdentity {
1015             mAppOps.setUidMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), MODE_ERRORED)
1016             try {
1017                 val mode = mAppOps.unsafeCheckOpNoThrow(OPSTR_RESERVED_FOR_TESTING,
1018                     Process.myUid() + 1, mOpPackageName)
1019 
1020                 // For invalid uids checkOp return the default mode
1021                 assertEquals(mode, defaultMode)
1022             } finally {
1023                 // Clear the uid state
1024                 mAppOps.setUidMode(OPSTR_RESERVED_FOR_TESTING, Process.myUid(), defaultMode)
1025             }
1026         }
1027     }
1028 
1029     @Test
ensurePhoneCallOpsRestrictednull1030     fun ensurePhoneCallOpsRestricted() {
1031         val pm = mContext.packageManager
1032         assumeTrue((pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) ||
1033                 pm.hasSystemFeature(PackageManager.FEATURE_TELECOM)) &&
1034                 pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE))
1035         val micReturn = mAppOps.noteOp(OPSTR_PHONE_CALL_MICROPHONE, Process.myUid(), mOpPackageName,
1036                 null, null)
1037         assertEquals(MODE_IGNORED, micReturn)
1038         val cameraReturn = mAppOps.noteOp(OPSTR_PHONE_CALL_CAMERA, Process.myUid(),
1039                 mOpPackageName, null, null)
1040         assertEquals(MODE_IGNORED, cameraReturn)
1041     }
1042 
1043     @Test
1044     @FlakyTest
testRestrictedSettingsOpsReadnull1045     fun testRestrictedSettingsOpsRead() {
1046         val changedQueue = LinkedBlockingQueue<Int>()
1047         val onOpChangeWatcher = object: OnOpChangedListener{
1048             var opChangedCount = 0
1049             override fun onOpChanged(op: String?, packageName: String?) {
1050                 if (Objects.equal(op, OPSTR_ACCESS_RESTRICTED_SETTINGS)
1051                     && Objects.equal(packageName, mOpPackageName)) {
1052                     changedQueue.put(opChangedCount++)
1053                 }
1054             }
1055         }
1056 
1057         // Apps without manage appops permission will get security exception if it tries to access
1058         // restricted settings ops.
1059         runWithShellPermissionIdentity {
1060             setOpMode(mOpPackageName, OPSTR_ACCESS_RESTRICTED_SETTINGS, MODE_ERRORED)
1061         }
1062         Assert.assertThrows(SecurityException::class.java) {
1063             mAppOps.unsafeCheckOpRawNoThrow(OPSTR_ACCESS_RESTRICTED_SETTINGS, Process.myUid(),
1064                     mOpPackageName)
1065         }
1066 
1067         // Test for b/336323279
1068         assertNull(
1069             mAppOps.getOpsForPackage(
1070                 Process.myUid(),
1071                 mOpPackageName,
1072                 intArrayOf(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS)
1073             )
1074         )
1075 
1076         // Apps with manage appops permission (shell) should be able to read restricted settings op
1077         // successfully.
1078         runWithShellPermissionIdentity {
1079             mAppOps.unsafeCheckOpRawNoThrow(OPSTR_ACCESS_RESTRICTED_SETTINGS, Process.myUid(),
1080                     mOpPackageName)
1081 
1082             assertNotNull(
1083                 mAppOps.getOpsForPackage(
1084                     Process.myUid(),
1085                     mOpPackageName,
1086                     intArrayOf(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS)
1087                 )
1088             )
1089         }
1090 
1091         // Normal apps should not receive op change callback when op is changed.
1092         try {
1093             setOpMode(mOpPackageName, OPSTR_ACCESS_RESTRICTED_SETTINGS, MODE_ERRORED)
1094 
1095             mAppOps.startWatchingMode(OPSTR_ACCESS_RESTRICTED_SETTINGS, mOpPackageName,
1096                     onOpChangeWatcher)
1097 
1098             val exception = try {
1099                 assertNotNull("Unexpected onOpChanged callback received",
1100                     changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS))
1101                 null
1102             } catch (e: AssertionError) {
1103                 e
1104             }
1105             assertNotNull(exception)
1106         } finally {
1107             // Clean up registered watcher.
1108             mAppOps.stopWatchingMode(onOpChangeWatcher)
1109         }
1110 
1111         // Apps with manage ops permission (shell) should be able to receive op change callback.
1112         runWithShellPermissionIdentity {
1113             try {
1114                 setOpMode(mOpPackageName, OPSTR_ACCESS_RESTRICTED_SETTINGS, MODE_ERRORED)
1115 
1116                 mAppOps.startWatchingMode(OPSTR_ACCESS_RESTRICTED_SETTINGS, mOpPackageName,
1117                         onOpChangeWatcher)
1118 
1119                 setOpMode(mOpPackageName, OPSTR_ACCESS_RESTRICTED_SETTINGS, MODE_ALLOWED)
1120 
1121                 assertEquals("onOpChanged callback count unexpected",
1122                     changedQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS),
1123                     0)
1124             } finally {
1125                 // Clean up registered watcher.
1126                 mAppOps.stopWatchingMode(onOpChangeWatcher)
1127             }
1128         }
1129     }
1130 
runWithShellPermissionIdentitynull1131     private fun runWithShellPermissionIdentity(command: () -> Unit) {
1132         val uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation()
1133         uiAutomation.adoptShellPermissionIdentity()
1134         try {
1135             command.invoke()
1136         } finally {
1137             uiAutomation.dropShellPermissionIdentity()
1138         }
1139     }
1140 }
1141