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.content.Context 20 import android.os.Build 21 import android.os.Handler 22 import android.os.PowerManager 23 import android.provider.DeviceConfig 24 import android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION 25 import android.testing.AndroidTestingRunner 26 import android.testing.TestableLooper 27 import android.testing.TestableLooper.RunWithLooper 28 import com.android.server.apphibernation.AppHibernationManagerInternal 29 import com.android.server.apphibernation.AppHibernationService 30 import com.android.server.extendedtestutils.wheneverStatic 31 import com.android.server.testutils.whenever 32 import org.junit.Assert 33 import org.junit.Assert.assertFalse 34 import org.junit.Assert.assertTrue 35 import org.junit.Before 36 import org.junit.Rule 37 import org.junit.Test 38 import org.junit.runner.RunWith 39 import org.mockito.Mock 40 import org.mockito.Mockito.verify 41 import org.mockito.MockitoAnnotations 42 43 @RunWith(AndroidTestingRunner::class) 44 @RunWithLooper 45 class PackageManagerServiceHibernationTests { 46 47 companion object { 48 val TEST_PACKAGE_NAME = "test.package" 49 val TEST_PACKAGE_2_NAME = "test.package2" 50 val TEST_USER_ID = 0 51 52 val KEY_APP_HIBERNATION_ENABLED = "app_hibernation_enabled" 53 } 54 55 @Rule 56 @JvmField 57 val rule = MockSystemRule() 58 59 @Mock 60 lateinit var appHibernationManager: AppHibernationManagerInternal 61 @Mock 62 lateinit var powerManager: PowerManager 63 64 @Before 65 @Throws(Exception::class) 66 fun setup() { 67 MockitoAnnotations.initMocks(this) 68 wheneverStatic { DeviceConfig.getBoolean( 69 NAMESPACE_APP_HIBERNATION, KEY_APP_HIBERNATION_ENABLED, false) }.thenReturn(true) 70 AppHibernationService.sIsServiceEnabled = true 71 rule.system().stageNominalSystemState() 72 whenever(rule.mocks().injector.getLocalService(AppHibernationManagerInternal::class.java)) 73 .thenReturn(appHibernationManager) 74 whenever(rule.mocks().injector.handler) 75 .thenReturn(Handler(TestableLooper.get(this).looper)) 76 val injector = object : PackageDexOptimizer.Injector { 77 override fun getAppHibernationManagerInternal(): AppHibernationManagerInternal { 78 return appHibernationManager 79 } 80 81 override fun getPowerManager(context: Context?): PowerManager { 82 return powerManager 83 } 84 } 85 val packageDexOptimizer = PackageDexOptimizer( 86 injector, 87 rule.mocks().installer, 88 rule.mocks().installLock, 89 rule.mocks().context, 90 "*dexopt*") 91 whenever(rule.mocks().injector.packageDexOptimizer) 92 .thenReturn(packageDexOptimizer) 93 whenever(appHibernationManager.isOatArtifactDeletionEnabled).thenReturn(true) 94 } 95 96 @Test 97 fun testExitForceStopExitsHibernation() { 98 rule.system().stageScanExistingPackage( 99 TEST_PACKAGE_NAME, 100 1L, 101 rule.system().dataAppDirectory) 102 val pm = createPackageManagerService() 103 rule.system().validateFinalState() 104 105 TestableLooper.get(this).processAllMessages() 106 107 whenever(appHibernationManager.isHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID)) 108 .thenReturn(true) 109 110 pm.setPackageStoppedState(pm.snapshotComputer(), TEST_PACKAGE_NAME, false, TEST_USER_ID) 111 112 TestableLooper.get(this).processAllMessages() 113 114 verify(appHibernationManager).setHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID, false) 115 verify(appHibernationManager).setHibernatingGlobally(TEST_PACKAGE_NAME, false) 116 } 117 118 @Test 119 fun testExitForceStop_nonExistingAppHibernationManager_doesNotThrowException() { 120 whenever(rule.mocks().injector.getLocalService(AppHibernationManagerInternal::class.java)) 121 .thenReturn(null) 122 123 rule.system().stageScanExistingPackage( 124 TEST_PACKAGE_NAME, 125 1L, 126 rule.system().dataAppDirectory) 127 val pm = createPackageManagerService() 128 rule.system().validateFinalState() 129 130 TestableLooper.get(this).processAllMessages() 131 132 whenever(appHibernationManager.isHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID)) 133 .thenReturn(true) 134 135 try { 136 pm.setPackageStoppedState(pm.snapshotComputer(), TEST_PACKAGE_NAME, false, 137 TEST_USER_ID) 138 TestableLooper.get(this).processAllMessages() 139 } catch (e: Exception) { 140 Assert.fail("Method throws exception when AppHibernationManager is not ready.\n$e") 141 } 142 } 143 144 @Test 145 fun testGetOptimizablePackages_ExcludesGloballyHibernatingPackages() { 146 rule.system().stageScanExistingPackage( 147 TEST_PACKAGE_NAME, 148 1L, 149 rule.system().dataAppDirectory, 150 withPackage = { it.apply { isDeclaredHavingCode = true } }) 151 rule.system().stageScanExistingPackage( 152 TEST_PACKAGE_2_NAME, 153 1L, 154 rule.system().dataAppDirectory, 155 withPackage = { it.apply { isDeclaredHavingCode = true } }) 156 val pm = createPackageManagerService() 157 rule.system().validateFinalState() 158 whenever(appHibernationManager.isHibernatingGlobally(TEST_PACKAGE_2_NAME)).thenReturn(true) 159 160 val optimizablePkgs = DexOptHelper(pm).getOptimizablePackages(pm.snapshotComputer()) 161 162 assertTrue(optimizablePkgs.contains(TEST_PACKAGE_NAME)) 163 assertFalse(optimizablePkgs.contains(TEST_PACKAGE_2_NAME)) 164 } 165 166 private fun createPackageManagerService(): PackageManagerService { 167 return PackageManagerService(rule.mocks().injector, 168 false /*factoryTest*/, 169 MockSystem.DEFAULT_VERSION_INFO.fingerprint, 170 false /*isEngBuild*/, 171 false /*isUserDebugBuild*/, 172 Build.VERSION_CODES.CUR_DEVELOPMENT, 173 Build.VERSION.INCREMENTAL) 174 } 175 } 176