/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.permission5.cts

import android.Manifest
import android.app.AppOpsManager
import android.app.Instrumentation
import android.content.AttributionSource
import android.content.ComponentName
import android.content.ContentValues
import android.content.Context
import android.content.ContextParams
import android.content.Intent
import android.content.pm.PackageManager.FEATURE_LEANBACK
import android.content.pm.PackageManager.FEATURE_TELEPHONY
import android.net.Uri
import android.os.Bundle
import android.os.Process
import android.os.RemoteCallback
import android.os.SystemClock
import android.os.UserHandle
import android.permission.PermissionManager
import android.platform.test.annotations.AppModeFull
import android.provider.CalendarContract
import android.provider.CallLog
import android.provider.ContactsContract
import android.provider.Telephony
import android.speech.RecognitionListener
import android.speech.SpeechRecognizer
import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.SystemUtil
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatcher
import org.mockito.Mockito.eq
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.intThat
import org.mockito.Mockito.isNull
import org.mockito.Mockito.mock
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.locks.ReentrantLock
import java.util.function.Consumer

@AppModeFull(reason = "Instant apps cannot hold READ_CONTACTS/READ_CALENDAR/READ_SMS/READ_CALL_LOG")
class RuntimePermissionsAppOpTrackingTest {

    @Before
    fun setUpTest() {
        val appOpsManager = context.getSystemService(AppOpsManager::class.java)!!
        SystemUtil.runWithShellPermissionIdentity {
            appOpsManager.clearHistory()
            appOpsManager.setHistoryParameters(
                    AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE,
                    SNAPSHOT_INTERVAL_MILLIS,
                    INTERVAL_COMPRESSION_MULTIPLIER)

            appOpsManager.resetPackageOpsNoHistory(context.packageName)
            appOpsManager.resetPackageOpsNoHistory(SHELL_PACKAGE_NAME)
            appOpsManager.resetPackageOpsNoHistory(RECEIVER_PACKAGE_NAME)
            appOpsManager.resetPackageOpsNoHistory(RECEIVER2_PACKAGE_NAME)
        }
    }

    @After
    fun tearDownTest() {
        val appOpsManager = context.getSystemService(AppOpsManager::class.java)!!
        SystemUtil.runWithShellPermissionIdentity {
            appOpsManager.clearHistory()
            appOpsManager.resetHistoryParameters()
        }
    }

    @Test
    @Throws(Exception::class)
    fun testSelfContactsAccess() {
        testSelfAccess(ContactsContract.Contacts.CONTENT_URI,
                Manifest.permission.READ_CONTACTS)
    }

    @Test
    @Throws(Exception::class)
    fun testSelfCalendarAccess() {
        testSelfAccess(CalendarContract.Calendars.CONTENT_URI,
                Manifest.permission.READ_CALENDAR)
    }

    @Test
    @Throws(Exception::class)
    fun testSelfSmsAccess() {
        assumeNotTv()
        assumeHasTelephony()
        testSelfAccess(Telephony.Sms.CONTENT_URI,
                Manifest.permission.READ_SMS)
    }

    @Test
    @Throws(Exception::class)
    fun testSelfCallLogAccess() {
        testSelfAccess(CallLog.Calls.CONTENT_URI,
                Manifest.permission.READ_CALL_LOG)
    }

    @Throws(Exception::class)
    private fun testSelfAccess(uri: Uri, permission: String) {
        val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG, null, null)
        val beginEndMillis = System.currentTimeMillis()
        context.contentResolver.query(uri, null, null, null)!!.close()
        val endTimeMillis = System.currentTimeMillis()

        assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!,
                beginEndMillis, endTimeMillis, context.attributionSource,
                /*accessorForeground*/ true, /*receiverForeground*/ false,
                /*accessorTrusted*/ true, /*accessorAccessCount*/ 1,
                /*receiverAccessCount*/ 0, /*checkAccessor*/ true,
                /*fromDatasource*/ false)
    }

    @Test
    @Throws(Exception::class)
    fun testSelfCalendarWrite() {
        testSelfWrite(CalendarContract.Calendars.CONTENT_URI,
                Manifest.permission.WRITE_CALENDAR)
    }

    @Test
    @Throws(Exception::class)
    fun testSelfCallLogWrite() {
        testSelfWrite(CallLog.Calls.CONTENT_URI,
                Manifest.permission.WRITE_CALL_LOG)
    }

    @Throws(Exception::class)
    private fun testSelfWrite(uri: Uri, permission: String) {
        val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG, null, null)
        val beginEndMillis = System.currentTimeMillis()
        context.contentResolver.insert(uri, ContentValues())
        val endTimeMillis = System.currentTimeMillis()

        assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!,
                beginEndMillis, endTimeMillis, context.attributionSource,
                /*accessorForeground*/ true, /*receiverForeground*/ false,
                /*accessorTrusted*/ true, /*accessorAccessCount*/ 1,
                /*receiverAccessCount*/ 0, /*checkAccessor*/ true,
                /*fromDatasource*/ false)
    }

    @Test
    @Throws(Exception::class)
    fun testUntrustedContactsAccessAttributeToAnother() {
        testUntrustedAccessAttributeToAnother(ContactsContract.Contacts.CONTENT_URI,
                Manifest.permission.READ_CONTACTS)
    }

    @Test
    @Throws(Exception::class)
    fun testUntrustedCalendarAccessAttributeToAnother() {
        testUntrustedAccessAttributeToAnother(CalendarContract.Calendars.CONTENT_URI,
                Manifest.permission.READ_CALENDAR)
    }

    @Test
    @Throws(Exception::class)
    fun testUntrustedSmsAccessAttributeToAnother() {
        assumeNotTv()
        assumeHasTelephony()
        testUntrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI,
                Manifest.permission.READ_SMS)
    }

    @Test
    @Throws(Exception::class)
    fun testUntrustedCallLogAccessAttributeToAnother() {
        testUntrustedAccessAttributeToAnother(CallLog.Calls.CONTENT_URI,
                Manifest.permission.READ_CALL_LOG)
    }

    @Throws(Exception::class)
    private fun testUntrustedAccessAttributeToAnother(uri: Uri, permission: String) {
        val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG,
                RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG)
        val beginEndMillis = System.currentTimeMillis()
        context.contentResolver.query(uri, null, null, null)!!.close()
        val endTimeMillis = System.currentTimeMillis()

        assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!,
                beginEndMillis, endTimeMillis, context.attributionSource,
                /*accessorForeground*/ true, /*receiverForeground*/ false,
                /*accessorTrusted*/ false, /*accessorAccessCount*/ 1,
                /*receiverAccessCount*/ 1, /*checkAccessor*/ false,
                /*fromDatasource*/ false)
    }

    @Test
    @Throws(Exception::class)
    fun testUntrustedContactsAccessAttributeToAnotherThroughIntermediary() {
        testUntrustedAccessAttributeToAnotherThroughIntermediary(
                ContactsContract.Contacts.CONTENT_URI,
                Manifest.permission.READ_CONTACTS)
    }

    @Test
    @Throws(Exception::class)
    fun testUntrustedCalendarAccessAttributeToAnotherThroughIntermediary() {
        testUntrustedAccessAttributeToAnotherThroughIntermediary(
                CalendarContract.Calendars.CONTENT_URI,
                Manifest.permission.READ_CALENDAR)
    }

    @Test
    @Throws(Exception::class)
    fun testUntrustedSmsAccessAttributeToAnotherThroughIntermediary() {
        assumeNotTv()
        assumeHasTelephony()
        testUntrustedAccessAttributeToAnotherThroughIntermediary(
                Telephony.Sms.CONTENT_URI,
                Manifest.permission.READ_SMS)
    }

    @Test
    @Throws(Exception::class)
    fun testUntrustedCallLogAccessAttributeToAnotherThroughIntermediary() {
        testUntrustedAccessAttributeToAnotherThroughIntermediary(
                CallLog.Calls.CONTENT_URI,
                Manifest.permission.READ_CALL_LOG)
    }

    @Throws(Exception::class)
    private fun testUntrustedAccessAttributeToAnotherThroughIntermediary(
        uri: Uri,
        permission: String
    ) {
        runWithAuxiliaryApps {
            val nextAttributionSource = startBlamedAppActivity()

            val intermediaryContext = context.createContext(ContextParams.Builder()
                    .setNextAttributionSource(nextAttributionSource)
                    .setAttributionTag(ACCESSOR_ATTRIBUTION_TAG)
                    .build())

            val beginEndMillis = System.currentTimeMillis()
            intermediaryContext.contentResolver.query(uri, null, null, null)!!.close()
            val endTimeMillis = System.currentTimeMillis()

            // Assert first stage access
            assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!,
                    beginEndMillis, endTimeMillis, intermediaryContext.attributionSource,
                    /*accessorForeground*/ true, /*receiverForeground*/ true,
                    /*accessorTrusted*/ false, /*accessorAccessCount*/ 1,
                    /*receiverAccessCount*/ 1, /*checkAccessor*/ false,
                    /*fromDatasource*/ false)

            // Assert second stage access
            assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!,
                    beginEndMillis, endTimeMillis, nextAttributionSource,
                    /*accessorForeground*/ true, /*receiverForeground*/ false,
                    /*accessorTrusted*/ false, /*accessorAccessCount*/ 1,
                    /*receiverAccessCount*/ 1, /*checkAccessor*/ false,
                    /*fromDatasource*/ false)
        }
    }

    @Test(expected = SecurityException::class)
    fun testCannotForgeAttributionSource() {
        val receiverSource = AttributionSource(context
                .packageManager.getPackageUid(RECEIVER2_PACKAGE_NAME, 0),
                RECEIVER2_PACKAGE_NAME, RECEIVER2_ATTRIBUTION_TAG, null, AttributionSource(
                context.packageManager.getPackageUid(RECEIVER_PACKAGE_NAME, 0),
                RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG))
        val intermediaryContext = context.createContext(ContextParams.Builder()
            .setNextAttributionSource(receiverSource)
            .setAttributionTag(ACCESSOR_ATTRIBUTION_TAG)
            .build())
        intermediaryContext.contentResolver.query(CallLog.Calls.CONTENT_URI, null,
                null, null)!!.close()
    }

    @Test(expected = SecurityException::class)
    fun testCannotAppendToForgeAttributionSource() {
        runWithAuxiliaryApps {
            val nextAttributionSource = startBlamedAppActivity()
            val untrustedAttributionSource = AttributionSource(context
                    .packageManager.getPackageUid(RECEIVER2_PACKAGE_NAME, 0),
                    RECEIVER2_PACKAGE_NAME, RECEIVER2_ATTRIBUTION_TAG, null,
                    nextAttributionSource)
            val intermediaryContext = context.createContext(ContextParams.Builder()
                    .setNextAttributionSource(untrustedAttributionSource)
                    .setAttributionTag(ACCESSOR_ATTRIBUTION_TAG)
                    .build())
            intermediaryContext.contentResolver.query(CallLog.Calls.CONTENT_URI, null,
                    null, null)!!.close()
        }
    }

    @Test
    @Throws(Exception::class)
    fun testTrustedAccessContactsAttributeToAnother() {
        testTrustedAccessAttributeToAnother(ContactsContract.Contacts.CONTENT_URI,
                Manifest.permission.READ_CONTACTS)
    }

    @Test
    @Throws(Exception::class)
    fun testTrustedAccessCalendarAttributeToAnother() {
        testTrustedAccessAttributeToAnother(CalendarContract.Calendars.CONTENT_URI,
                Manifest.permission.READ_CALENDAR)
    }

    @Test
    @Throws(Exception::class)
    fun testTrustedAccessSmsAttributeToAnother() {
        assumeNotTv()
        assumeHasTelephony()
        testTrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI,
                Manifest.permission.READ_SMS)
    }

    @Test
    @Throws(Exception::class)
    fun testTrustedAccessCallLogAttributeToAnother() {
        testTrustedAccessAttributeToAnother(CallLog.Calls.CONTENT_URI,
                Manifest.permission.READ_CALL_LOG)
    }

    @Throws(Exception::class)
    private fun testTrustedAccessAttributeToAnother(uri: Uri, permission: String) {
        val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG,
                RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG)
        val beginEndMillis = System.currentTimeMillis()
        SystemUtil.runWithShellPermissionIdentity {
            context.contentResolver.query(uri, null, null, null)!!.close()
        }
        val endTimeMillis = System.currentTimeMillis()

        // Calculate the shellUid to account for running this from a secondary user.
        val shellUid = UserHandle.getUid(Process.myUserHandle().identifier,
            UserHandle.getAppId(Process.SHELL_UID))
        // Since we use adopt the shell permission identity we need to adjust
        // the permission identity to have the shell as the accessor.
        assertNotRunningOpAccess(AppOpsManager.permissionToOp(permission)!!,
                beginEndMillis, endTimeMillis, AttributionSource(shellUid,
                SHELL_PACKAGE_NAME, context.attributionTag, null,
                context.attributionSource.next),
                /*accessorForeground*/ false, /*receiverForeground*/ false,
                /*accessorTrusted*/ true, /*accessorAccessCount*/ 1,
                /*receiverAccessCount*/ 1, /*checkAccessor*/ false,
                /*fromDatasource*/ false)
    }

    @Test
    @Throws(Exception::class)
    fun testMicRecognitionInjectRecoWithoutAttribution() {
        runWithAuxiliaryApps {
            startBlamedAppActivity()

            val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG,
                    RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG)

            val listener = mock(AppOpsManager.OnOpActiveChangedListener::class.java)
            val appopsManager = context.getSystemService(AppOpsManager::class.java)
            SystemUtil.runWithShellPermissionIdentity<Unit> {
                appopsManager!!.startWatchingActive(arrayOf(AppOpsManager.OPSTR_RECORD_AUDIO),
                        context.mainExecutor, listener)
            }

            val speechStartTime = System.currentTimeMillis()
            val recognizerRef = AtomicReference<SpeechRecognizer>()
            var currentOperationComplete = CountDownLatch(1)

            instrumentation.runOnMainSync {
                val recognizer = SpeechRecognizer.createSpeechRecognizer(context,
                        ComponentName(RECEIVER2_PACKAGE_NAME, RECOGNITION_SERVICE))

                recognizer.setRecognitionListener(object : RecognitionListener {
                    override fun onReadyForSpeech(params: Bundle?) {}
                    override fun onRmsChanged(rmsdB: Float) {}
                    override fun onBufferReceived(buffer: ByteArray?) {
                        currentOperationComplete.countDown()
                    }
                    override fun onPartialResults(partialResults: Bundle?) {}
                    override fun onEvent(eventType: Int, params: Bundle?) {}
                    override fun onError(error: Int) {}
                    override fun onResults(results: Bundle?) {}
                    override fun onBeginningOfSpeech() {}
                    override fun onEndOfSpeech() {}
                })

                val recoIntent = Intent()
                recoIntent.putExtra(OPERATION, OPERATION_INJECT_RECO_WITHOUT_ATTRIBUTION)
                recognizer.startListening(recoIntent)

                recognizerRef.set(recognizer)
            }

            try {
                currentOperationComplete.await(ASYNC_OPERATION_TIMEOUT_MILLIS,
                        TimeUnit.MILLISECONDS)

                val op = AppOpsManager.permissionToOp(Manifest.permission.RECORD_AUDIO)!!

                assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                        AttributionSource(context.packageManager.getPackageUid(
                                RECEIVER2_PACKAGE_NAME, 0), RECEIVER2_PACKAGE_NAME,
                                /*attributionTag*/ null, null, context.attributionSource),
                        /*accessorForeground*/ true, /*receiverForeground*/ true,
                        /*accessorTrusted*/ false, /*accessorAccessCount*/ 1,
                        /*receiverAccessCount*/ 1, /*checkAccessor*/ true,
                        /*fromDatasource*/ false)

                assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                        context.attributionSource, /*accessorForeground*/ true,
                        /*receiverForeground*/ true, /*accessorTrusted*/ false,
                        /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1,
                        /*checkAccessor*/ false, /*fromDatasource*/ false)

                // Finish recon and check if all ops are finished
                currentOperationComplete = CountDownLatch(1)
                instrumentation.runOnMainSync { recognizerRef.get().cancel() }
                currentOperationComplete.await(ASYNC_OPERATION_TIMEOUT_MILLIS,
                        TimeUnit.MILLISECONDS)

                val recognizerUid = context.packageManager.getPackageUid(
                        RECEIVER2_PACKAGE_NAME, 0)

                assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                        AttributionSource(recognizerUid, RECEIVER2_PACKAGE_NAME,
                                /*attributionTag*/ null, null, context.attributionSource),
                        /*accessorForeground*/ true, /*receiverForeground*/ true,
                        /*accessorTrusted*/ false, /*accessorAccessCount*/ 1,
                        /*receiverAccessCount*/ 1, /*checkAccessor*/ true,
                        /*fromDatasource*/ false)

                assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                        context.attributionSource, /*accessorForeground*/ true,
                        /*receiverForeground*/ true, /*accessorTrusted*/ false,
                        /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1,
                        /*checkAccessor*/ false, /*fromDatasource*/ false)

                var attributionChainId: Int? = null
                val inOrder = inOrder(listener)
                val attributionChainIdMatcher = ArgumentMatcher<Int> {
                    if (attributionChainId == null) {
                        attributionChainId = it
                        return@ArgumentMatcher true
                    } else {
                        return@ArgumentMatcher (attributionChainId == it)
                    }
                }
                val receiverUid = context.packageManager.getPackageUid(
                        RECEIVER_PACKAGE_NAME, 0)

                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), eq(true),
                        eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR),
                        intThat(attributionChainIdMatcher))
                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG),
                        eq(true), eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY),
                        intThat(attributionChainIdMatcher))
                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG),
                        eq(true), eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER),
                        intThat(attributionChainIdMatcher))

                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), eq(false),
                        eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR),
                        intThat(attributionChainIdMatcher))
                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG),
                        eq(false), eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY),
                        intThat(attributionChainIdMatcher))
                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG),
                        eq(false), eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER),
                        intThat(attributionChainIdMatcher))
            } finally {
                // Take down the recognition service
                instrumentation.runOnMainSync { recognizerRef.get().destroy() }
            }
        }
    }

    @Test
    @Throws(Exception::class)
    fun testMicRecognitionMicRecoWithAttribution() {
        runWithAuxiliaryApps {
            startBlamedAppActivity()

            val context = createAttributionContext(ACCESSOR_ATTRIBUTION_TAG,
                    RECEIVER_PACKAGE_NAME, RECEIVER_ATTRIBUTION_TAG)

            val listener = mock(AppOpsManager.OnOpActiveChangedListener::class.java)
            val appopsManager = context.getSystemService(AppOpsManager::class.java)
            SystemUtil.runWithShellPermissionIdentity<Unit> {
                appopsManager!!.startWatchingActive(arrayOf(AppOpsManager.OPSTR_RECORD_AUDIO),
                        context.mainExecutor, listener)
            }

            val speechStartTime = System.currentTimeMillis()
            val recognizerRef = AtomicReference<SpeechRecognizer>()
            var currentOperationComplete = CountDownLatch(1)

            instrumentation.runOnMainSync {
                val recognizer = SpeechRecognizer.createSpeechRecognizer(context,
                        ComponentName(RECEIVER2_PACKAGE_NAME, RECOGNITION_SERVICE))

                recognizer.setRecognitionListener(object : RecognitionListener {
                    override fun onReadyForSpeech(params: Bundle?) {}
                    override fun onRmsChanged(rmsdB: Float) {}
                    override fun onBufferReceived(buffer: ByteArray?) {
                        currentOperationComplete.countDown()
                    }
                    override fun onPartialResults(partialResults: Bundle?) {}
                    override fun onEvent(eventType: Int, params: Bundle?) {}
                    override fun onError(error: Int) {}
                    override fun onResults(results: Bundle?) {}
                    override fun onBeginningOfSpeech() {}
                    override fun onEndOfSpeech() {}
                })

                val recoIntent = Intent()
                recoIntent.putExtra(OPERATION, OPERATION_MIC_RECO_WITH_ATTRIBUTION)
                recognizer.startListening(recoIntent)

                recognizerRef.set(recognizer)
            }

            try {
                currentOperationComplete.await(ASYNC_OPERATION_TIMEOUT_MILLIS,
                        TimeUnit.MILLISECONDS)

                val op = AppOpsManager.permissionToOp(Manifest.permission.RECORD_AUDIO)!!

                assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                        AttributionSource(context.packageManager.getPackageUid(
                                RECEIVER2_PACKAGE_NAME, 0), RECEIVER2_PACKAGE_NAME,
                                /*attributionTag*/ null, null, context.attributionSource),
                        /*accessorForeground*/ true, /*receiverForeground*/ true,
                        /*accessorTrusted*/ true, /*accessorAccessCount*/ 1,
                        /*receiverAccessCount*/ 1, /*checkAccessor*/ true,
                        /*fromDatasource*/ true)

                assertRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                        context.attributionSource, /*accessorForeground*/ true,
                        /*receiverForeground*/ true, /*accessorTrusted*/ true,
                        /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1,
                        /*checkAccessor*/ false, /*fromDatasource*/ true)

                // Finish recon and check if all ops are finished
                currentOperationComplete = CountDownLatch(1)
                instrumentation.runOnMainSync { recognizerRef.get().cancel() }
                currentOperationComplete.await(ASYNC_OPERATION_TIMEOUT_MILLIS,
                        TimeUnit.MILLISECONDS)

                val recognizerUid = context.packageManager.getPackageUid(
                        RECEIVER2_PACKAGE_NAME, 0)

                assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                        AttributionSource(recognizerUid, RECEIVER2_PACKAGE_NAME,
                                /*attributionTag*/ null, null, context.attributionSource),
                        /*accessorForeground*/ true, /*receiverForeground*/ true,
                        /*accessorTrusted*/ true, /*accessorAccessCount*/ 1,
                        /*receiverAccessCount*/ 1, /*checkAccessor*/ true,
                        /*fromDatasource*/ true)

                assertNotRunningOpAccess(op, speechStartTime, System.currentTimeMillis(),
                        context.attributionSource, /*accessorForeground*/ true,
                        /*receiverForeground*/ true, /*accessorTrusted*/ true,
                        /*accessorAccessCount*/ 0, /*receiverAccessCount*/ 1,
                        /*checkAccessor*/ false, /*fromDatasource*/ true)

                var attributionChainId: Int? = null
                val inOrder = inOrder(listener)
                val attributionChainIdMatcher = ArgumentMatcher<Int> {
                    if (attributionChainId == null) {
                        attributionChainId = it
                        return@ArgumentMatcher true
                    } else {
                        return@ArgumentMatcher (attributionChainId == it)
                    }
                }
                val receiverUid = context.packageManager.getPackageUid(
                        RECEIVER_PACKAGE_NAME, 0)

                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), eq(true),
                        eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR or ATTRIBUTION_FLAG_TRUSTED),
                        intThat(attributionChainIdMatcher))
                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG),
                        eq(true), eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY or
                        ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher))
                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG),
                        eq(true), eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER or
                        ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher))

                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(recognizerUid), eq(RECEIVER2_PACKAGE_NAME), isNull(), eq(false),
                        eq(AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR or ATTRIBUTION_FLAG_TRUSTED),
                        intThat(attributionChainIdMatcher))
                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(Process.myUid()), eq(context.packageName), eq(ACCESSOR_ATTRIBUTION_TAG),
                        eq(false), eq(AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY or
                        ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher))
                inOrder.verify(listener).onOpActiveChanged(eq(AppOpsManager.OPSTR_RECORD_AUDIO),
                        eq(receiverUid), eq(RECEIVER_PACKAGE_NAME), eq(RECEIVER_ATTRIBUTION_TAG),
                        eq(false), eq(AppOpsManager.ATTRIBUTION_FLAG_RECEIVER or
                        ATTRIBUTION_FLAG_TRUSTED), intThat(attributionChainIdMatcher))
            } finally {
                // Take down the recognition service
                instrumentation.runOnMainSync { recognizerRef.get().destroy() }
            }
        }
    }

    fun runWithAuxiliaryApps(worker: () -> Unit) {
        ensureAuxiliaryAppsNotRunningAndNoResidualProcessState()
        try {
            worker.invoke()
        } finally {
            ensureAuxiliaryAppsNotRunningAndNoResidualProcessState()
        }
    }

    companion object {
        private const val ASYNC_OPERATION_TIMEOUT_MILLIS: Long = 5000 // 5 sec
        private const val INTERVAL_COMPRESSION_MULTIPLIER = 10
        private const val SNAPSHOT_INTERVAL_MILLIS: Long = 1000

        val SHELL_PACKAGE_NAME = "com.android.shell"
        val RECEIVER_PACKAGE_NAME = "android.permission5.cts.blamed"
        val BRING_TO_FOREGROUND_ACTIVITY =
                "android.permission5.cts.blamed.BringToForegroundActivity"
        val RECOGNITION_SERVICE = "android.permission5.cts.blamed2.MyRecognitionService"
        val REMOTE_CALLBACK = "remote_callback"
        val ATTRIBUTION_SOURCE = "attribution_source"
        val ACCESSOR_ATTRIBUTION_TAG = "accessor_attribution_tag"
        val RECEIVER2_PACKAGE_NAME = "android.permission5.cts.blamed2"
        val RECEIVER_ATTRIBUTION_TAG = "receiver_attribution_tag"
        val RECEIVER2_ATTRIBUTION_TAG = "receiver2_attribution_tag"

        val OPERATION = "operation"
        val OPERATION_MIC_RECO_WITH_ATTRIBUTION = "operation:mic_reco_with_attribution"
        val OPERATION_INJECT_RECO_WITHOUT_ATTRIBUTION = "operation:inject_reco_without_attribution"

        val ATTRIBUTION_FLAG_TRUSTED = 0x8

        private val context: Context
            get() = InstrumentationRegistry.getInstrumentation().getContext()

        private val instrumentation: Instrumentation
            get() = InstrumentationRegistry.getInstrumentation()

        private val isTv = context.packageManager.hasSystemFeature(FEATURE_LEANBACK)
        private val isTel = context.packageManager.hasSystemFeature(FEATURE_TELEPHONY)

        fun ensureAuxiliaryAppsNotRunningAndNoResidualProcessState() {
            SystemUtil.runShellCommand("am force-stop $RECEIVER_PACKAGE_NAME")
            SystemUtil.runShellCommand("am force-stop $RECEIVER2_PACKAGE_NAME")
            SystemClock.sleep(ASYNC_OPERATION_TIMEOUT_MILLIS)
        }

        @Throws(Exception::class)
        private fun assertRunningOpAccess(
            op: String,
            beginEndMillis: Long,
            endTimeMillis: Long,
            attributionSource: AttributionSource,
            accessorForeground: Boolean,
            receiverForeground: Boolean,
            accessorTrusted: Boolean,
            accessorAccessCount: Int,
            receiverAccessCount: Int,
            checkAccessor: Boolean,
            fromDatasource: Boolean
        ) {
            assertOpAccess(op, beginEndMillis, endTimeMillis, attributionSource,
                    accessorForeground, receiverForeground, accessorTrusted,
                    /*assertRunning*/ true, accessorAccessCount, receiverAccessCount,
                    checkAccessor, fromDatasource)
        }

        @Throws(Exception::class)
        private fun assertNotRunningOpAccess(
            op: String,
            beginEndMillis: Long,
            endTimeMillis: Long,
            attributionSource: AttributionSource,
            accessorForeground: Boolean,
            receiverForeground: Boolean,
            accessorTrusted: Boolean,
            accessorAccessCount: Int,
            receiverAccessCount: Int,
            checkAccessor: Boolean,
            fromDatasource: Boolean
        ) {
            assertOpAccess(op, beginEndMillis, endTimeMillis, attributionSource,
                    accessorForeground, receiverForeground, accessorTrusted,
                    /*assertRunning*/ false, accessorAccessCount, receiverAccessCount,
                    checkAccessor, fromDatasource)
        }

        @Throws(Exception::class)
        private fun assertOpAccess(
            op: String,
            beginEndMillis: Long,
            endTimeMillis: Long,
            attributionSource: AttributionSource,
            accessorForeground: Boolean,
            receiverForeground: Boolean,
            accessorTrusted: Boolean,
            assertRunning: Boolean,
            accessorAccessCount: Int,
            receiverAccessCount: Int,
            checkAccessor: Boolean,
            fromDatasource: Boolean
        ) {
            assertLastOpAccess(op, beginEndMillis, endTimeMillis, attributionSource,
                    accessorForeground, receiverForeground, accessorTrusted, assertRunning,
                    checkAccessor, fromDatasource)
            assertHistoricalOpAccess(op, attributionSource, accessorForeground,
                    receiverForeground, accessorTrusted, accessorAccessCount, receiverAccessCount,
                    checkAccessor, fromDatasource)
        }

        private fun assertLastOpAccess(
            op: String,
            beginEndMillis: Long,
            endTimeMillis: Long,
            attributionSource: AttributionSource,
            accessorForeground: Boolean,
            receiverForeground: Boolean,
            accessorTrusted: Boolean,
            assertRunning: Boolean,
            checkAccessor: Boolean,
            fromDatasource: Boolean
        ) {
            val appOpsManager = context.getSystemService(AppOpsManager::class.java)!!
            val allPackagesOps: MutableList<AppOpsManager.PackageOps?> = ArrayList()
            SystemUtil.runWithShellPermissionIdentity<Boolean> {
                allPackagesOps.addAll(appOpsManager.getPackagesForOps(arrayOf(op)))
            }
            if (checkAccessor) {
                assertLastAccessorOps(op, beginEndMillis, endTimeMillis, attributionSource,
                        accessorForeground, accessorTrusted, assertRunning, fromDatasource,
                        allPackagesOps)
            } else {
                assertNotLastAccessorOps(op, attributionSource, allPackagesOps)
            }
            if (attributionSource.next != null) {
                assertLastReceiverOps(op, beginEndMillis, endTimeMillis, attributionSource,
                        receiverForeground, accessorTrusted, assertRunning, allPackagesOps)
            }
        }

        @Throws(Exception::class)
        private fun assertHistoricalOpAccess(
            op: String,
            attributionSource: AttributionSource,
            accessorForeground: Boolean,
            receiverForeground: Boolean,
            accessorTrusted: Boolean,
            accessorAccessCount: Int,
            receiverAccessCount: Int,
            checkAccessor: Boolean,
            fromDatasource: Boolean
        ) {
            val appOpsManager = context.getSystemService(AppOpsManager::class.java)!!
            val request = AppOpsManager.HistoricalOpsRequest.Builder(0, Long.MAX_VALUE)
                    .setOpNames(listOf(op))
                    .build()
            val historicalOpsRef = AtomicReference<AppOpsManager.HistoricalOps>()
            val lock = ReentrantLock()
            val condition = lock.newCondition()
            SystemUtil.runWithShellPermissionIdentity {
                appOpsManager.getHistoricalOps(request, context.mainExecutor,
                        Consumer { historicalOps: AppOpsManager.HistoricalOps ->
                            historicalOpsRef.set(historicalOps)
                            lock.lock()
                            try {
                                condition.signalAll()
                            } finally {
                                lock.unlock()
                            }
                        })
            }
            lock.lock()
            try {
                condition.await(ASYNC_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
            } finally {
                lock.unlock()
            }

            val historicalOps = historicalOpsRef.get()
            if (checkAccessor) {
                assertHistoricalAccessorOps(op, attributionSource, accessorForeground,
                        accessorTrusted, fromDatasource, accessorAccessCount, historicalOps)
            } else {
                assertNoHistoricalAccessorOps(op, attributionSource, historicalOps)
            }
            if (attributionSource.next != null) {
                assertHistoricalReceiverOps(op, attributionSource, receiverForeground,
                        accessorTrusted, receiverAccessCount, historicalOps)
            }
        }

        private fun assertLastAccessorOps(
            op: String,
            beginEndMillis: Long,
            endTimeMillis: Long,
            attributionSource: AttributionSource,
            accessorForeground: Boolean,
            accessorTrusted: Boolean,
            assertRunning: Boolean,
            fromDatasource: Boolean,
            allPackagesOps: List<AppOpsManager.PackageOps?>
        ) {
            val accessorPackageOps = findPackageOps(attributionSource.uid,
                    attributionSource.packageName!!, allPackagesOps)
            for (opEntry in accessorPackageOps!!.ops) {
                if (!op.equals(opEntry.opStr)) {
                    continue
                }
                val attributedOpEntry = opEntry.attributedOpEntries[
                        attributionSource.attributionTag]
                if (attributionSource.next == null) {
                    // Access for ourselves
                    assertLastAccessInRange(attributedOpEntry!!, beginEndMillis, endTimeMillis,
                            AppOpsManager.OP_FLAG_SELF, accessorForeground, assertRunning)
                } else if (accessorTrusted) {
                    // Access for others and we are trusted. If we got the data from a datasource
                    // the latter is the proxy and we proxied, otherwise we are the proxy.
                    if (fromDatasource) {
                        assertLastAccessInRange(attributedOpEntry!!, beginEndMillis, endTimeMillis,
                                AppOpsManager.OP_FLAG_TRUSTED_PROXIED, accessorForeground,
                                assertRunning)
                    } else {
                        assertLastAccessInRange(attributedOpEntry!!, beginEndMillis, endTimeMillis,
                                AppOpsManager.OP_FLAG_TRUSTED_PROXY, accessorForeground,
                                assertRunning)
                    }
                } else {
                    // Access for others and we are not trusted.
                    assertLastAccessInRange(attributedOpEntry!!, beginEndMillis, endTimeMillis,
                            AppOpsManager.OP_FLAG_UNTRUSTED_PROXY, accessorForeground,
                            assertRunning)
                }
            }
        }

        private fun assertNotLastAccessorOps(
            op: String,
            attributionSource: AttributionSource,
            allPackagesOps: List<AppOpsManager.PackageOps?>
        ) {
            val accessorPackageOps = findPackageOps(attributionSource.uid,
                    attributionSource.packageName!!, allPackagesOps) ?: return
            for (opEntry in accessorPackageOps.ops) {
                if (!op.equals(opEntry.opStr)) {
                    continue
                }
                val attributedOpEntry = opEntry.attributedOpEntries[
                        attributionSource.attributionTag]
                if (attributedOpEntry != null) {
                    assertThat(attributedOpEntry.getLastAccessBackgroundTime(
                            AppOpsManager.OP_FLAG_SELF
                            or AppOpsManager.OP_FLAG_UNTRUSTED_PROXY
                            or AppOpsManager.OP_FLAG_TRUSTED_PROXY)).isEqualTo(-1)
                    assertThat(attributedOpEntry.getLastAccessBackgroundTime(
                            AppOpsManager.OP_FLAG_SELF
                            or AppOpsManager.OP_FLAG_UNTRUSTED_PROXY
                            or AppOpsManager.OP_FLAG_TRUSTED_PROXY)).isEqualTo(-1)
                }
            }
        }

        private fun assertHistoricalAccessorOps(
            op: String,
            attributionSource: AttributionSource,
            accessorForeground: Boolean,
            accessorTrusted: Boolean,
            fromDatasource: Boolean,
            assertedAccessCount: Int,
            historicalOps: AppOpsManager.HistoricalOps
        ) {
            val accessorPackageOps = findPackageOps(
                    attributionSource.uid, attributionSource.packageName!!,
                    historicalOps)
            val attributedPackageOps = accessorPackageOps?.getAttributedOps(
                    attributionSource.attributionTag)

            val attributedPackageOp = attributedPackageOps!!.getOp(op)
            if (attributionSource.next == null) {
                // Access for ourselves
                assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_SELF,
                        accessorForeground, assertedAccessCount)
            } else if (accessorTrusted) {
                // Access for others and we are trusted. If we got the data from a datasource it
                // would blame the accessor in a trusted way
                if (fromDatasource) {
                    assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_TRUSTED_PROXIED,
                            accessorForeground, assertedAccessCount)
                } else {
                    assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_TRUSTED_PROXY,
                            accessorForeground, assertedAccessCount)
                }
            } else {
                // Access for others and we are not trusted
                assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_UNTRUSTED_PROXY,
                        accessorForeground, assertedAccessCount)
            }
        }

        private fun assertNoHistoricalAccessorOps(
            op: String,
            attributionSource: AttributionSource,
            historicalOps: AppOpsManager.HistoricalOps
        ) {
            val accessorPackageOps = findPackageOps(
                    attributionSource.uid, attributionSource.packageName!!,
                    historicalOps)
            val attributedPackageOps = accessorPackageOps?.getAttributedOps(
                    attributionSource.attributionTag) ?: return
            val attributedPackageOp = attributedPackageOps.getOp(op)
            if (attributedPackageOp != null) {
                assertThat(attributedPackageOp.getBackgroundAccessCount(
                        AppOpsManager.OP_FLAG_SELF
                                or AppOpsManager.OP_FLAG_UNTRUSTED_PROXY
                                or AppOpsManager.OP_FLAG_TRUSTED_PROXY)).isEqualTo(0)
                assertThat(attributedPackageOp.getBackgroundAccessCount(
                        AppOpsManager.OP_FLAG_SELF
                                or AppOpsManager.OP_FLAG_UNTRUSTED_PROXY
                                or AppOpsManager.OP_FLAG_TRUSTED_PROXY)).isEqualTo(0)
            }
        }

        private fun assertLastReceiverOps(
            op: String,
            beginTimeMillis: Long,
            endTimeMillis: Long,
            attributionSource: AttributionSource,
            receiverForeground: Boolean,
            accessorTrusted: Boolean,
            assertRunning: Boolean,
            allPackagesOps: List<AppOpsManager.PackageOps?>
        ) {
            val receiverPackageOps = findPackageOps(
                    attributionSource.next!!.uid,
                    attributionSource.next!!.packageName!!,
                    allPackagesOps)
            for (opEntry in receiverPackageOps!!.ops) {
                if (op != opEntry.opStr) {
                    continue
                }
                val attributedOpEntry = opEntry.attributedOpEntries[
                        attributionSource.next!!.attributionTag]
                val opProxyInfo: AppOpsManager.OpEventProxyInfo?
                opProxyInfo = if (accessorTrusted) {
                    // Received from a trusted accessor. If we got the data from a datasource it
                    // would blame the accessor in a trusted way
                    assertLastAccessInRange(attributedOpEntry!!, beginTimeMillis, endTimeMillis,
                            AppOpsManager.OP_FLAG_TRUSTED_PROXIED, receiverForeground,
                            assertRunning)
                    attributedOpEntry.getLastProxyInfo(AppOpsManager.OP_FLAG_TRUSTED_PROXIED)
                } else {
                    // Received from an untrusted accessor
                    assertLastAccessInRange(attributedOpEntry!!, beginTimeMillis, endTimeMillis,
                            AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED, receiverForeground,
                            assertRunning)
                    attributedOpEntry.getLastProxyInfo(
                            AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED)
                }
                assertThat(opProxyInfo!!.uid).isEqualTo(attributionSource.uid)
                assertThat(opProxyInfo.packageName).isEqualTo(attributionSource.packageName)
                assertThat(opProxyInfo.attributionTag).isEqualTo(attributionSource.attributionTag)
            }
        }

        private fun assertHistoricalReceiverOps(
            op: String,
            attributionSource: AttributionSource,
            receiverForeground: Boolean,
            accessorTrusted: Boolean,
            assertedAccessCount: Int,
            historicalOps: AppOpsManager.HistoricalOps
        ) {
            val accessorPackageOps = findPackageOps(
                    attributionSource.next!!.uid,
                    attributionSource.next!!.packageName!!,
                    historicalOps)
            val attributedPackageOps = accessorPackageOps?.getAttributedOps(
                    attributionSource.next!!.attributionTag!!)
            val attributedPackageOp = attributedPackageOps!!.getOp(op)
            if (accessorTrusted) {
                // Received from a trusted accessor.
                    assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_TRUSTED_PROXIED,
                            receiverForeground, assertedAccessCount)
            } else {
                // Received from an untrusted accessor
                assertAccessCount(attributedPackageOp!!, AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED,
                        receiverForeground, assertedAccessCount)
            }
        }

        private fun assertLastAccessInRange(
            opEntry: AppOpsManager.AttributedOpEntry,
            beginTimeMillis: Long,
            endTimeMillis: Long,
            assertedFlag: Int,
            assertForeground: Boolean,
            assertRunning: Boolean
        ) {
            assertThat(opEntry.isRunning).isEqualTo(assertRunning)
            assertTimeInRangeIfRequired(opEntry, assertedFlag,
                    AppOpsManager.OP_FLAG_SELF,
                    assertForeground, beginTimeMillis, endTimeMillis)
            assertTimeInRangeIfRequired(opEntry, assertedFlag,
                    AppOpsManager.OP_FLAG_TRUSTED_PROXY,
                    assertForeground, beginTimeMillis, endTimeMillis)
            assertTimeInRangeIfRequired(opEntry, assertedFlag,
                    AppOpsManager.OP_FLAG_UNTRUSTED_PROXY,
                    assertForeground, beginTimeMillis, endTimeMillis)
            assertTimeInRangeIfRequired(opEntry, assertedFlag,
                    AppOpsManager.OP_FLAG_TRUSTED_PROXIED,
                    assertForeground, beginTimeMillis, endTimeMillis)
            assertTimeInRangeIfRequired(opEntry, assertedFlag,
                    AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED,
                    assertForeground, beginTimeMillis, endTimeMillis)
            if (assertForeground) {
                assertThat(opEntry.getLastAccessBackgroundTime(AppOpsManager.OP_FLAGS_ALL))
                        .isEqualTo(-1)
            } else {
                assertThat(opEntry.getLastAccessForegroundTime(AppOpsManager.OP_FLAGS_ALL))
                        .isEqualTo(-1)
            }
        }

        private fun assertTimeInRangeIfRequired(
            opEntry: AppOpsManager.AttributedOpEntry,
            assertedFlag: Int,
            accessedFlag: Int,
            assertForeground: Boolean,
            beginTimeMillis: Long,
            endTimeMillis: Long
        ) {
            if (assertedFlag != accessedFlag) {
                return
            }
            val accessTime: Long
            accessTime = if (assertForeground) {
                opEntry.getLastAccessForegroundTime(accessedFlag)
            } else {
                opEntry.getLastAccessBackgroundTime(accessedFlag)
            }
            assertThat(accessTime).isAtLeast(beginTimeMillis)
            assertThat(accessTime).isAtMost(endTimeMillis)
        }

        private fun assertAccessCount(
            historicalOp: AppOpsManager.HistoricalOp,
            assertedFlag: Int,
            assertForeground: Boolean,
            assertedAccessCount: Int
        ) {
            assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_SELF,
                    assertedFlag, assertForeground, assertedAccessCount)
            assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_TRUSTED_PROXY,
                    assertedFlag, assertForeground, assertedAccessCount)
            assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_UNTRUSTED_PROXY,
                    assertedFlag, assertForeground, assertedAccessCount)
            assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_TRUSTED_PROXIED,
                    assertedFlag, assertForeground, assertedAccessCount)
            assertAccessCountIfRequired(historicalOp, AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED,
                    assertedFlag, assertForeground, assertedAccessCount)
            if (assertForeground) {
                assertThat(historicalOp.getBackgroundAccessCount(
                        AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0)
            } else {
                assertThat(historicalOp.getForegroundAccessCount(
                        AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0)
            }
        }

        private fun assertAccessCountIfRequired(
            historicalOp: AppOpsManager.HistoricalOp,
            assertedFlag: Int,
            accessedFlag: Int,
            assertForeground: Boolean,
            assertedAccessCount: Int
        ) {
            if (assertedFlag != accessedFlag) {
                return
            }
            val accessCount: Long
            accessCount = if (assertForeground) {
                historicalOp.getForegroundAccessCount(accessedFlag)
            } else {
                historicalOp.getBackgroundAccessCount(accessedFlag)
            }
            assertThat(accessCount).isEqualTo(assertedAccessCount)
        }

        private fun findPackageOps(
            uid: Int,
            packageName: String,
            searchedList: List<AppOpsManager.PackageOps?>
        ): AppOpsManager.PackageOps? {
            return searchedList.stream()
                    .filter { packageOps: AppOpsManager.PackageOps? ->
                        packageOps!!.uid == uid && packageOps.packageName == packageName
                    }
                    .findAny()
                    .orElse(null)
        }

        private fun findPackageOps(
            uid: Int,
            packageName: String,
            historicalOps: AppOpsManager.HistoricalOps
        ): AppOpsManager.HistoricalPackageOps? {
            val uidOps = historicalOps.getUidOps(uid)
            return uidOps?.getPackageOps(packageName)
        }

        fun createAttributionContext(
            attributionTag: String?,
            receiverPackageName: String?,
            receiverAttributionTag: String?
        ): Context {
            val attributionParamsBuilder = ContextParams.Builder()
            if (attributionTag != null) {
                attributionParamsBuilder.setAttributionTag(attributionTag)
            }
            if (receiverPackageName != null) {
                val attributionSourceBuilder = AttributionSource.Builder(
                        context.packageManager.getPackageUid(receiverPackageName, 0))
                attributionSourceBuilder.setPackageName(receiverPackageName)
                if (receiverAttributionTag != null) {
                    attributionSourceBuilder.setAttributionTag(receiverAttributionTag)
                }
                var receiverAttributionSource = attributionSourceBuilder.build()
                SystemUtil.runWithShellPermissionIdentity {
                    receiverAttributionSource = context.getSystemService(
                            PermissionManager::class.java)!!.registerAttributionSource(
                            receiverAttributionSource)
                }
                attributionParamsBuilder.setNextAttributionSource(receiverAttributionSource)
            }
            return context.createContext(attributionParamsBuilder.build())
        }

        fun startBlamedAppActivity(): AttributionSource {
            val activityStatedLatch = CountDownLatch(1)
            val attributionSourceRef = AtomicReference<AttributionSource>()
            val intent = Intent()
            intent.setClassName(RECEIVER_PACKAGE_NAME, BRING_TO_FOREGROUND_ACTIVITY)
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
            intent.putExtra(REMOTE_CALLBACK, RemoteCallback {
                attributionSourceRef.set(it?.getParcelable(ATTRIBUTION_SOURCE))
                activityStatedLatch.countDown()
            })
            context.startActivity(intent)
            activityStatedLatch.await(ASYNC_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
            return attributionSourceRef.get()
        }

        private fun assumeNotTv() = assumeFalse(isTv)
        private fun assumeHasTelephony() = assumeTrue(isTel)
    }
}
