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