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 50 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 67 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 77 private fun checkPackageStartable() { 78 pms.checkPackageStartable(pms.snapshotComputer(), TEST_PACKAGE, TEST_USER_ID) 79 } 80 81 @Before 82 @Throws(Exception::class) 83 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 90 fun freezePackage() { 91 val freezer = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms, TEST_EXIT_REASON) 92 verify(pms, times(1)) 93 .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON), 94 eq(TEST_EXIT_REASON)) 95 96 assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) { 97 checkPackageStartable() 98 } 99 100 freezer.close() 101 checkPackageStartable() 102 } 103 104 @Test 105 fun freezePackage_twice() { 106 val freezer1 = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms, 107 TEST_EXIT_REASON) 108 val freezer2 = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms, 109 TEST_EXIT_REASON) 110 verify(pms, times(2)) 111 .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON), 112 eq(TEST_EXIT_REASON)) 113 114 assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) { 115 checkPackageStartable() 116 } 117 118 freezer1.close() 119 assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) { 120 checkPackageStartable() 121 } 122 123 freezer2.close() 124 checkPackageStartable() 125 } 126 127 @Test 128 fun freezePackage_withoutClosing() { 129 var freezer: PackageFreezer? = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms, 130 TEST_EXIT_REASON) 131 verify(pms, times(1)) 132 .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON), 133 eq(TEST_EXIT_REASON)) 134 135 assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) { 136 checkPackageStartable() 137 } 138 139 freezer = null 140 System.gc() 141 System.runFinalization() 142 143 checkPackageStartable() 144 } 145 } 146