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