1 /* 2 * Copyright (C) 2022 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.art; 18 19 import static com.android.server.art.GetDexoptNeededResult.ArtifactsLocation; 20 21 import static org.mockito.Mockito.any; 22 import static org.mockito.Mockito.anyBoolean; 23 import static org.mockito.Mockito.argThat; 24 import static org.mockito.Mockito.eq; 25 import static org.mockito.Mockito.lenient; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.same; 28 29 import android.os.CancellationSignal; 30 import android.os.SystemProperties; 31 import android.os.UserHandle; 32 import android.os.UserManager; 33 import android.os.storage.StorageManager; 34 35 import com.android.modules.utils.pm.PackageStateModulesUtils; 36 import com.android.server.art.testing.StaticMockitoRule; 37 import com.android.server.pm.pkg.AndroidPackage; 38 import com.android.server.pm.pkg.AndroidPackageSplit; 39 import com.android.server.pm.pkg.PackageState; 40 import com.android.server.pm.pkg.PackageUserState; 41 42 import dalvik.system.PathClassLoader; 43 44 import org.junit.Before; 45 import org.junit.Rule; 46 import org.mockito.Mock; 47 48 import java.util.ArrayList; 49 import java.util.List; 50 51 public class PrimaryDexopterTestBase { 52 protected static final String PKG_NAME = "com.example.foo"; 53 protected static final int UID = 12345; 54 protected static final int SHARED_GID = UserHandle.getSharedAppGid(UID); 55 protected static final long ART_VERSION = 331413030l; 56 protected static final String APP_VERSION_NAME = "12.34.56"; 57 protected static final long APP_VERSION_CODE = 1536036288l; 58 59 @Rule 60 public StaticMockitoRule mockitoRule = new StaticMockitoRule( 61 SystemProperties.class, Constants.class, PackageStateModulesUtils.class); 62 63 @Mock protected PrimaryDexopter.Injector mInjector; 64 @Mock protected IArtd mArtd; 65 @Mock protected UserManager mUserManager; 66 @Mock protected DexUseManagerLocal mDexUseManager; 67 @Mock protected StorageManager mStorageManager; 68 protected PackageState mPkgState; 69 protected AndroidPackage mPkg; 70 protected PackageUserState mPkgUserStateNotInstalled; 71 protected PackageUserState mPkgUserStateInstalled; 72 protected CancellationSignal mCancellationSignal; 73 74 @Before setUp()75 public void setUp() throws Exception { 76 lenient().when(mInjector.getArtd()).thenReturn(mArtd); 77 lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false); 78 lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false); 79 lenient().when(mInjector.getUserManager()).thenReturn(mUserManager); 80 lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager); 81 lenient().when(mInjector.getStorageManager()).thenReturn(mStorageManager); 82 lenient().when(mInjector.getArtVersion()).thenReturn(ART_VERSION); 83 84 lenient() 85 .when(SystemProperties.get("dalvik.vm.systemuicompilerfilter")) 86 .thenReturn("speed"); 87 lenient() 88 .when(SystemProperties.getBoolean(eq("dalvik.vm.always_debuggable"), anyBoolean())) 89 .thenReturn(false); 90 lenient().when(SystemProperties.get("dalvik.vm.appimageformat")).thenReturn("lz4"); 91 lenient().when(SystemProperties.get("pm.dexopt.shared")).thenReturn("speed"); 92 93 // No ISA translation. 94 lenient() 95 .when(SystemProperties.get(argThat(arg -> arg.startsWith("ro.dalvik.vm.isa.")))) 96 .thenReturn(""); 97 98 lenient().when(Constants.getPreferredAbi()).thenReturn("arm64-v8a"); 99 lenient().when(Constants.getNative64BitAbi()).thenReturn("arm64-v8a"); 100 lenient().when(Constants.getNative32BitAbi()).thenReturn("armeabi-v7a"); 101 102 lenient() 103 .when(mUserManager.getUserHandles(anyBoolean())) 104 .thenReturn(List.of(UserHandle.of(0), UserHandle.of(1), UserHandle.of(2))); 105 106 lenient().when(mDexUseManager.isPrimaryDexUsedByOtherApps(any(), any())).thenReturn(false); 107 108 lenient().when(mStorageManager.getAllocatableBytes(any())).thenReturn(1l); 109 110 mPkgUserStateNotInstalled = createPackageUserState(false /* installed */); 111 mPkgUserStateInstalled = createPackageUserState(true /* installed */); 112 mPkgState = createPackageState(); 113 mPkg = mPkgState.getAndroidPackage(); 114 mCancellationSignal = new CancellationSignal(); 115 } 116 createPackage()117 private AndroidPackage createPackage() { 118 // This package has the base APK and one split APK that has code. 119 AndroidPackage pkg = mock(AndroidPackage.class); 120 var baseSplit = mock(AndroidPackageSplit.class); 121 lenient().when(baseSplit.getPath()).thenReturn("/data/app/foo/base.apk"); 122 lenient().when(baseSplit.isHasCode()).thenReturn(true); 123 lenient().when(baseSplit.getClassLoaderName()).thenReturn(PathClassLoader.class.getName()); 124 125 var split0 = mock(AndroidPackageSplit.class); 126 lenient().when(split0.getName()).thenReturn("split_0"); 127 lenient().when(split0.getPath()).thenReturn("/data/app/foo/split_0.apk"); 128 lenient().when(split0.isHasCode()).thenReturn(true); 129 130 var split1 = mock(AndroidPackageSplit.class); 131 lenient().when(split1.getName()).thenReturn("split_1"); 132 lenient().when(split1.getPath()).thenReturn("/data/app/foo/split_1.apk"); 133 lenient().when(split1.isHasCode()).thenReturn(false); 134 135 var splits = List.of(baseSplit, split0, split1); 136 lenient().when(pkg.getSplits()).thenReturn(splits); 137 138 lenient().when(pkg.isVmSafeMode()).thenReturn(false); 139 lenient().when(pkg.isDebuggable()).thenReturn(false); 140 lenient().when(pkg.getTargetSdkVersion()).thenReturn(123); 141 lenient().when(pkg.isSignedWithPlatformKey()).thenReturn(false); 142 lenient().when(pkg.isNonSdkApiRequested()).thenReturn(false); 143 lenient().when(pkg.getVersionName()).thenReturn(APP_VERSION_NAME); 144 lenient().when(pkg.getLongVersionCode()).thenReturn(APP_VERSION_CODE); 145 return pkg; 146 } 147 createPackageState()148 private PackageState createPackageState() { 149 PackageState pkgState = mock(PackageState.class); 150 lenient().when(pkgState.getPackageName()).thenReturn(PKG_NAME); 151 lenient().when(pkgState.getPrimaryCpuAbi()).thenReturn("arm64-v8a"); 152 lenient().when(pkgState.getSecondaryCpuAbi()).thenReturn("armeabi-v7a"); 153 lenient().when(pkgState.isSystem()).thenReturn(false); 154 lenient().when(pkgState.isUpdatedSystemApp()).thenReturn(false); 155 lenient().when(pkgState.getAppId()).thenReturn(UID); 156 lenient().when(pkgState.getSharedLibraryDependencies()).thenReturn(new ArrayList<>()); 157 lenient().when(pkgState.getStateForUser(any())).thenReturn(mPkgUserStateNotInstalled); 158 AndroidPackage pkg = createPackage(); 159 lenient().when(pkgState.getAndroidPackage()).thenReturn(pkg); 160 lenient() 161 .when(PackageStateModulesUtils.isLoadableInOtherProcesses( 162 same(pkgState), anyBoolean())) 163 .thenReturn(false); 164 return pkgState; 165 } 166 createPackageUserState(boolean isInstalled)167 private PackageUserState createPackageUserState(boolean isInstalled) { 168 PackageUserState pkgUserState = mock(PackageUserState.class); 169 lenient().when(pkgUserState.isInstalled()).thenReturn(isInstalled); 170 return pkgUserState; 171 } 172 dexoptIsNotNeeded()173 protected GetDexoptNeededResult dexoptIsNotNeeded() { 174 var result = new GetDexoptNeededResult(); 175 result.isDexoptNeeded = false; 176 return result; 177 } 178 dexoptIsNeeded()179 protected GetDexoptNeededResult dexoptIsNeeded() { 180 return dexoptIsNeeded(ArtifactsLocation.NONE_OR_ERROR); 181 } 182 dexoptIsNeeded(@rtifactsLocation byte location)183 protected GetDexoptNeededResult dexoptIsNeeded(@ArtifactsLocation byte location) { 184 var result = new GetDexoptNeededResult(); 185 result.isDexoptNeeded = true; 186 result.artifactsLocation = location; 187 if (location != ArtifactsLocation.NONE_OR_ERROR) { 188 result.isVdexUsable = true; 189 } 190 return result; 191 } 192 createArtdDexoptResult(boolean cancelled, long wallTimeMs, long cpuTimeMs, long sizeBytes, long sizeBeforeBytes)193 protected ArtdDexoptResult createArtdDexoptResult(boolean cancelled, long wallTimeMs, 194 long cpuTimeMs, long sizeBytes, long sizeBeforeBytes) { 195 var result = new ArtdDexoptResult(); 196 result.cancelled = cancelled; 197 result.wallTimeMs = wallTimeMs; 198 result.cpuTimeMs = cpuTimeMs; 199 result.sizeBytes = sizeBytes; 200 result.sizeBeforeBytes = sizeBeforeBytes; 201 return result; 202 } 203 createArtdDexoptResult(boolean cancelled)204 protected ArtdDexoptResult createArtdDexoptResult(boolean cancelled) { 205 return createArtdDexoptResult(cancelled, 0 /* wallTimeMs */, 0 /* cpuTimeMs */, 206 0 /* sizeBytes */, 0 /* sizeBeforeBytes */); 207 } 208 } 209