1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm.test 18 19 import com.android.internal.util.test.SystemPreparer 20 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner 21 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test 22 import com.google.common.truth.Truth.assertThat 23 import org.junit.After 24 import org.junit.Before 25 import org.junit.ClassRule 26 import org.junit.Rule 27 import org.junit.Test 28 import org.junit.rules.RuleChain 29 import org.junit.rules.TemporaryFolder 30 import org.junit.runner.RunWith 31 32 @RunWith(DeviceJUnit4ClassRunner::class) 33 class OverlayPathsUninstallSystemUpdatesTest : BaseHostJUnit4Test() { 34 35 companion object { 36 private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app" 37 private const val VERSION_ONE = "PackageManagerTestAppVersion1.apk" 38 private const val VERSION_TWO = "PackageManagerTestAppVersion2.apk" 39 40 @get:ClassRule 41 val deviceRebootRule = SystemPreparer.TestRuleDelegate(true) 42 } 43 44 private val tempFolder = TemporaryFolder() 45 private val preparer: SystemPreparer = SystemPreparer(tempFolder, 46 SystemPreparer.RebootStrategy.FULL, deviceRebootRule, true) { this.device } 47 48 @Rule 49 @JvmField 50 val rules = RuleChain.outerRule(tempFolder).around(preparer)!! 51 private val filePath = HostUtils.makePathForApk("PackageManagerTestApp.apk", Partition.PRODUCT) 52 53 @Before 54 @After 55 fun removeApk() { 56 device.uninstallPackage(TEST_PKG_NAME) 57 } 58 59 @Test 60 fun verify() { 61 // First, push a system app to the device and then update it so there's a data variant 62 preparer.pushResourceFile(VERSION_ONE, filePath.toString()) 63 .reboot() 64 65 val versionTwoFile = HostUtils.copyResourceToHostFile(VERSION_TWO, tempFolder.newFile()) 66 67 assertThat(device.installPackage(versionTwoFile, true)).isNull() 68 69 device.executeShellCommand( 70 "cmd overlay fabricate --target-name TestResources" + 71 " --target $TEST_PKG_NAME" + 72 " --name UninstallSystemUpdatesTest" + 73 " $TEST_PKG_NAME:color/overlay_test 0x1C 0xFFFFFFFF" 74 ) 75 76 device.executeShellCommand( 77 "cmd overlay enable --user 0 com.android.shell:UninstallSystemUpdatesTest" 78 ) 79 80 fun verifyValueOverlaid() { 81 assertThat(device.executeShellCommand( 82 "cmd overlay lookup --user 0 $TEST_PKG_NAME $TEST_PKG_NAME:color/overlay_test" 83 ).trim()).isEqualTo("#ffffffff") 84 } 85 86 verifyValueOverlaid() 87 88 assertThat( 89 device.executeShellCommand("pm uninstall-system-updates $TEST_PKG_NAME" 90 ).trim()).endsWith("Success") 91 92 // Wait for paths to re-propagate. This doesn't do a retry loop in case the path clear also 93 // has some latency. There must be some minimum wait time for the paths to settle, and then 94 // a wait time for the paths to re-propagate. Rather than complicate the logic, just wait 95 // a long enough time for both events to occur. 96 Thread.sleep(5000) 97 98 verifyValueOverlaid() 99 } 100 } 101