• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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