/*
 * Copyright (C) 2018 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.packageinstaller.nopermission.cts

import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager;
import android.content.pm.PackageInstaller
import android.content.pm.PackageInstaller.EXTRA_STATUS
import android.content.pm.PackageInstaller.STATUS_FAILURE_INVALID
import android.os.Build
import android.platform.test.annotations.AppModeFull
import androidx.test.InstrumentationRegistry
import androidx.test.filters.MediumTest
import androidx.test.runner.AndroidJUnit4
import android.support.test.uiautomator.By
import android.support.test.uiautomator.UiDevice
import android.support.test.uiautomator.Until
import androidx.core.content.FileProvider
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.model.Statement
import org.junit.runner.Description
import org.junit.Rule
import org.junit.rules.TestRule
import org.junit.AssumptionViolatedException

import java.io.File
import java.lang.IllegalArgumentException

private const val TEST_APK_NAME = "CtsEmptyTestApp.apk"
private const val TEST_APK_PACKAGE_NAME = "android.packageinstaller.emptytestapp.cts"
private const val TEST_APK_EXTERNAL_LOCATION = "/data/local/tmp/cts/nopermission"
private const val CONTENT_AUTHORITY = "android.packageinstaller.nopermission.cts.fileprovider"
private const val PACKAGE_INSTALLER_PACKAGE_NAME = "com.android.packageinstaller"
private const val INSTALL_CONFIRM_TEXT_ID = "install_confirm_question"
private const val WM_DISMISS_KEYGUARD_COMMAND = "wm dismiss-keyguard"

private const val ACTION = "NoPermissionTests.install_cb"

private const val WAIT_FOR_UI_TIMEOUT = 5000L

@RunWith(AndroidJUnit4::class)
@MediumTest
@AppModeFull
class NoPermissionTests {
    private var context = InstrumentationRegistry.getTargetContext()
    private var pm = context.packageManager
    private var packageName = context.packageName
    private var apkFile = File(context.filesDir, TEST_APK_NAME)
    private var uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
    private var isWatch: Boolean = pm.hasSystemFeature(PackageManager.FEATURE_WATCH)

    private val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val status = intent.getIntExtra(EXTRA_STATUS, STATUS_FAILURE_INVALID)

            if (status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
                val activityIntent = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)
                activityIntent!!.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                context.startActivity(activityIntent)
            }
        }
    }

    @get:Rule
    val testRule: TestRule = object :TestRule {
        override fun apply(base: Statement, description: Description?)
                = NewStatement(base)
        inner class NewStatement(private val base: Statement) : Statement() {
            @Throws(Throwable::class)
            override fun evaluate() {
                if (isWatch) {
                    throw AssumptionViolatedException("Install/uninstall feature is not supported on WearOs");
                }
                base.evaluate()
            }
        }
    }

    @Before
    fun wakeUpScreen() {
        if (!uiDevice.isScreenOn) {
            uiDevice.wakeUp()
        }
        uiDevice.executeShellCommand(WM_DISMISS_KEYGUARD_COMMAND)
    }

    @Before
    fun copyTestApk() {
        File(TEST_APK_EXTERNAL_LOCATION, TEST_APK_NAME).copyTo(target = apkFile, overwrite = true)
    }

    @Before
    fun registerInstallResultReceiver() {
        context.registerReceiver(receiver, IntentFilter(ACTION),
                Context.RECEIVER_EXPORTED_UNAUDITED)
    }

    @Before
    fun waitForUIIdle() {
        uiDevice.waitForIdle()
    }

    private fun launchPackageInstallerViaIntent() {
        val intent = Intent(Intent.ACTION_INSTALL_PACKAGE)
        intent.data = FileProvider.getUriForFile(context, CONTENT_AUTHORITY, apkFile)
        intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK
        context.startActivity(intent)
    }

    private fun launchPackageInstallerViaSession() {
        val pi = pm.packageInstaller

        // Create session
        val sessionId = pi.createSession(PackageInstaller.SessionParams(
                PackageInstaller.SessionParams.MODE_FULL_INSTALL))
        val session = pi.openSession(sessionId)!!

        // Write data to session
        File(TEST_APK_EXTERNAL_LOCATION, TEST_APK_NAME).inputStream().use { fileOnDisk ->
            session.openWrite(TEST_APK_NAME, 0, -1).use { sessionFile ->
                fileOnDisk.copyTo(sessionFile)
            }
        }

        // Commit session
        val pendingIntent = PendingIntent.getBroadcast(context, 0, Intent(ACTION),
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
        session.commit(pendingIntent.intentSender)
    }

    private fun assertInstallSucceeded(errorMessage: String) {
        val selector = By.res(PACKAGE_INSTALLER_PACKAGE_NAME, INSTALL_CONFIRM_TEXT_ID)
        assertTrue(errorMessage, uiDevice.wait(Until.hasObject(selector), WAIT_FOR_UI_TIMEOUT))
        uiDevice.pressBack()
    }

    private fun assertInstallFailed(errorMessage: String) {
        val selector = By.res(PACKAGE_INSTALLER_PACKAGE_NAME, INSTALL_CONFIRM_TEXT_ID)
        assertFalse(errorMessage, uiDevice.wait(Until.hasObject(selector), WAIT_FOR_UI_TIMEOUT))
        uiDevice.pressBack()
    }

    @Test
    fun noPermissionsTestIntent() {
        launchPackageInstallerViaIntent()

        if (pm.getPackageInfo(packageName, 0).applicationInfo.targetSdkVersion
                >= Build.VERSION_CODES.O) {
            assertInstallFailed("Package Installer UI should not appear")
        } else {
            assertInstallSucceeded("Package Installer UI should appear")
        }
    }

    @Test
    fun noPermissionsTestSession() {
        launchPackageInstallerViaSession()

        if (pm.getPackageInfo(packageName, 0).applicationInfo.targetSdkVersion
                >= Build.VERSION_CODES.O) {
            assertInstallFailed("Package Installer UI should not appear")
        } else {
            assertInstallSucceeded("Package Installer UI should appear")
        }
    }

    @After
    fun unregisterInstallResultReceiver() {
        try {
            context.unregisterReceiver(receiver)
        } catch (ignored: IllegalArgumentException) {
        }
    }

    @After
    fun uninstallTestPackage() {
        uiDevice.executeShellCommand("pm uninstall $TEST_APK_PACKAGE_NAME")
    }
}
