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