/*
 * Copyright (C) 2020 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.permission4.cts

import android.Manifest
import android.app.Instrumentation
import android.app.UiAutomation
import android.app.compat.CompatChanges
import android.content.AttributionSource
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.hardware.camera2.CameraManager
import android.os.Build
import android.os.Process
import android.os.SystemClock
import android.permission.PermissionManager
import android.provider.DeviceConfig
import android.provider.Settings
import android.safetycenter.SafetyCenterManager
import android.server.wm.WindowManagerStateHelper
import android.support.test.uiautomator.By
import android.support.test.uiautomator.BySelector
import android.support.test.uiautomator.StaleObjectException
import android.support.test.uiautomator.UiDevice
import android.support.test.uiautomator.UiObject2
import android.support.test.uiautomator.UiSelector
import androidx.annotation.RequiresApi
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.DisableAnimationRule
import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runShellCommand
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.android.compatibility.common.util.UiAutomatorUtils
import org.junit.After
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test

private const val APP_LABEL = "CtsCameraMicAccess"
private const val APP_PKG = "android.permission4.cts.appthataccessescameraandmic"
private const val SHELL_PKG = "com.android.shell"
private const val USE_CAMERA = "use_camera"
private const val USE_MICROPHONE = "use_microphone"
private const val USE_HOTWORD = "use_hotword"
private const val INTENT_ACTION = "test.action.USE_CAMERA_OR_MIC"
private const val PRIVACY_CHIP_ID = "com.android.systemui:id/privacy_chip"
private const val CAR_MIC_PRIVACY_CHIP_ID = "com.android.systemui:id/mic_privacy_chip"
private const val CAR_CAMERA_PRIVACY_CHIP_ID = "com.android.systemui:id/camera_privacy_chip"
private const val PRIVACY_ITEM_ID = "com.android.systemui:id/privacy_item"
private const val SAFETY_CENTER_ITEM_ID = "com.android.permissioncontroller:id/parent_card_view"
private const val INDICATORS_FLAG = "camera_mic_icons_enabled"
private const val PERMISSION_INDICATORS_NOT_PRESENT = 162547999L
private const val IDLE_TIMEOUT_MILLIS: Long = 1000
private const val UNEXPECTED_TIMEOUT_MILLIS = 1000
private const val TIMEOUT_MILLIS: Long = 20000
private const val TV_MIC_INDICATOR_WINDOW_TITLE = "MicrophoneCaptureIndicator"
private const val MIC_LABEL_NAME = "microphone_toggle_label_qs"
private const val CAMERA_LABEL_NAME = "camera_toggle_label_qs"

class CameraMicIndicatorsPermissionTest {
    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
    private val context: Context = instrumentation.context
    private val uiAutomation: UiAutomation = instrumentation.uiAutomation
    private val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
    private val packageManager: PackageManager = context.packageManager
    private val permissionManager: PermissionManager =
        context.getSystemService(PermissionManager::class.java)!!

    private val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
    private val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
    private val micLabel = getPermissionControllerString(MIC_LABEL_NAME)
    private val cameraLabel = getPermissionControllerString(CAMERA_LABEL_NAME)
    private var wasEnabled = false
    private var isScreenOn = false
    private var screenTimeoutBeforeTest: Long = 0L

    @get:Rule
    val disableAnimationRule = DisableAnimationRule()

    companion object {
        const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled"
        const val DELAY_MILLIS = 3000L
    }

    private val safetyCenterEnabled = callWithShellPermissionIdentity {
        DeviceConfig.getString(DeviceConfig.NAMESPACE_PRIVACY,
            SAFETY_CENTER_ENABLED, false.toString())
    }

    @Before
    fun setUp() {
        runWithShellPermissionIdentity {
            screenTimeoutBeforeTest = Settings.System.getLong(
                context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT
            )
            Settings.System.putLong(
                context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT, 1800000L
            )
            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
                SAFETY_CENTER_ENABLED, false.toString(), false)
        }

        if (!isScreenOn) {
            uiDevice.wakeUp()
            runShellCommand(instrumentation, "wm dismiss-keyguard")
            Thread.sleep(DELAY_MILLIS)
            isScreenOn = true
        }
        uiDevice.findObject(By.text("Close"))?.click()
        wasEnabled = setIndicatorsEnabledStateIfNeeded(true)
        // If the change Id is not present, then isChangeEnabled will return true. To bypass this,
        // the change is set to "false" if present.
        assumeFalse("feature not present on this device", callWithShellPermissionIdentity {
            CompatChanges.isChangeEnabled(PERMISSION_INDICATORS_NOT_PRESENT, Process.SYSTEM_UID)
        })
    }

    private fun setIndicatorsEnabledStateIfNeeded(shouldBeEnabled: Boolean): Boolean {
        var currentlyEnabled = false
        runWithShellPermissionIdentity {
            currentlyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                INDICATORS_FLAG, true)
            if (currentlyEnabled != shouldBeEnabled) {
                DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY, INDICATORS_FLAG,
                    shouldBeEnabled.toString(), false)
            }
        }
        return currentlyEnabled
    }

    @After
    fun tearDown() {
        if (!wasEnabled) {
            setIndicatorsEnabledStateIfNeeded(false)
        }
        runWithShellPermissionIdentity {
            Settings.System.putLong(
                context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT,
                screenTimeoutBeforeTest
            )
        }
        changeSafetyCenterFlag(safetyCenterEnabled)
        if (!isTv) {
            pressBack()
            pressBack()
        }
        pressHome()
        pressHome()
        Thread.sleep(DELAY_MILLIS)
    }

    private fun openApp(useMic: Boolean, useCamera: Boolean, useHotword: Boolean) {
        context.startActivity(Intent(INTENT_ACTION).apply {
            putExtra(USE_CAMERA, useCamera)
            putExtra(USE_MICROPHONE, useMic)
            putExtra(USE_HOTWORD, useHotword)
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        })
    }

    @Test
    fun testCameraIndicator() {
        val manager = context.getSystemService(CameraManager::class.java)!!
        assumeTrue(manager.cameraIdList.isNotEmpty())
        changeSafetyCenterFlag(false.toString())
        testCameraAndMicIndicator(useMic = false, useCamera = true)
    }

    @Test
    fun testMicIndicator() {
        changeSafetyCenterFlag(false.toString())
        testCameraAndMicIndicator(useMic = true, useCamera = false)
    }

    @Test
    fun testHotwordIndicatorBehavior() {
        changeSafetyCenterFlag(false.toString())
        testCameraAndMicIndicator(useMic = false, useCamera = false, useHotword = true)
    }

    @Test
    fun testChainUsageWithOtherUsage() {
        // TV has only the mic icon
        assumeFalse(isTv)
        // Car has separate panels for mic and camera for now.
        // TODO(b/218788634): enable this test for car once the new camera indicator is implemented.
        assumeFalse(isCar)
        changeSafetyCenterFlag(false.toString())
        testCameraAndMicIndicator(useMic = false, useCamera = true, chainUsage = true)
    }

    @Test
    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
    fun testSafetyCenterCameraIndicator() {
        assumeFalse(isTv)
        assumeFalse(isCar)
        val manager = context.getSystemService(CameraManager::class.java)!!
        assumeTrue(manager.cameraIdList.isNotEmpty())
        changeSafetyCenterFlag(true.toString())
        assumeSafetyCenterEnabled()
        testCameraAndMicIndicator(useMic = false, useCamera = true, safetyCenterEnabled = true)
    }

    @Test
    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
    fun testSafetyCenterMicIndicator() {
        assumeFalse(isTv)
        assumeFalse(isCar)
        changeSafetyCenterFlag(true.toString())
        assumeSafetyCenterEnabled()
        testCameraAndMicIndicator(useMic = true, useCamera = false, safetyCenterEnabled = true)
    }

    @Test
    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
    fun testSafetyCenterHotwordIndicatorBehavior() {
        assumeFalse(isTv)
        assumeFalse(isCar)
        changeSafetyCenterFlag(true.toString())
        assumeSafetyCenterEnabled()
        testCameraAndMicIndicator(
            useMic = false,
            useCamera = false,
            useHotword = true,
            safetyCenterEnabled = true
        )
    }

    @Test
    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
    fun testSafetyCenterChainUsageWithOtherUsage() {
        assumeFalse(isTv)
        assumeFalse(isCar)
        changeSafetyCenterFlag(true.toString())
        assumeSafetyCenterEnabled()
        testCameraAndMicIndicator(
            useMic = false,
            useCamera = true,
            chainUsage = true,
            safetyCenterEnabled = true
        )
    }

    private fun testCameraAndMicIndicator(
        useMic: Boolean,
        useCamera: Boolean,
        useHotword: Boolean = false,
        chainUsage: Boolean = false,
        safetyCenterEnabled: Boolean = false
    ) {
        var chainAttribution: AttributionSource? = null
        openApp(useMic, useCamera, useHotword)
        try {
            eventually {
                val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
                assertTrue("View with text $APP_LABEL not found", appView.exists())
            }
            if (chainUsage) {
                chainAttribution = createChainAttribution()
                runWithShellPermissionIdentity {
                    val ret = permissionManager.checkPermissionForStartDataDelivery(
                        Manifest.permission.RECORD_AUDIO, chainAttribution!!, "")
                    Assert.assertEquals(PermissionManager.PERMISSION_GRANTED, ret)
                }
            }

            if (isTv) {
                assertTvIndicatorsShown(useMic, useCamera, useHotword)
            } else if (isCar) {
                assertCarIndicatorsShown(useMic, useCamera, useHotword, chainUsage)
            } else {
                // Hotword gets remapped to RECORD_AUDIO on handheld, so handheld should show a mic
                // indicator
                uiDevice.openQuickSettings()
                assertPrivacyChipAndIndicatorsPresent(
                    useMic || useHotword,
                    useCamera,
                    chainUsage,
                    safetyCenterEnabled
                )
            }
        } finally {
            if (chainAttribution != null) {
                permissionManager.finishDataDelivery(Manifest.permission.RECORD_AUDIO,
                chainAttribution!!)
            }
        }
    }

    private fun assertTvIndicatorsShown(useMic: Boolean, useCamera: Boolean, useHotword: Boolean) {
        if (useMic || useHotword) {
            val found = WindowManagerStateHelper()
                .waitFor("Waiting for the mic indicator window to come up") {
                    it.containsWindow(TV_MIC_INDICATOR_WINDOW_TITLE) &&
                    it.isWindowVisible(TV_MIC_INDICATOR_WINDOW_TITLE)
                }
            if (useMic) {
                assertTrue("Did not find chip", found)
            } else {
                assertFalse("Found chip, but did not expect to", found)
            }
        }
        if (useCamera) {
            // There is no camera indicator on TVs.
        }
    }

    private fun assertCarIndicatorsShown(
        useMic: Boolean,
        useCamera: Boolean,
        useHotword: Boolean,
        chainUsage: Boolean
    ) {
        eventually {
            // Ensure the privacy chip is present (or not)
            var micPrivacyChip = uiDevice.findObject(By.res(CAR_MIC_PRIVACY_CHIP_ID))
            var cameraPrivacyChip = uiDevice.findObject(By.res(CAR_CAMERA_PRIVACY_CHIP_ID))
            if (useMic) {
                assertNotNull("Did not find mic chip", micPrivacyChip)
                // Click to chip to show the panel.
                micPrivacyChip.click()
            } else if (useCamera) {
                assertNotNull("Did not find camera chip", cameraPrivacyChip)
                // Click to chip to show the panel.
                cameraPrivacyChip.click()
            } else if (useHotword) {
                assertNull("Found mic chip, but did not expect to", micPrivacyChip)
                assertNull("Found camera chip, but did not expect to", cameraPrivacyChip)
            }
        }

        eventually {
            if (chainUsage) {
                // Not applicable for car
                assertChainMicAndOtherCameraUsed(false)
                return@eventually
            }
            if (useHotword) {
                // There should be no privacy panel when using hot word
                val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
                assertFalse("View with text $micLabel found, but did not expect to",
                    micLabelView.exists())
                val cameraLabelView = uiDevice.findObject(UiSelector().textContains(cameraLabel))
                assertFalse("View with text $cameraLabel found, but did not expect to",
                    cameraLabelView.exists())
                val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
                assertFalse("View with text $APP_LABEL found, but did not expect to",
                    appView.exists())
            } else if (useMic) {
                // There should be a mic privacy panel after mic privacy chip is clicked
                val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
                assertTrue("View with text $micLabel not found", micLabelView.exists())
                val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
                assertTrue("View with text $APP_LABEL not found", appView.exists())
            } else if (useCamera) {
                // There should be a camera privacy panel after camera privacy chip is clicked
                val cameraLabelView = uiDevice.findObject(UiSelector().textContains(cameraLabel))
                assertTrue("View with text $cameraLabel not found", cameraLabelView.exists())
                val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
                assertTrue("View with text $APP_LABEL not found", appView.exists())
            }
        }
    }

    private fun assertPrivacyChipAndIndicatorsPresent(
        useMic: Boolean,
        useCamera: Boolean,
        chainUsage: Boolean,
        safetyCenterEnabled: Boolean = false
    ) {
        // Ensure the privacy chip is present
        eventually {
            val privacyChip = uiDevice.findObject(UiSelector().resourceId(PRIVACY_CHIP_ID))
            assertTrue("view with id $PRIVACY_CHIP_ID not found", privacyChip.exists())
            privacyChip.click()
        }

        eventually {
            if (chainUsage) {
                assertChainMicAndOtherCameraUsed(safetyCenterEnabled)
                return@eventually
            }
            if (useMic) {
                var iconView = if (safetyCenterEnabled) {
                    waitFindObjectOrNull(By.text(micLabel))
                } else {
                    uiDevice.findObject(UiSelector().descriptionContains(micLabel))
                }
                assertNotNull("View with description $micLabel not found", iconView)
            }
            if (useCamera) {
                var iconView = if (safetyCenterEnabled) {
                    waitFindObjectOrNull(By.text(cameraLabel))
                } else {
                    uiDevice.findObject(UiSelector().descriptionContains(cameraLabel))
                }
                assertNotNull("View with text $APP_LABEL not found", iconView)
            }
            var appView = waitFindObjectOrNull(By.textContains(APP_LABEL))
            assertNotNull("View with text $APP_LABEL not found", appView)
            if (safetyCenterEnabled) {
                assertTrue("Did not find safety center views",
                    uiDevice.findObjects(By.res(SAFETY_CENTER_ITEM_ID)).size > 0)
            }
        }
    }

    private fun createChainAttribution(): AttributionSource? {
        var attrSource: AttributionSource? = null
        runWithShellPermissionIdentity {
            try {
                val appUid = packageManager.getPackageUid(APP_PKG, 0)
                val childAttribution = AttributionSource(appUid, APP_PKG, null)
                val attribution = AttributionSource(Process.myUid(), context.packageName, null,
                    null, permissionManager.registerAttributionSource(childAttribution))
                attrSource = permissionManager.registerAttributionSource(attribution)
            } catch (e: PackageManager.NameNotFoundException) {
                Assert.fail("Expected to find a UID for $APP_LABEL")
            }
        }
        return attrSource
    }

    private fun assertChainMicAndOtherCameraUsed(safetyCenterEnabled: Boolean) {
        val shellLabel = try {
            context.packageManager.getApplicationInfo(SHELL_PKG, 0)
                .loadLabel(context.packageManager).toString()
        } catch (e: PackageManager.NameNotFoundException) {
            "Did not find shell package"
        }

        if (safetyCenterEnabled) {
            var micView = waitFindObjectOrNull(By.text(micLabel))
            assertNotNull("View with text $micLabel not found", micView)
            var camView = waitFindObjectOrNull(By.text(cameraLabel))
            assertNotNull("View with text $cameraLabel not found", camView)
            var shellView = waitFindObjectOrNull(By.textContains(shellLabel))
            assertNotNull("View with text $shellLabel not found", shellView)
        } else {
            val usageViews = uiDevice.findObjects(By.res(PRIVACY_ITEM_ID))
            assertEquals("Expected two usage views", 2, usageViews.size)
            val appViews = uiDevice.findObjects(By.textContains(APP_LABEL))
            assertEquals("Expected two $APP_LABEL view", 2, appViews.size)
            val shellView = uiDevice.findObjects(By.textContains(shellLabel))
            assertEquals("Expected only one shell view", 1, shellView.size)
        }
    }

    private fun pressBack() {
        uiDevice.pressBack()
        waitForIdle()
    }

    private fun pressHome() {
        uiDevice.pressHome()
        waitForIdle()
    }

    private fun waitForIdle() =
        uiAutomation.waitForIdle(IDLE_TIMEOUT_MILLIS, TIMEOUT_MILLIS)

    private fun changeSafetyCenterFlag(safetyCenterEnabled: String) {
        runWithShellPermissionIdentity {
            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
                SAFETY_CENTER_ENABLED, safetyCenterEnabled, false)
        }
    }

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    private fun assumeSafetyCenterEnabled() {
        val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
        val isSafetyCenterEnabled: Boolean = runWithShellPermissionIdentity<Boolean> {
            safetyCenterManager.isSafetyCenterEnabled
        }
        assumeTrue(isSafetyCenterEnabled)
    }

    protected fun waitFindObjectOrNull(selector: BySelector): UiObject2? {
        waitForIdle()
        return findObjectWithRetry({ t -> UiAutomatorUtils.waitFindObjectOrNull(selector, t) })
    }

    private fun findObjectWithRetry(
        automatorMethod: (timeoutMillis: Long) -> UiObject2?,
        timeoutMillis: Long = TIMEOUT_MILLIS
    ): UiObject2? {
        waitForIdle()
        val startTime = SystemClock.elapsedRealtime()
        return try {
            automatorMethod(timeoutMillis)
        } catch (e: StaleObjectException) {
            val remainingTime = timeoutMillis - (SystemClock.elapsedRealtime() - startTime)
            if (remainingTime <= 0) {
                throw e
            }
            automatorMethod(remainingTime)
        }
    }

    private fun getPermissionControllerString(resourceName: String): String {
        val permissionControllerPkg = context.packageManager.permissionControllerPackageName
        try {
            val permissionControllerContext =
                context.createPackageContext(permissionControllerPkg, 0)
            val resourceId =
                permissionControllerContext.resources.getIdentifier(
                    resourceName, "string", "com.android.permissioncontroller")
            return permissionControllerContext.getString(resourceId)
        } catch (e: PackageManager.NameNotFoundException) {
            throw RuntimeException(e)
        }
    }
}