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