1 /*
2  * Copyright (C) 2021 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
18 
19 import android.os.Build
20 import com.android.server.testutils.any
21 import com.android.server.testutils.spy
22 import com.android.server.testutils.whenever
23 import com.google.common.truth.Truth.assertThat
24 import org.junit.Before
25 import org.junit.Rule
26 import org.junit.Test
27 import org.junit.runner.RunWith
28 import org.junit.runners.JUnit4
29 import org.mockito.Mockito.eq
30 import org.mockito.Mockito.times
31 import org.mockito.Mockito.verify
32 import kotlin.test.assertFailsWith
33 
34 @RunWith(JUnit4::class)
35 class PackageFreezerTest {
36 
37     companion object {
38         const val TEST_PACKAGE = "com.android.test.package"
39         const val TEST_REASON = "test reason"
40         const val TEST_EXIT_REASON = 1
41         const val TEST_USER_ID = 0
42     }
43 
44     @Rule
45     @JvmField
46     val rule = MockSystemRule()
47 
48     lateinit var pms: PackageManagerService
49 
createPackageManagerServicenull50     private fun createPackageManagerService(vararg stageExistingPackages: String):
51             PackageManagerService {
52         stageExistingPackages.forEach {
53             rule.system().stageScanExistingPackage(it, 1L,
54                 rule.system().dataAppDirectory)
55         }
56         var pms = PackageManagerService(rule.mocks().injector,
57             false /*factoryTest*/,
58             MockSystem.DEFAULT_VERSION_INFO.fingerprint,
59             false /*isEngBuild*/,
60             false /*isUserDebugBuild*/,
61             Build.VERSION_CODES.CUR_DEVELOPMENT,
62             Build.VERSION.INCREMENTAL)
63         rule.system().validateFinalState()
64         return pms
65     }
66 
frozenMessagenull67     private fun frozenMessage(packageName: String) = "Package $packageName is currently frozen!"
68 
69     private fun <T : Throwable> assertThrowContainsMessage(
70         exceptionClass: kotlin.reflect.KClass<T>,
71         message: String,
72         block: () -> Unit
73     ) {
74         assertThat(assertFailsWith(exceptionClass, block).message).contains(message)
75     }
76 
checkPackageStartablenull77     private fun checkPackageStartable() {
78         pms.checkPackageStartable(pms.snapshotComputer(), TEST_PACKAGE, TEST_USER_ID)
79     }
80 
81     @Before
82     @Throws(Exception::class)
setupnull83     fun setup() {
84         rule.system().stageNominalSystemState()
85         pms = spy(createPackageManagerService(TEST_PACKAGE))
86         whenever(pms.killApplication(any(), any(), any(), any(), any()))
87     }
88 
89     @Test
freezePackagenull90     fun freezePackage() {
91         val freezer = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms,
92                 TEST_EXIT_REASON, null /* request */)
93         verify(pms, times(1))
94             .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON),
95                     eq(TEST_EXIT_REASON))
96 
97         assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) {
98             checkPackageStartable()
99         }
100 
101         freezer.close()
102         checkPackageStartable()
103     }
104 
105     @Test
freezePackage_twicenull106     fun freezePackage_twice() {
107         val freezer1 = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms,
108                 TEST_EXIT_REASON, null  /* request */)
109         val freezer2 = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms,
110                 TEST_EXIT_REASON, null  /* request */)
111         verify(pms, times(2))
112             .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON),
113                     eq(TEST_EXIT_REASON))
114 
115         assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) {
116             checkPackageStartable()
117         }
118 
119         freezer1.close()
120         assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) {
121             checkPackageStartable()
122         }
123 
124         freezer2.close()
125         checkPackageStartable()
126     }
127 
128     @Test
freezePackage_withoutClosingnull129     fun freezePackage_withoutClosing() {
130         var freezer: PackageFreezer? = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms,
131                 TEST_EXIT_REASON, null  /* request */)
132         verify(pms, times(1))
133             .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON),
134                     eq(TEST_EXIT_REASON))
135 
136         assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) {
137             checkPackageStartable()
138         }
139 
140         freezer = null
141         System.gc()
142         System.runFinalization()
143 
144         checkPackageStartable()
145     }
146 }
147