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