/*
 * 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.os.cts

import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_TOP_SLEEPING
import android.app.Instrumentation
import android.apphibernation.AppHibernationManager
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.permission.PermissionControllerManager
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_ELIGIBLE
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_UNKNOWN
import android.platform.test.annotations.AppModeFull
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION
import android.provider.Settings
import android.support.test.uiautomator.By
import android.support.test.uiautomator.BySelector
import android.support.test.uiautomator.UiDevice
import android.support.test.uiautomator.UiObject2
import android.support.test.uiautomator.UiScrollable
import android.support.test.uiautomator.UiSelector
import androidx.test.InstrumentationRegistry
import androidx.test.filters.SdkSuppress
import androidx.test.runner.AndroidJUnit4
import com.android.compatibility.common.util.DisableAnimationRule
import com.android.compatibility.common.util.FreezeRotationRule
import com.android.compatibility.common.util.SystemUtil
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
import com.android.compatibility.common.util.UiAutomatorUtils
import org.hamcrest.CoreMatchers
import org.hamcrest.Matchers
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

/**
 * Integration test for app hibernation.
 */
@RunWith(AndroidJUnit4::class)
@AppModeFull(reason = "Instant apps cannot access app hibernation")
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
class AppHibernationIntegrationTest {
    companion object {
        const val LOG_TAG = "AppHibernationIntegrationTest"
        const val WAIT_TIME_MS = 1000L
        const val TIMEOUT_TIME_MS = 5000L
        const val MAX_SCROLL_ATTEMPTS = 3
        const val TEST_UNUSED_THRESHOLD = 1L
        const val HIBERNATION_ENABLED_KEY = "app_hibernation_enabled"

        const val CMD_KILL = "am kill %s"
    }
    private val context: Context = InstrumentationRegistry.getTargetContext()
    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()

    private lateinit var packageManager: PackageManager
    private lateinit var permissionControllerManager: PermissionControllerManager
    private var oldHibernationValue: String? = null

    @get:Rule
    val disableAnimationRule = DisableAnimationRule()

    @get:Rule
    val freezeRotationRule = FreezeRotationRule()

    @Before
    fun setup() {
        oldHibernationValue = callWithShellPermissionIdentity {
            DeviceConfig.getProperty(NAMESPACE_APP_HIBERNATION, HIBERNATION_ENABLED_KEY)
        }
        runWithShellPermissionIdentity {
            DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, HIBERNATION_ENABLED_KEY, "true",
                false /* makeDefault */)
        }
        packageManager = context.packageManager
        permissionControllerManager =
            context.getSystemService(PermissionControllerManager::class.java)!!

        // Collapse notifications
        assertThat(
            runShellCommandOrThrow("cmd statusbar collapse"),
            CoreMatchers.equalTo(""))

        // Wake up the device
        runShellCommandOrThrow("input keyevent KEYCODE_WAKEUP")
        runShellCommandOrThrow("input keyevent 82")
    }

    @After
    fun cleanUp() {
        goHome()
        runWithShellPermissionIdentity {
            DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, HIBERNATION_ENABLED_KEY,
                oldHibernationValue, false /* makeDefault */)
        }
    }

    @Test
    fun testUnusedApp_getsForceStopped() {
        withUnusedThresholdMs(TEST_UNUSED_THRESHOLD) {
            withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
                // Use app
                startApp(APK_PACKAGE_NAME_S_APP)
                leaveApp(APK_PACKAGE_NAME_S_APP)
                killApp(APK_PACKAGE_NAME_S_APP)

                // Wait for the unused threshold time to pass
                Thread.sleep(TEST_UNUSED_THRESHOLD)

                // Run job
                runAppHibernationJob(context, LOG_TAG)

                // Verify
                val ai =
                    packageManager.getApplicationInfo(APK_PACKAGE_NAME_S_APP, 0 /* flags */)
                val stopped = ((ai.flags and ApplicationInfo.FLAG_STOPPED) != 0)
                assertTrue(stopped)

                if (hasFeatureTV()) {
                    // Skip checking unused apps screen because it may be unavailable on TV
                    return
                }
                openUnusedAppsNotification()
                waitFindObject(By.text(APK_PACKAGE_NAME_S_APP))
            }
        }
    }

    @Test
    fun testPreSVersionUnusedApp_doesntGetForceStopped() {
        assumeFalse(
            "TV may have different behaviour for Pre-S version apps",
            hasFeatureTV())
        withUnusedThresholdMs(TEST_UNUSED_THRESHOLD) {
            withApp(APK_PATH_R_APP, APK_PACKAGE_NAME_R_APP) {
                // Use app
                startApp(APK_PACKAGE_NAME_R_APP)
                leaveApp(APK_PACKAGE_NAME_R_APP)
                killApp(APK_PACKAGE_NAME_R_APP)

                // Wait for the unused threshold time to pass
                Thread.sleep(TEST_UNUSED_THRESHOLD)

                // Run job
                runAppHibernationJob(context, LOG_TAG)

                // Verify
                val ai =
                    packageManager.getApplicationInfo(APK_PACKAGE_NAME_R_APP, 0 /* flags */)
                val stopped = ((ai.flags and ApplicationInfo.FLAG_STOPPED) != 0)
                assertFalse(stopped)
            }
        }
    }

    @Test
    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
    fun testUnusedAppCount() {
        withUnusedThresholdMs(TEST_UNUSED_THRESHOLD) {
            withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
                // Use app
                startApp(APK_PACKAGE_NAME_S_APP)
                leaveApp(APK_PACKAGE_NAME_S_APP)
                killApp(APK_PACKAGE_NAME_S_APP)

                // Wait for the unused threshold time to pass
                Thread.sleep(TEST_UNUSED_THRESHOLD)

                // Run job
                runAppHibernationJob(context, LOG_TAG)

                // Verify unused app count pulled correctly
                val countDownLatch = CountDownLatch(1)
                var unusedAppCount = -1
                runWithShellPermissionIdentity {
                    permissionControllerManager.getUnusedAppCount({ r -> r.run() },
                        { res ->
                            unusedAppCount = res
                            countDownLatch.countDown()
                        })

                    assertTrue("Timed out waiting for unused app count",
                        countDownLatch.await(TIMEOUT_TIME_MS, TimeUnit.MILLISECONDS))
                    assertTrue("Expected non-zero unused app count but is $unusedAppCount",
                        unusedAppCount > 0)
                }
            }
        }
    }

    @Test
    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
    fun testGetHibernationEligibility_eligibleByDefault() {
        withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
            // Verify app is eligible for hibernation
            val countDownLatch = CountDownLatch(1)
            var hibernationEligibility = HIBERNATION_ELIGIBILITY_UNKNOWN
            runWithShellPermissionIdentity {
                permissionControllerManager.getHibernationEligibility(APK_PACKAGE_NAME_S_APP,
                    { r -> r.run() },
                    { res ->
                        hibernationEligibility = res
                        countDownLatch.countDown()
                    })

                assertTrue("Timed out waiting for hibernation eligibility",
                    countDownLatch.await(TIMEOUT_TIME_MS, TimeUnit.MILLISECONDS))
                assertEquals("Expected test app to be eligible for hibernation but wasn't.",
                    HIBERNATION_ELIGIBILITY_ELIGIBLE, hibernationEligibility)
            }
        }
    }

    @Test
    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
    fun testGetHibernationStatsForUser_getsStatsForIndividualPackages() {
        val appHibernationManager = context.getSystemService(AppHibernationManager::class.java)!!
        withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
            runWithShellPermissionIdentity {
                val stats =
                    appHibernationManager.getHibernationStatsForUser(
                        setOf(APK_PACKAGE_NAME_S_APP))

                assertNotNull(stats[APK_PACKAGE_NAME_S_APP])
                assertTrue(stats[APK_PACKAGE_NAME_S_APP]!!.diskBytesSaved >= 0)
            }
        }
    }

    @Test
    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
    fun testGetHibernationStatsForUser_getsStatsForAllPackages() {
        val appHibernationManager = context.getSystemService(AppHibernationManager::class.java)!!
        withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
            runWithShellPermissionIdentity {
                val stats = appHibernationManager.getHibernationStatsForUser()

                assertFalse("Expected non-empty list of hibernation stats", stats.isEmpty())
                assertTrue("Expected test package to be in list of returned savings but wasn't",
                    stats.containsKey(APK_PACKAGE_NAME_S_APP))
            }
        }
    }

    @Test
    fun testAppInfo_RemovePermissionsAndFreeUpSpaceToggleExists() {
        assumeFalse(
            "Remove permissions and free up space toggle may be unavailable on TV",
            hasFeatureTV())
        withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
            // Open app info
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
            val uri = Uri.fromParts("package", APK_PACKAGE_NAME_S_APP, null /* fragment */)
            intent.data = uri
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)

            waitForIdle()
            UiAutomatorUtils.getUiDevice()

            val packageManager = context.packageManager
            val settingsPackage = intent.resolveActivity(packageManager).packageName
            val res = packageManager.getResourcesForApplication(settingsPackage)
            val title = res.getString(
                res.getIdentifier("unused_apps_switch", "string", settingsPackage))

            // Settings can have multiple scrollable containers so all of them should be
            // searched.
            var toggleFound = UiDevice.getInstance(instrumentation)
                .findObject(UiSelector().text(title))
                .waitForExists(WAIT_TIME_MS)
            var i = 0
            var scrollableObject = UiScrollable(UiSelector().scrollable(true).instance(i))
            while (!toggleFound && scrollableObject.waitForExists(WAIT_TIME_MS)) {
                toggleFound = scrollableObject.scrollTextIntoView(title)
                scrollableObject = UiScrollable(UiSelector().scrollable(true).instance(++i))
            }

            assertTrue("Remove permissions and free up space toggle not found", toggleFound)
        }
    }

    private fun leaveApp(packageName: String) {
        eventually {
            goHome()
            SystemUtil.runWithShellPermissionIdentity {
                val packageImportance = context
                    .getSystemService(ActivityManager::class.java)!!
                    .getPackageImportance(packageName)
                assertThat(packageImportance, Matchers.greaterThan(IMPORTANCE_TOP_SLEEPING))
            }
        }
    }

    private fun killApp(packageName: String) {
        eventually {
            SystemUtil.runWithShellPermissionIdentity {
                runShellCommandOrThrow(String.format(CMD_KILL, packageName))
                val packageImportance = context
                    .getSystemService(ActivityManager::class.java)!!
                    .getPackageImportance(packageName)
                assertThat(packageImportance, Matchers.equalTo(IMPORTANCE_GONE))
            }
        }
    }

    private fun waitFindObject(selector: BySelector): UiObject2 {
        return waitFindObject(instrumentation.uiAutomation, selector)
    }
}
