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