1 /* <lambda>null2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.attributionsource.cts 17 18 import android.Manifest 19 import android.app.AppOpsManager 20 import android.app.Instrumentation 21 import android.content.AttributionSource 22 import android.content.ComponentName 23 import android.content.ContentValues 24 import android.content.Context 25 import android.content.ContextParams 26 import android.content.Intent 27 import android.content.pm.PackageManager.FEATURE_LEANBACK 28 import android.content.pm.PackageManager.FEATURE_TELEPHONY 29 import android.net.Uri 30 import android.os.Bundle 31 import android.os.Process 32 import android.os.RemoteCallback 33 import android.os.SystemClock 34 import android.os.UserHandle 35 import android.permission.PermissionManager 36 import android.permission.flags.Flags 37 import android.platform.test.annotations.AppModeFull 38 import android.platform.test.annotations.RequiresFlagsEnabled 39 import android.platform.test.flag.junit.DeviceFlagsValueProvider 40 import android.provider.CalendarContract 41 import android.provider.CallLog 42 import android.provider.ContactsContract 43 import android.provider.Telephony 44 import android.speech.RecognitionListener 45 import android.speech.SpeechRecognizer 46 import androidx.test.platform.app.InstrumentationRegistry 47 import com.android.compatibility.common.util.SystemUtil 48 import com.google.common.truth.Truth.assertWithMessage 49 import java.util.concurrent.CountDownLatch 50 import java.util.concurrent.TimeUnit 51 import java.util.concurrent.atomic.AtomicReference 52 import java.util.concurrent.locks.ReentrantLock 53 import java.util.function.Consumer 54 import org.junit.After 55 import org.junit.Assume.assumeFalse 56 import org.junit.Assume.assumeTrue 57 import org.junit.Before 58 import org.junit.Rule 59 import org.junit.Test 60 import org.mockito.ArgumentMatcher 61 import org.mockito.Mockito.eq 62 import org.mockito.Mockito.inOrder 63 import org.mockito.Mockito.intThat 64 import org.mockito.Mockito.isNull 65 import org.mockito.Mockito.mock 66 67 @AppModeFull(reason = "Instant apps cannot hold READ_CONTACTS/READ_CALENDAR/READ_SMS/READ_CALL_LOG") 68 class RuntimePermissionsAppOpTrackingTest { 69 70 @get:Rule val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() 71 72 @Before 73 fun setUpTest() { 74 val appOpsManager = context.getSystemService(AppOpsManager::class.java)!! 75 SystemUtil.runWithShellPermissionIdentity { 76 appOpsManager.clearHistory() 77 appOpsManager.setHistoryParameters( 78 AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE, 79 SNAPSHOT_INTERVAL_MILLIS, 80 INTERVAL_COMPRESSION_MULTIPLIER) 81 82 appOpsManager.resetPackageOpsNoHistory(context.packageName) 83 appOpsManager.resetPackageOpsNoHistory(SHELL_PACKAGE_NAME) 84 appOpsManager.resetPackageOpsNoHistory(RECEIVER_PACKAGE_NAME) 85 appOpsManager.resetPackageOpsNoHistory(RECEIVER2_PACKAGE_NAME) 86 } 87 } 88 89 @After 90 fun tearDownTest() { 91 val appOpsManager = context.getSystemService(AppOpsManager::class.java)!! 92 SystemUtil.runWithShellPermissionIdentity { 93 appOpsManager.clearHistory() 94 appOpsManager.resetHistoryParameters() 95 } 96 } 97 98 @Test 99 @Throws(Exception::class) 100 fun testSelfContactsAccess() { 101 testSelfAccess(ContactsContract.Contacts.CONTENT_URI, 102 Manifest.permission.READ_CONTACTS) 103 } 104 105 @Test 106 @Throws(Exception::class) 107 fun testSelfCalendarAccess() { 108 testSelfAccess(CalendarContract.Calendars.CONTENT_URI, 109 Manifest.permission.READ_CALENDAR) 110 } 111 112 @Test 113 @Throws(Exception::class) 114 fun testSelfSmsAccess() { 115 assumeNotTv() 116 assumeHasTelephony() 117 testSelfAccess(Telephony.Sms.CONTENT_URI, 118 Manifest.permission.READ_SMS) 119 } 120 121 @Test 122 @Throws(Exception::class) 123 fun testSelfCallLogAccess() { 124 testSelfAccess(CallLog.Calls.CONTENT_URI, 125 Manifest.permission.READ_CALL_LOG) 126 } 127 128 @Throws(Exception::class) 129 private fun testSelfAccess(uri: Uri, permission: String) { 130 val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG, null, null) 131 val beginEndMillis = System.currentTimeMillis() 132 context.contentResolver.query(uri, null, null, null)!!.close() 133 val endTimeMillis = System.currentTimeMillis() 134 135 assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!, 136 beginEndMillis, endTimeMillis, context.attributionSource, 137 /*accessorForeground*/ true, /*receiverForeground*/ false, 138 /*accessorTrusted*/ true, /*accessorAccessCount*/ 1, 139 /*receiverAccessCount*/ 0, /*checkAccessor*/ true, 140 /*fromDatasource*/ false) 141 } 142 143 @Test 144 @Throws(Exception::class) 145 fun testSelfCalendarWrite() { 146 testSelfWrite(CalendarContract.Calendars.CONTENT_URI, 147 Manifest.permission.WRITE_CALENDAR) 148 } 149 150 @Test 151 @Throws(Exception::class) 152 fun testSelfCallLogWrite() { 153 testSelfWrite(CallLog.Calls.CONTENT_URI, 154 Manifest.permission.WRITE_CALL_LOG) 155 } 156 157 @Throws(Exception::class) 158 private fun testSelfWrite(uri: Uri, permission: String) { 159 val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG, null, null) 160 val beginEndMillis = System.currentTimeMillis() 161 context.contentResolver.insert(uri, ContentValues()) 162 val endTimeMillis = System.currentTimeMillis() 163 164 assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!, 165 beginEndMillis, endTimeMillis, context.attributionSource, 166 /*accessorForeground*/ true, /*receiverForeground*/ false, 167 /*accessorTrusted*/ true, /*accessorAccessCount*/ 1, 168 /*receiverAccessCount*/ 0, /*checkAccessor*/ true, 169 /*fromDatasource*/ false) 170 } 171 172 @Test 173 @Throws(Exception::class) 174 fun testUntrustedContactsAccessAttributeToAnother() { 175 testUntrustedAccessAttributeToAnother(ContactsContract.Contacts.CONTENT_URI, 176 Manifest.permission.READ_CONTACTS) 177 } 178 179 @Test 180 @Throws(Exception::class) 181 fun testUntrustedCalendarAccessAttributeToAnother() { 182 testUntrustedAccessAttributeToAnother(CalendarContract.Calendars.CONTENT_URI, 183 Manifest.permission.READ_CALENDAR) 184 } 185 186 @Test 187 @Throws(Exception::class) 188 fun testUntrustedSmsAccessAttributeToAnother() { 189 assumeNotTv() 190 assumeHasTelephony() 191 testUntrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI, 192 Manifest.permission.READ_SMS) 193 } 194 195 @Test 196 @Throws(Exception::class) 197 fun testUntrustedCallLogAccessAttributeToAnother() { 198 testUntrustedAccessAttributeToAnother(CallLog.Calls.CONTENT_URI, 199 Manifest.permission.READ_CALL_LOG) 200 } 201 202 @Throws(Exception::class) 203 private fun testUntrustedAccessAttributeToAnother(uri: Uri, permission: String) { 204 val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG, 205 RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG) 206 val beginEndMillis = System.currentTimeMillis() 207 context.contentResolver.query(uri, null, null, null)!!.close() 208 val endTimeMillis = System.currentTimeMillis() 209 210 assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!, 211 beginEndMillis, endTimeMillis, context.attributionSource, 212 /*accessorForeground*/ true, /*receiverForeground*/ false, 213 /*accessorTrusted*/ false, /*accessorAccessCount*/ 1, 214 /*receiverAccessCount*/ 1, /*checkAccessor*/ false, 215 /*fromDatasource*/ false) 216 } 217 218 @Test 219 @Throws(Exception::class) 220 fun testUntrustedContactsAccessAttributeToAnotherThroughIntermediary() { 221 testUntrustedAccessAttributeToAnotherThroughIntermediary( 222 ContactsContract.Contacts.CONTENT_URI, 223 Manifest.permission.READ_CONTACTS) 224 } 225 226 @Test 227 @Throws(Exception::class) 228 fun testUntrustedCalendarAccessAttributeToAnotherThroughIntermediary() { 229 testUntrustedAccessAttributeToAnotherThroughIntermediary( 230 CalendarContract.Calendars.CONTENT_URI, 231 Manifest.permission.READ_CALENDAR) 232 } 233 234 @Test 235 @Throws(Exception::class) 236 fun testUntrustedSmsAccessAttributeToAnotherThroughIntermediary() { 237 assumeNotTv() 238 assumeHasTelephony() 239 testUntrustedAccessAttributeToAnotherThroughIntermediary( 240 Telephony.Sms.CONTENT_URI, 241 Manifest.permission.READ_SMS) 242 } 243 244 @Test 245 @Throws(Exception::class) 246 fun testUntrustedCallLogAccessAttributeToAnotherThroughIntermediary() { 247 testUntrustedAccessAttributeToAnotherThroughIntermediary( 248 CallLog.Calls.CONTENT_URI, 249 Manifest.permission.READ_CALL_LOG) 250 } 251 252 @Throws(Exception::class) 253 private fun testUntrustedAccessAttributeToAnotherThroughIntermediary( 254 uri: Uri, 255 permission: String 256 ) { 257 runWithAuxiliaryApps { 258 val nextAttributionSource = startBlamedAppActivity() 259 260 val intermediaryContext = context.createContext(ContextParams.Builder() 261 .setNextAttributionSource(nextAttributionSource) 262 .setAttributionTag(ACCESSOR_ATTRIBUTION_TAG) 263 .build()) 264 265 val beginEndMillis = System.currentTimeMillis() 266 intermediaryContext.contentResolver.query(uri, null, null, null)!!.close() 267 val endTimeMillis = System.currentTimeMillis() 268 269 // Assert first stage access 270 assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!, 271 beginEndMillis, endTimeMillis, intermediaryContext.attributionSource, 272 /*accessorForeground*/ true, /*receiverForeground*/ true, 273 /*accessorTrusted*/ false, /*accessorAccessCount*/ 1, 274 /*receiverAccessCount*/ 1, /*checkAccessor*/ false, 275 /*fromDatasource*/ false) 276 277 // Assert second stage access 278 assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!, 279 beginEndMillis, endTimeMillis, nextAttributionSource, 280 /*accessorForeground*/ true, /*receiverForeground*/ false, 281 /*accessorTrusted*/ false, /*accessorAccessCount*/ 1, 282 /*receiverAccessCount*/ 1, /*checkAccessor*/ false, 283 /*fromDatasource*/ false) 284 } 285 } 286 287 @Test(expected = SecurityException::class) 288 fun testCannotForgeAttributionSource() { 289 val receiverSource = AttributionSource(context 290 .packageManager.getPackageUid(RECEIVER2_PACKAGE_NAME, 0), 291 RECEIVER2_PACKAGE_NAME, RECEIVER2_ATTRIBUTION_TAG, null, AttributionSource( 292 context.packageManager.getPackageUid(RECEIVER_PACKAGE_NAME, 0), 293 RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG)) 294 val intermediaryContext = context.createContext(ContextParams.Builder() 295 .setNextAttributionSource(receiverSource) 296 .setAttributionTag(ACCESSOR_ATTRIBUTION_TAG) 297 .build()) 298 intermediaryContext.contentResolver.query(CallLog.Calls.CONTENT_URI, null, 299 null, null)!!.close() 300 } 301 302 @Test(expected = SecurityException::class) 303 fun testCannotAppendToForgeAttributionSource() { 304 runWithAuxiliaryApps { 305 val nextAttributionSource = startBlamedAppActivity() 306 val untrustedAttributionSource = AttributionSource(context 307 .packageManager.getPackageUid(RECEIVER2_PACKAGE_NAME, 0), 308 RECEIVER2_PACKAGE_NAME, RECEIVER2_ATTRIBUTION_TAG, null, 309 nextAttributionSource) 310 val intermediaryContext = context.createContext(ContextParams.Builder() 311 .setNextAttributionSource(untrustedAttributionSource) 312 .setAttributionTag(ACCESSOR_ATTRIBUTION_TAG) 313 .build()) 314 intermediaryContext.contentResolver.query(CallLog.Calls.CONTENT_URI, null, 315 null, null)!!.close() 316 } 317 } 318 319 @Test 320 @Throws(Exception::class) 321 fun testTrustedAccessContactsAttributeToAnother() { 322 testTrustedAccessAttributeToAnother(ContactsContract.Contacts.CONTENT_URI, 323 Manifest.permission.READ_CONTACTS) 324 } 325 326 @Test 327 @Throws(Exception::class) 328 fun testTrustedAccessCalendarAttributeToAnother() { 329 testTrustedAccessAttributeToAnother(CalendarContract.Calendars.CONTENT_URI, 330 Manifest.permission.READ_CALENDAR) 331 } 332 333 @Test 334 @Throws(Exception::class) 335 fun testTrustedAccessSmsAttributeToAnother() { 336 assumeNotTv() 337 assumeHasTelephony() 338 testTrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI, 339 Manifest.permission.READ_SMS) 340 } 341 342 @Test 343 @Throws(Exception::class) 344 fun testTrustedAccessCallLogAttributeToAnother() { 345 testTrustedAccessAttributeToAnother(CallLog.Calls.CONTENT_URI, 346 Manifest.permission.READ_CALL_LOG) 347 } 348 349 @Throws(Exception::class) 350 private fun testTrustedAccessAttributeToAnother(uri: Uri, permission: String) { 351 val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG, 352 RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG) 353 val beginEndMillis = System.currentTimeMillis() 354 SystemUtil.runWithShellPermissionIdentity { 355 context.contentResolver.query(uri, null, null, null)!!.close() 356 } 357 val endTimeMillis = System.currentTimeMillis() 358 359 // Calculate the shellUid to account for running this from a secondary user. 360 val shellUid = UserHandle.getUid(Process.myUserHandle().identifier, 361 UserHandle.getAppId(Process.SHELL_UID)) 362 // Since we use adopt the shell permission identity we need to adjust 363 // the permission identity to have the shell as the accessor. 364 assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!, 365 beginEndMillis, endTimeMillis, AttributionSource(shellUid, 366 SHELL_PACKAGE_NAME, ACCESSOR_ATTRIBUTION_TAG, null, 367 context.attributionSource.next), 368 /*accessorForeground*/ false, /*receiverForeground*/ false, 369 /*accessorTrusted*/ true, /*accessorAccessCount*/ 1, 370 /*receiverAccessCount*/ 1, /*checkAccessor*/ false, 371 /*fromDatasource*/ false) 372 } 373 374 @Test 375 fun testGetAllPackagesForAllAppOps() { 376 val appOpsManager = Companion.context.getSystemService(AppOpsManager::class.java)!! 377 val result = SystemUtil.runWithShellPermissionIdentity<List<AppOpsManager.PackageOps>> { 378 appOpsManager.getPackagesForOps(null as Array<String>?) 379 } 380 assertWithMessage("Expected at least one package").that(result.size).isAtLeast(1) 381 } 382 383 @Test 384 @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 385 @Throws(Exception::class) 386 fun testMicRecognitionInjectRecoWithoutAttribution() { 387 runWithAuxiliaryApps { 388 startBlamedAppActivity() 389 390 val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG, 391 RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG) 392 393 val listener = mock(AppOpsManager.OnOpActiveChangedListener::class.java) 394 val appopsManager = context.getSystemService(AppOpsManager::class.java) 395 SystemUtil.runWithShellPermissionIdentity<Unit> { 396 appopsManager!!.startWatchingActive(arrayOf(AppOpsManager.OPSTR_RECORD_AUDIO), 397 context.mainExecutor, listener) 398 } 399 400 val speechStartTime = System.currentTimeMillis() 401 val recognizerRef = AtomicReference<SpeechRecognizer>() 402 var currentOperationComplete = CountDownLatch(1) 403 404 // Makes sure that all runnable for setting up temporary recognition service is done 405 // before moving on to start the recognizer. 406 instrumentation.runOnMainSync { 407 instrumentation.uiAutomation 408 .adoptShellPermissionIdentity("android.permission.MANAGE_SPEECH_RECOGNITION") 409 val recognizer = SpeechRecognizer.createOnDeviceTestingSpeechRecognizer(context) 410 recognizer.setTemporaryOnDeviceRecognizer(ComponentName(RECEIVER2_PACKAGE_NAME, RECOGNITION_SERVICE)) 411 recognizerRef.set(recognizer) 412 } 413 414 instrumentation.runOnMainSync { 415 val recognizer = recognizerRef.get() 416 417 recognizer.setRecognitionListener(object : RecognitionListener { 418 override fun onReadyForSpeech(params: Bundle?) {} 419 override fun onRmsChanged(rmsdB: Float) {} 420 override fun onBufferReceived(buffer: ByteArray?) { 421 currentOperationComplete.countDown() 422 } 423 override fun onPartialResults(partialResults: Bundle?) {} 424 override fun onEvent(eventType: Int, params: Bundle?) {} 425 override fun onError(error: Int) {} 426 override fun onResults(results: Bundle?) {} 427 override fun onBeginningOfSpeech() {} 428 override fun onEndOfSpeech() {} 429 }) 430 431 val recoIntent = Intent() 432 recoIntent.putExtra(OPERATION, OPERATION_INJECT_RECO_WITHOUT_ATTRIBUTION) 433 recognizer.startListening(recoIntent) 434 } 435 436 try { 437 currentOperationComplete.await(ASYNC_OPERATION_TIMEOUT_MILLIS, 438 TimeUnit.MILLISECONDS) 439 440 val op = AppOpsManager.permissionToOp(Manifest.permission.RECORD_AUDIO)!! 441 442 assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(), 443 AttributionSource(context.packageManager.getPackageUid( 444 RECEIVER2_PACKAGE_NAME, 0), RECEIVER2_PACKAGE_NAME, 445 /*attributionTag*/ null, null, context.attributionSource), 446 /*accessorForeground*/ true, /*receiverForeground*/ true, 447 /*accessorTrusted*/ false, /*accessorAccessCount*/ 1, 448 /*receiverAccessCount*/ 1, /*checkAccessor*/ true, 449 /*fromDatasource*/ false) 450 451 assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(), 452 context.attributionSource, /*accessorForeground*/ true, 453 /*receiverForeground*/ true, /*accessorTrusted*/ false, 454 /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1, 455 /*checkAccessor*/ false, /*fromDatasource*/ false) 456 457 // Finish recon and check if all ops are finished 458 currentOperationComplete = CountDownLatch(1) 459 instrumentation.runOnMainSync { recognizerRef.get().cancel() } 460 currentOperationComplete.await(ASYNC_OPERATION_TIMEOUT_MILLIS, 461 TimeUnit.MILLISECONDS) 462 463 val recognizerUid = context.packageManager.getPackageUid( 464 RECEIVER2_PACKAGE_NAME, 0) 465 466 assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(), 467 AttributionSource(recognizerUid, RECEIVER2_PACKAGE_NAME, 468 /*attributionTag*/ null, null, context.attributionSource), 469 /*accessorForeground*/ true, /*receiverForeground*/ true, 470 /*accessorTrusted*/ false, /*accessorAccessCount*/ 1, 471 /*receiverAccessCount*/ 1, /*checkAccessor*/ true, 472 /*fromDatasource*/ false) 473 474 assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(), 475 context.attributionSource, /*accessorForeground*/ true, 476 /*receiverForeground*/ true, /*accessorTrusted*/ false, 477 /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1, 478 /*checkAccessor*/ false, /*fromDatasource*/ false) 479 480 var attributionChainId: Int? = null 481 val inOrder = inOrder(listener) 482 val attributionChainIdMatcher = ArgumentMatcher<Int> { 483 if (attributionChainId == null) { 484 attributionChainId = it 485 return@ArgumentMatcher true 486 } else { 487 return@ArgumentMatcher (attributionChainId == it) 488 } 489 } 490 val receiverUid = context.packageManager.getPackageUid( 491 RECEIVER_PACKAGE_NAME, 0) 492 493 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 494 eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), 495 eq(Context.DEVICE_ID_DEFAULT), eq(true), 496 eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR), 497 intThat(attributionChainIdMatcher)) 498 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 499 eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG), 500 eq(Context.DEVICE_ID_DEFAULT), eq(true), 501 eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY), 502 intThat(attributionChainIdMatcher)) 503 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 504 eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG), 505 eq(Context.DEVICE_ID_DEFAULT), eq(true), 506 eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER), 507 intThat(attributionChainIdMatcher)) 508 509 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 510 eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), 511 eq(Context.DEVICE_ID_DEFAULT), eq(false), 512 eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR), 513 intThat(attributionChainIdMatcher)) 514 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 515 eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG), 516 eq(Context.DEVICE_ID_DEFAULT), eq(false), 517 eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY), 518 intThat(attributionChainIdMatcher)) 519 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 520 eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG), 521 eq(Context.DEVICE_ID_DEFAULT), eq(false), 522 eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER), 523 intThat(attributionChainIdMatcher)) 524 } finally { 525 // Take down the recognition service 526 instrumentation.runOnMainSync { 527 recognizerRef.get().setTemporaryOnDeviceRecognizer(null) 528 recognizerRef.get().destroy() 529 instrumentation.uiAutomation.dropShellPermissionIdentity() 530 } 531 } 532 } 533 } 534 535 @Test 536 @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 537 @Throws(Exception::class) 538 fun testMicRecognitionMicRecoWithAttribution() { 539 runWithAuxiliaryApps { 540 startBlamedAppActivity() 541 542 val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG, 543 RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG) 544 545 val listener = mock(AppOpsManager.OnOpActiveChangedListener::class.java) 546 val appopsManager = context.getSystemService(AppOpsManager::class.java) 547 SystemUtil.runWithShellPermissionIdentity<Unit> { 548 appopsManager!!.startWatchingActive(arrayOf(AppOpsManager.OPSTR_RECORD_AUDIO), 549 context.mainExecutor, listener) 550 } 551 552 val speechStartTime = System.currentTimeMillis() 553 val recognizerRef = AtomicReference<SpeechRecognizer>() 554 var currentOperationComplete = CountDownLatch(1) 555 556 // Makes sure that all runnable for setting up temporary recognition service is done 557 // before moving on to start the recognizer. 558 instrumentation.runOnMainSync { 559 instrumentation.uiAutomation 560 .adoptShellPermissionIdentity("android.permission.MANAGE_SPEECH_RECOGNITION") 561 val recognizer = SpeechRecognizer.createOnDeviceTestingSpeechRecognizer(context) 562 recognizer.setTemporaryOnDeviceRecognizer(ComponentName(RECEIVER2_PACKAGE_NAME, RECOGNITION_SERVICE)) 563 recognizerRef.set(recognizer) 564 } 565 566 instrumentation.runOnMainSync { 567 val recognizer = recognizerRef.get() 568 569 recognizer.setRecognitionListener(object : RecognitionListener { 570 override fun onReadyForSpeech(params: Bundle?) {} 571 override fun onRmsChanged(rmsdB: Float) {} 572 override fun onBufferReceived(buffer: ByteArray?) { 573 currentOperationComplete.countDown() 574 } 575 override fun onPartialResults(partialResults: Bundle?) {} 576 override fun onEvent(eventType: Int, params: Bundle?) {} 577 override fun onError(error: Int) {} 578 override fun onResults(results: Bundle?) {} 579 override fun onBeginningOfSpeech() {} 580 override fun onEndOfSpeech() {} 581 }) 582 583 val recoIntent = Intent() 584 recoIntent.putExtra(OPERATION, OPERATION_MIC_RECO_WITH_ATTRIBUTION) 585 recognizer.startListening(recoIntent) 586 } 587 588 try { 589 currentOperationComplete.await(ASYNC_OPERATION_TIMEOUT_MILLIS, 590 TimeUnit.MILLISECONDS) 591 592 val op = AppOpsManager.permissionToOp(Manifest.permission.RECORD_AUDIO)!! 593 594 assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(), 595 AttributionSource(context.packageManager.getPackageUid( 596 RECEIVER2_PACKAGE_NAME, 0), RECEIVER2_PACKAGE_NAME, 597 /*attributionTag*/ null, null, context.attributionSource), 598 /*accessorForeground*/ true, /*receiverForeground*/ true, 599 /*accessorTrusted*/ true, /*accessorAccessCount*/ 1, 600 /*receiverAccessCount*/ 1, /*checkAccessor*/ true, 601 /*fromDatasource*/ true) 602 603 assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(), 604 context.attributionSource, /*accessorForeground*/ true, 605 /*receiverForeground*/ true, /*accessorTrusted*/ true, 606 /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1, 607 /*checkAccessor*/ false, /*fromDatasource*/ true) 608 609 // Finish recon and check if all ops are finished 610 currentOperationComplete = CountDownLatch(1) 611 instrumentation.runOnMainSync { recognizerRef.get().cancel() } 612 currentOperationComplete.await(ASYNC_OPERATION_TIMEOUT_MILLIS, 613 TimeUnit.MILLISECONDS) 614 615 val recognizerUid = context.packageManager.getPackageUid( 616 RECEIVER2_PACKAGE_NAME, 0) 617 618 assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(), 619 AttributionSource(recognizerUid, RECEIVER2_PACKAGE_NAME, 620 /*attributionTag*/ null, null, context.attributionSource), 621 /*accessorForeground*/ true, /*receiverForeground*/ true, 622 /*accessorTrusted*/ true, /*accessorAccessCount*/ 1, 623 /*receiverAccessCount*/ 1, /*checkAccessor*/ true, 624 /*fromDatasource*/ true) 625 626 assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(), 627 context.attributionSource, /*accessorForeground*/ true, 628 /*receiverForeground*/ true, /*accessorTrusted*/ true, 629 /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1, 630 /*checkAccessor*/ false, /*fromDatasource*/ true) 631 632 var attributionChainId: Int? = null 633 val inOrder = inOrder(listener) 634 val attributionChainIdMatcher = ArgumentMatcher<Int> { 635 if (attributionChainId == null) { 636 attributionChainId = it 637 return@ArgumentMatcher true 638 } else { 639 return@ArgumentMatcher (attributionChainId == it) 640 } 641 } 642 val receiverUid = context.packageManager.getPackageUid( 643 RECEIVER_PACKAGE_NAME, 0) 644 645 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 646 eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), 647 eq(Context.DEVICE_ID_DEFAULT), eq(true), 648 eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR or ATTRIBUTION_FLAG_TRUSTED), 649 intThat(attributionChainIdMatcher)) 650 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 651 eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG), 652 eq(Context.DEVICE_ID_DEFAULT), eq(true), 653 eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY or 654 ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher)) 655 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 656 eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG), 657 eq(Context.DEVICE_ID_DEFAULT), eq(true), 658 eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER or 659 ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher)) 660 661 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 662 eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), 663 eq(Context.DEVICE_ID_DEFAULT), eq(false), 664 eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR or ATTRIBUTION_FLAG_TRUSTED), 665 intThat(attributionChainIdMatcher)) 666 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 667 eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG), 668 eq(Context.DEVICE_ID_DEFAULT), eq(false), 669 eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY or 670 ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher)) 671 inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO), 672 eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG), 673 eq(Context.DEVICE_ID_DEFAULT), eq(false), 674 eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER or 675 ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher)) 676 } finally { 677 // Take down the recognition service 678 instrumentation.runOnMainSync { 679 recognizerRef.get().setTemporaryOnDeviceRecognizer(null) 680 recognizerRef.get().destroy() 681 instrumentation.uiAutomation.dropShellPermissionIdentity() 682 } 683 } 684 } 685 } 686 687 fun runWithAuxiliaryApps(worker: () -> Unit) { 688 ensureAuxiliaryAppsNotRunningAndNoResidualProcessState() 689 try { 690 worker.invoke() 691 } finally { 692 ensureAuxiliaryAppsNotRunningAndNoResidualProcessState() 693 } 694 } 695 696 companion object { 697 private const val ASYNC_OPERATION_TIMEOUT_MILLIS: Long = 5000 // 5 sec 698 private const val INTERVAL_COMPRESSION_MULTIPLIER = 10 699 private const val SNAPSHOT_INTERVAL_MILLIS: Long = 1000 700 701 val SHELL_PACKAGE_NAME = "com.android.shell" 702 val RECEIVER_PACKAGE_NAME = "android.attributionsource.cts.blamed" 703 val BRING_TO_FOREGROUND_ACTIVITY = 704 "android.attributionsource.cts.blamed.BringToForegroundActivity" 705 val RECOGNITION_SERVICE = "android.attributionsource.cts.blamed2.MyRecognitionService" 706 val REMOTE_CALLBACK = "remote_callback" 707 val ATTRIBUTION_SOURCE = "attribution_source" 708 val ACCESSOR_ATTRIBUTION_TAG = "accessor_attribution_tag" 709 val RECEIVER2_PACKAGE_NAME = "android.attributionsource.cts.blamed2" 710 val RECEIVER_ATTRIBUTION_TAG = "receiver_attribution_tag" 711 val RECEIVER2_ATTRIBUTION_TAG = "receiver2_attribution_tag" 712 713 val OPERATION = "operation" 714 val OPERATION_MIC_RECO_WITH_ATTRIBUTION = "operation:mic_reco_with_attribution" 715 val OPERATION_INJECT_RECO_WITHOUT_ATTRIBUTION = "operation:inject_reco_without_attribution" 716 717 val ATTRIBUTION_FLAG_TRUSTED = 0x8 718 719 private val context: Context 720 get() = InstrumentationRegistry.getInstrumentation().getContext() 721 722 private val instrumentation: Instrumentation 723 get() = InstrumentationRegistry.getInstrumentation() 724 725 private val isTv = context.packageManager.hasSystemFeature(FEATURE_LEANBACK) 726 private val isTel = context.packageManager.hasSystemFeature(FEATURE_TELEPHONY) 727 728 fun ensureAuxiliaryAppsNotRunningAndNoResidualProcessState() { 729 SystemUtil.runShellCommand("am force-stop $RECEIVER_PACKAGE_NAME") 730 SystemUtil.runShellCommand("am force-stop $RECEIVER2_PACKAGE_NAME") 731 SystemClock.sleep(ASYNC_OPERATION_TIMEOUT_MILLIS) 732 } 733 734 @Throws(Exception::class) 735 private fun assertRunningOpAccess( 736 op: String, 737 beginEndMillis: Long, 738 endTimeMillis: Long, 739 attributionSource: AttributionSource, 740 accessorForeground: Boolean, 741 receiverForeground: Boolean, 742 accessorTrusted: Boolean, 743 accessorAccessCount: Int, 744 receiverAccessCount: Int, 745 checkAccessor: Boolean, 746 fromDatasource: Boolean 747 ) { 748 assertOpAccess(op, beginEndMillis, endTimeMillis, attributionSource, 749 accessorForeground, receiverForeground, accessorTrusted, 750 /*assertRunning*/ true, accessorAccessCount, receiverAccessCount, 751 checkAccessor, fromDatasource) 752 } 753 754 @Throws(Exception::class) 755 private fun assertNotRunningOpAccess( 756 op: String, 757 beginEndMillis: Long, 758 endTimeMillis: Long, 759 attributionSource: AttributionSource, 760 accessorForeground: Boolean, 761 receiverForeground: Boolean, 762 accessorTrusted: Boolean, 763 accessorAccessCount: Int, 764 receiverAccessCount: Int, 765 checkAccessor: Boolean, 766 fromDatasource: Boolean 767 ) { 768 assertOpAccess(op, beginEndMillis, endTimeMillis, attributionSource, 769 accessorForeground, receiverForeground, accessorTrusted, 770 /*assertRunning*/ false, accessorAccessCount, receiverAccessCount, 771 checkAccessor, fromDatasource) 772 } 773 774 @Throws(Exception::class) 775 private fun assertOpAccess( 776 op: String, 777 beginEndMillis: Long, 778 endTimeMillis: Long, 779 attributionSource: AttributionSource, 780 accessorForeground: Boolean, 781 receiverForeground: Boolean, 782 accessorTrusted: Boolean, 783 assertRunning: Boolean, 784 accessorAccessCount: Int, 785 receiverAccessCount: Int, 786 checkAccessor: Boolean, 787 fromDatasource: Boolean 788 ) { 789 assertLastOpAccess(op, beginEndMillis, endTimeMillis, attributionSource, 790 accessorForeground, receiverForeground, accessorTrusted, assertRunning, 791 checkAccessor, fromDatasource) 792 assertHistoricalOpAccess(op, attributionSource, accessorForeground, 793 receiverForeground, accessorTrusted, accessorAccessCount, receiverAccessCount, 794 checkAccessor, fromDatasource) 795 } 796 797 private fun assertLastOpAccess( 798 op: String, 799 beginEndMillis: Long, 800 endTimeMillis: Long, 801 attributionSource: AttributionSource, 802 accessorForeground: Boolean, 803 receiverForeground: Boolean, 804 accessorTrusted: Boolean, 805 assertRunning: Boolean, 806 checkAccessor: Boolean, 807 fromDatasource: Boolean 808 ) { 809 val appOpsManager = context.getSystemService(AppOpsManager::class.java)!! 810 val allPackagesOps: MutableList<AppOpsManager.PackageOps?> = ArrayList() 811 SystemUtil.runWithShellPermissionIdentity<Boolean> { 812 allPackagesOps.addAll(appOpsManager.getPackagesForOps(arrayOf(op))) 813 } 814 if (checkAccessor) { 815 assertLastAccessorOps(op, beginEndMillis, endTimeMillis, attributionSource, 816 accessorForeground, accessorTrusted, assertRunning, fromDatasource, 817 allPackagesOps) 818 } else { 819 assertNotLastAccessorOps(op, attributionSource, allPackagesOps) 820 } 821 if (attributionSource.next != null) { 822 assertLastReceiverOps(op, beginEndMillis, endTimeMillis, attributionSource, 823 receiverForeground, accessorTrusted, assertRunning, allPackagesOps) 824 } 825 } 826 827 @Throws(Exception::class) 828 private fun assertHistoricalOpAccess( 829 op: String, 830 attributionSource: AttributionSource, 831 accessorForeground: Boolean, 832 receiverForeground: Boolean, 833 accessorTrusted: Boolean, 834 accessorAccessCount: Int, 835 receiverAccessCount: Int, 836 checkAccessor: Boolean, 837 fromDatasource: Boolean 838 ) { 839 val appOpsManager = context.getSystemService(AppOpsManager::class.java)!! 840 val request = AppOpsManager.HistoricalOpsRequest.Builder(0, Long.MAX_VALUE) 841 .setOpNames(listOf(op)) 842 .build() 843 val historicalOpsRef = AtomicReference<AppOpsManager.HistoricalOps>() 844 val lock = ReentrantLock() 845 val condition = lock.newCondition() 846 SystemUtil.runWithShellPermissionIdentity { 847 appOpsManager.getHistoricalOps(request, context.mainExecutor, 848 Consumer { historicalOps: AppOpsManager.HistoricalOps -> 849 historicalOpsRef.set(historicalOps) 850 lock.lock() 851 try { 852 condition.signalAll() 853 } finally { 854 lock.unlock() 855 } 856 }) 857 } 858 lock.lock() 859 try { 860 condition.await(ASYNC_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) 861 } finally { 862 lock.unlock() 863 } 864 865 val historicalOps = historicalOpsRef.get() 866 if (checkAccessor) { 867 assertHistoricalAccessorOps(op, attributionSource, accessorForeground, 868 accessorTrusted, fromDatasource, accessorAccessCount, historicalOps) 869 } else { 870 assertNoHistoricalAccessorOps(op, attributionSource, historicalOps) 871 } 872 if (attributionSource.next != null) { 873 assertHistoricalReceiverOps(op, attributionSource, receiverForeground, 874 accessorTrusted, receiverAccessCount, historicalOps) 875 } 876 } 877 878 private fun assertLastAccessorOps( 879 op: String, 880 beginEndMillis: Long, 881 endTimeMillis: Long, 882 attributionSource: AttributionSource, 883 accessorForeground: Boolean, 884 accessorTrusted: Boolean, 885 assertRunning: Boolean, 886 fromDatasource: Boolean, 887 allPackagesOps: List<AppOpsManager.PackageOps?> 888 ) { 889 val accessorPackageOps = findPackageOps(attributionSource.uid, 890 attributionSource.packageName!!, allPackagesOps) 891 for (opEntry in accessorPackageOps!!.ops) { 892 if (!op.equals(opEntry.opStr)) { 893 continue 894 } 895 val attributedOpEntry = opEntry.attributedOpEntries[ 896 attributionSource.attributionTag] 897 if (attributionSource.next == null) { 898 // Access for ourselves 899 assertLastAccessInRange(attributedOpEntry!!, beginEndMillis, endTimeMillis, 900 AppOpsManager.OP_FLAG_SELF, accessorForeground, assertRunning) 901 } else if (accessorTrusted) { 902 // Access for others and we are trusted. If we got the data from a datasource 903 // the latter is the proxy and we proxied, otherwise we are the proxy. 904 if (fromDatasource) { 905 assertLastAccessInRange(attributedOpEntry!!, beginEndMillis, endTimeMillis, 906 AppOpsManager.OP_FLAG_TRUSTED_PROXIED, accessorForeground, 907 assertRunning) 908 } else { 909 assertLastAccessInRange(attributedOpEntry!!, beginEndMillis, endTimeMillis, 910 AppOpsManager.OP_FLAG_TRUSTED_PROXY, accessorForeground, 911 assertRunning) 912 } 913 } else { 914 // Access for others and we are not trusted. 915 assertLastAccessInRange(attributedOpEntry!!, beginEndMillis, endTimeMillis, 916 AppOpsManager.OP_FLAG_UNTRUSTED_PROXY, accessorForeground, 917 assertRunning) 918 } 919 } 920 } 921 922 private fun assertNotLastAccessorOps( 923 op: String, 924 attributionSource: AttributionSource, 925 allPackagesOps: List<AppOpsManager.PackageOps?> 926 ) { 927 val accessorPackageOps = findPackageOps(attributionSource.uid, 928 attributionSource.packageName!!, allPackagesOps) ?: return 929 for (opEntry in accessorPackageOps.ops) { 930 if (!op.equals(opEntry.opStr)) { 931 continue 932 } 933 val attributedOpEntry = opEntry.attributedOpEntries[ 934 attributionSource.attributionTag] 935 if (attributedOpEntry != null) { 936 assertWithMessage("Found background accessor op, did not expect to") 937 .that(attributedOpEntry.getLastAccessBackgroundTime( 938 AppOpsManager.OP_FLAG_SELF 939 or AppOpsManager.OP_FLAG_UNTRUSTED_PROXY 940 or AppOpsManager.OP_FLAG_TRUSTED_PROXY)).isEqualTo(-1) 941 assertWithMessage("Found foreground accessor op, did not expect to") 942 .that(attributedOpEntry.getLastAccessForegroundTime( 943 AppOpsManager.OP_FLAG_SELF 944 or AppOpsManager.OP_FLAG_UNTRUSTED_PROXY 945 or AppOpsManager.OP_FLAG_TRUSTED_PROXY)).isEqualTo(-1) 946 } 947 } 948 } 949 950 private fun assertHistoricalAccessorOps( 951 op: String, 952 attributionSource: AttributionSource, 953 accessorForeground: Boolean, 954 accessorTrusted: Boolean, 955 fromDatasource: Boolean, 956 assertedAccessCount: Int, 957 historicalOps: AppOpsManager.HistoricalOps 958 ) { 959 val accessorPackageOps = findPackageOps( 960 attributionSource.uid, attributionSource.packageName!!, 961 historicalOps) 962 val attributedPackageOps = accessorPackageOps?.getAttributedOps( 963 attributionSource.attributionTag) 964 965 val attributedPackageOp = attributedPackageOps!!.getOp(op) 966 if (attributionSource.next == null) { 967 // Access for ourselves 968 assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_SELF, 969 accessorForeground, assertedAccessCount) 970 } else if (accessorTrusted) { 971 // Access for others and we are trusted. If we got the data from a datasource it 972 // would blame the accessor in a trusted way 973 if (fromDatasource) { 974 assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_TRUSTED_PROXIED, 975 accessorForeground, assertedAccessCount) 976 } else { 977 assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_TRUSTED_PROXY, 978 accessorForeground, assertedAccessCount) 979 } 980 } else { 981 // Access for others and we are not trusted 982 assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_UNTRUSTED_PROXY, 983 accessorForeground, assertedAccessCount) 984 } 985 } 986 987 private fun assertNoHistoricalAccessorOps( 988 op: String, 989 attributionSource: AttributionSource, 990 historicalOps: AppOpsManager.HistoricalOps 991 ) { 992 val accessorPackageOps = findPackageOps( 993 attributionSource.uid, attributionSource.packageName!!, 994 historicalOps) 995 val attributedPackageOps = accessorPackageOps?.getAttributedOps( 996 attributionSource.attributionTag) ?: return 997 val attributedPackageOp = attributedPackageOps.getOp(op) 998 if (attributedPackageOp != null) { 999 assertWithMessage("Found background historical accessor access, did not expect to") 1000 .that(attributedPackageOp.getBackgroundAccessCount( 1001 AppOpsManager.OP_FLAG_SELF 1002 or AppOpsManager.OP_FLAG_UNTRUSTED_PROXY 1003 or AppOpsManager.OP_FLAG_TRUSTED_PROXY)).isEqualTo(0) 1004 assertWithMessage("Found foreground historical accessor access, did not expect to") 1005 .that(attributedPackageOp.getForegroundAccessCount( 1006 AppOpsManager.OP_FLAG_SELF 1007 or AppOpsManager.OP_FLAG_UNTRUSTED_PROXY 1008 or AppOpsManager.OP_FLAG_TRUSTED_PROXY)).isEqualTo(0) 1009 } 1010 } 1011 1012 private fun assertLastReceiverOps( 1013 op: String, 1014 beginTimeMillis: Long, 1015 endTimeMillis: Long, 1016 attributionSource: AttributionSource, 1017 receiverForeground: Boolean, 1018 accessorTrusted: Boolean, 1019 assertRunning: Boolean, 1020 allPackagesOps: List<AppOpsManager.PackageOps?> 1021 ) { 1022 val receiverPackageOps = findPackageOps( 1023 attributionSource.next!!.uid, 1024 attributionSource.next!!.packageName!!, 1025 allPackagesOps) 1026 for (opEntry in receiverPackageOps!!.ops) { 1027 if (op != opEntry.opStr) { 1028 continue 1029 } 1030 val attributedOpEntry = opEntry.attributedOpEntries[ 1031 attributionSource.next!!.attributionTag] 1032 val opProxyInfo: AppOpsManager.OpEventProxyInfo? 1033 opProxyInfo = if (accessorTrusted) { 1034 // Received from a trusted accessor. If we got the data from a datasource it 1035 // would blame the accessor in a trusted way 1036 assertLastAccessInRange(attributedOpEntry!!, beginTimeMillis, endTimeMillis, 1037 AppOpsManager.OP_FLAG_TRUSTED_PROXIED, receiverForeground, 1038 assertRunning) 1039 attributedOpEntry.getLastProxyInfo(AppOpsManager.OP_FLAG_TRUSTED_PROXIED) 1040 } else { 1041 // Received from an untrusted accessor 1042 assertLastAccessInRange(attributedOpEntry!!, beginTimeMillis, endTimeMillis, 1043 AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED, receiverForeground, 1044 assertRunning) 1045 attributedOpEntry.getLastProxyInfo( 1046 AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED) 1047 } 1048 assertWithMessage("proxy uid is not equal to expected") 1049 .that(opProxyInfo!!.uid).isEqualTo(attributionSource.uid) 1050 assertWithMessage("proxy package name is not equal to expected") 1051 .that(opProxyInfo.packageName).isEqualTo(attributionSource.packageName) 1052 1053 /* Fix made to b/304983146 treats the attribution coming from shell as invalid 1054 because it will not exist in shell package. Hence this change is to 1055 validate them as null instead of actual values 1056 */ 1057 if (attributionSource.packageName == SHELL_PACKAGE_NAME) { 1058 assertWithMessage("proxy attribution tag is expected to be null") 1059 .that(opProxyInfo.attributionTag).isNull() 1060 } else { 1061 assertWithMessage("proxy attribution tag is not equal to expected") 1062 .that(opProxyInfo.attributionTag) 1063 .isEqualTo(attributionSource.attributionTag) 1064 } 1065 } 1066 } 1067 1068 private fun assertHistoricalReceiverOps( 1069 op: String, 1070 attributionSource: AttributionSource, 1071 receiverForeground: Boolean, 1072 accessorTrusted: Boolean, 1073 assertedAccessCount: Int, 1074 historicalOps: AppOpsManager.HistoricalOps 1075 ) { 1076 val accessorPackageOps = findPackageOps( 1077 attributionSource.next!!.uid, 1078 attributionSource.next!!.packageName!!, 1079 historicalOps) 1080 val attributedPackageOps = accessorPackageOps?.getAttributedOps( 1081 attributionSource.next!!.attributionTag!!) 1082 val attributedPackageOp = attributedPackageOps!!.getOp(op) 1083 if (accessorTrusted) { 1084 // Received from a trusted accessor. 1085 assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_TRUSTED_PROXIED, 1086 receiverForeground, assertedAccessCount) 1087 } else { 1088 // Received from an untrusted accessor 1089 assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED, 1090 receiverForeground, assertedAccessCount) 1091 } 1092 } 1093 1094 private fun assertLastAccessInRange( 1095 opEntry: AppOpsManager.AttributedOpEntry, 1096 beginTimeMillis: Long, 1097 endTimeMillis: Long, 1098 assertedFlag: Int, 1099 assertForeground: Boolean, 1100 assertRunning: Boolean 1101 ) { 1102 assertWithMessage("Unexpected op running state") 1103 .that(opEntry.isRunning).isEqualTo(assertRunning) 1104 assertTimeInRangeIfRequired(opEntry, assertedFlag, 1105 AppOpsManager.OP_FLAG_SELF, 1106 assertForeground, beginTimeMillis, endTimeMillis) 1107 assertTimeInRangeIfRequired(opEntry, assertedFlag, 1108 AppOpsManager.OP_FLAG_TRUSTED_PROXY, 1109 assertForeground, beginTimeMillis, endTimeMillis) 1110 assertTimeInRangeIfRequired(opEntry, assertedFlag, 1111 AppOpsManager.OP_FLAG_UNTRUSTED_PROXY, 1112 assertForeground, beginTimeMillis, endTimeMillis) 1113 assertTimeInRangeIfRequired(opEntry, assertedFlag, 1114 AppOpsManager.OP_FLAG_TRUSTED_PROXIED, 1115 assertForeground, beginTimeMillis, endTimeMillis) 1116 assertTimeInRangeIfRequired(opEntry, assertedFlag, 1117 AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED, 1118 assertForeground, beginTimeMillis, endTimeMillis) 1119 if (assertForeground) { 1120 assertWithMessage("Did not expect to find a background access").that( 1121 opEntry.getLastAccessBackgroundTime(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(-1) 1122 } else { 1123 assertWithMessage("Did not expect to find a foreground access").that( 1124 opEntry.getLastAccessForegroundTime(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(-1) 1125 } 1126 } 1127 1128 private fun assertTimeInRangeIfRequired( 1129 opEntry: AppOpsManager.AttributedOpEntry, 1130 assertedFlag: Int, 1131 accessedFlag: Int, 1132 assertForeground: Boolean, 1133 beginTimeMillis: Long, 1134 endTimeMillis: Long 1135 ) { 1136 if (assertedFlag != accessedFlag) { 1137 return 1138 } 1139 val accessTime: Long 1140 accessTime = if (assertForeground) { 1141 opEntry.getLastAccessForegroundTime(accessedFlag) 1142 } else { 1143 opEntry.getLastAccessBackgroundTime(accessedFlag) 1144 } 1145 val typeString = if (assertForeground) "foreground" else "background" 1146 assertWithMessage("$typeString access time $accessTime is not after $beginTimeMillis") 1147 .that(accessTime).isAtLeast(beginTimeMillis) 1148 assertWithMessage("$typeString access time $accessTime is not at before $endTimeMillis") 1149 .that(accessTime).isAtMost(endTimeMillis) 1150 } 1151 1152 private fun assertAccessCount( 1153 historicalOp: AppOpsManager.HistoricalOp, 1154 assertedFlag: Int, 1155 assertForeground: Boolean, 1156 assertedAccessCount: Int 1157 ) { 1158 assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_SELF, 1159 assertedFlag, assertForeground, assertedAccessCount) 1160 assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_TRUSTED_PROXY, 1161 assertedFlag, assertForeground, assertedAccessCount) 1162 assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_UNTRUSTED_PROXY, 1163 assertedFlag, assertForeground, assertedAccessCount) 1164 assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_TRUSTED_PROXIED, 1165 assertedFlag, assertForeground, assertedAccessCount) 1166 assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED, 1167 assertedFlag, assertForeground, assertedAccessCount) 1168 if (assertForeground) { 1169 assertWithMessage("Did not expect to find a background access").that( 1170 historicalOp.getBackgroundAccessCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0) 1171 } else { 1172 assertWithMessage("Did not expect to find a foreground access").that( 1173 historicalOp.getForegroundAccessCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0) 1174 } 1175 } 1176 1177 private fun assertAccessCountIfRequired( 1178 historicalOp: AppOpsManager.HistoricalOp, 1179 assertedFlag: Int, 1180 accessedFlag: Int, 1181 assertForeground: Boolean, 1182 assertedAccessCount: Int 1183 ) { 1184 if (assertedFlag != accessedFlag) { 1185 return 1186 } 1187 val accessCount: Long 1188 accessCount = if (assertForeground) { 1189 historicalOp.getForegroundAccessCount(accessedFlag) 1190 } else { 1191 historicalOp.getBackgroundAccessCount(accessedFlag) 1192 } 1193 assertWithMessage("Found incorrect number of accesses") 1194 .that(accessCount).isEqualTo(assertedAccessCount) 1195 } 1196 1197 private fun findPackageOps( 1198 uid: Int, 1199 packageName: String, 1200 searchedList: List<AppOpsManager.PackageOps?> 1201 ): AppOpsManager.PackageOps? { 1202 return searchedList.stream() 1203 .filter { packageOps: AppOpsManager.PackageOps? -> 1204 packageOps!!.uid == uid && packageOps.packageName == packageName 1205 } 1206 .findAny() 1207 .orElse(null) 1208 } 1209 1210 private fun findPackageOps( 1211 uid: Int, 1212 packageName: String, 1213 historicalOps: AppOpsManager.HistoricalOps 1214 ): AppOpsManager.HistoricalPackageOps? { 1215 val uidOps = historicalOps.getUidOps(uid) 1216 return uidOps?.getPackageOps(packageName) 1217 } 1218 1219 fun createAttributionContext( 1220 attributionTag: String?, 1221 receiverPackageName: String?, 1222 receiverAttributionTag: String? 1223 ): Context { 1224 val attributionParamsBuilder = ContextParams.Builder() 1225 if (attributionTag != null) { 1226 attributionParamsBuilder.setAttributionTag(attributionTag) 1227 } 1228 if (receiverPackageName != null) { 1229 val attributionSourceBuilder = AttributionSource.Builder( 1230 context.packageManager.getPackageUid(receiverPackageName, 0)) 1231 attributionSourceBuilder.setPackageName(receiverPackageName) 1232 if (receiverAttributionTag != null) { 1233 attributionSourceBuilder.setAttributionTag(receiverAttributionTag) 1234 } 1235 var receiverAttributionSource = attributionSourceBuilder.build() 1236 SystemUtil.runWithShellPermissionIdentity { 1237 receiverAttributionSource = context.getSystemService( 1238 PermissionManager::class.java)!!.registerAttributionSource( 1239 receiverAttributionSource) 1240 } 1241 attributionParamsBuilder.setNextAttributionSource(receiverAttributionSource) 1242 } 1243 return context.createContext(attributionParamsBuilder.build()) 1244 } 1245 1246 fun startBlamedAppActivity(): AttributionSource { 1247 val activityStatedLatch = CountDownLatch(1) 1248 val attributionSourceRef = AtomicReference<AttributionSource>() 1249 val intent = Intent() 1250 intent.setClassName(RECEIVER_PACKAGE_NAME, BRING_TO_FOREGROUND_ACTIVITY) 1251 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP) 1252 intent.putExtra(REMOTE_CALLBACK, RemoteCallback { 1253 attributionSourceRef.set(it?.getParcelable(ATTRIBUTION_SOURCE)) 1254 activityStatedLatch.countDown() 1255 }) 1256 context.startActivity(intent) 1257 activityStatedLatch.await(ASYNC_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) 1258 return attributionSourceRef.get() 1259 } 1260 1261 private fun assumeNotTv() = assumeFalse(isTv) 1262 private fun assumeHasTelephony() = assumeTrue(isTel) 1263 } 1264 } 1265