• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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