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