• 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 com.android.server.art.AidlUtils.buildFsPermission;
20 import static com.android.server.art.AidlUtils.buildOutputArtifacts;
21 import static com.android.server.art.AidlUtils.buildPermissionSettings;
22 import static com.android.server.art.OutputArtifacts.PermissionSettings;
23 import static com.android.server.art.model.DexoptResult.DexContainerFileDexoptResult;
24 import static com.android.server.art.testing.TestingUtils.deepEq;
25 
26 import static com.google.common.truth.Truth.assertThat;
27 
28 import static org.mockito.Mockito.any;
29 import static org.mockito.Mockito.anyBoolean;
30 import static org.mockito.Mockito.anyInt;
31 import static org.mockito.Mockito.argThat;
32 import static org.mockito.Mockito.doReturn;
33 import static org.mockito.Mockito.doThrow;
34 import static org.mockito.Mockito.eq;
35 import static org.mockito.Mockito.isNull;
36 import static org.mockito.Mockito.lenient;
37 import static org.mockito.Mockito.mock;
38 import static org.mockito.Mockito.times;
39 import static org.mockito.Mockito.verify;
40 import static org.mockito.Mockito.when;
41 
42 import android.content.pm.ApplicationInfo;
43 import android.os.Process;
44 import android.os.ServiceSpecificException;
45 import android.os.SystemProperties;
46 
47 import androidx.test.filters.SmallTest;
48 
49 import com.android.server.art.model.ArtFlags;
50 import com.android.server.art.model.DexoptParams;
51 import com.android.server.art.model.DexoptResult;
52 import com.android.server.art.testing.TestingUtils;
53 
54 import org.junit.Before;
55 import org.junit.Test;
56 import org.junit.runner.RunWith;
57 import org.junit.runners.Parameterized;
58 import org.junit.runners.Parameterized.Parameter;
59 import org.junit.runners.Parameterized.Parameters;
60 import org.mockito.ArgumentMatcher;
61 
62 import java.nio.file.NoSuchFileException;
63 import java.util.ArrayList;
64 import java.util.List;
65 
66 @SmallTest
67 @RunWith(Parameterized.class)
68 public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase {
69     private DexoptParams mDexoptParams;
70 
71     private PrimaryDexopter mPrimaryDexopter;
72 
73     @Parameter(0) public Params mParams;
74 
75     @Parameters(name = "{0}")
data()76     public static Iterable<Params> data() {
77         List<Params> list = new ArrayList<>();
78         Params params;
79 
80         // Baseline.
81         params = new Params();
82         list.add(params);
83 
84         // Sandbox SdkLib.
85         params = new Params();
86         params.mIsSanboxSdkLib = true;
87         list.add(params);
88 
89         params = new Params();
90         params.mRequestedCompilerFilter = "speed";
91         params.mExpectedCompilerFilter = "speed";
92         list.add(params);
93 
94         params = new Params();
95         params.mIsInDalvikCache = true;
96         list.add(params);
97 
98         params = new Params();
99         params.mHiddenApiEnforcementPolicy = ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
100         params.mExpectedIsHiddenApiPolicyEnabled = false;
101         list.add(params);
102 
103         params = new Params();
104         params.mIsDebuggable = true;
105         params.mRequestedCompilerFilter = "speed";
106         params.mExpectedCompilerFilter = "verify";
107         params.mExpectedIsDebuggable = true;
108         list.add(params);
109 
110         params = new Params();
111         params.mIsVmSafeMode = true;
112         params.mRequestedCompilerFilter = "speed";
113         params.mExpectedCompilerFilter = "verify";
114         list.add(params);
115 
116         params = new Params();
117         params.mIsUseEmbeddedDex = true;
118         params.mRequestedCompilerFilter = "speed";
119         params.mExpectedCompilerFilter = "verify";
120         list.add(params);
121 
122         params = new Params();
123         params.mAlwaysDebuggable = true;
124         params.mExpectedIsDebuggable = true;
125         list.add(params);
126 
127         params = new Params();
128         params.mIsSystemUi = true;
129         params.mExpectedCompilerFilter = "speed";
130         list.add(params);
131 
132         params = new Params();
133         params.mIsLauncher = true;
134         params.mExpectedCompilerFilter = "speed-profile";
135         list.add(params);
136 
137         params = new Params();
138         params.mForce = true;
139         params.mShouldDowngrade = false;
140         params.mExpectedDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_BETTER
141                 | DexoptTrigger.COMPILER_FILTER_IS_SAME | DexoptTrigger.COMPILER_FILTER_IS_WORSE
142                 | DexoptTrigger.PRIMARY_BOOT_IMAGE_BECOMES_USABLE | DexoptTrigger.NEED_EXTRACTION;
143         list.add(params);
144 
145         params = new Params();
146         params.mForce = true;
147         params.mShouldDowngrade = true;
148         params.mExpectedDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_BETTER
149                 | DexoptTrigger.COMPILER_FILTER_IS_SAME | DexoptTrigger.COMPILER_FILTER_IS_WORSE
150                 | DexoptTrigger.PRIMARY_BOOT_IMAGE_BECOMES_USABLE | DexoptTrigger.NEED_EXTRACTION;
151         list.add(params);
152 
153         params = new Params();
154         params.mShouldDowngrade = true;
155         params.mExpectedDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_WORSE;
156         list.add(params);
157 
158         params = new Params();
159         // This should not change the result.
160         params.mSkipIfStorageLow = true;
161         list.add(params);
162 
163         params = new Params();
164         params.mIgnoreProfile = true;
165         params.mRequestedCompilerFilter = "speed-profile";
166         params.mExpectedCompilerFilter = "verify";
167         list.add(params);
168 
169         params = new Params();
170         params.mIgnoreProfile = true;
171         params.mRequestedCompilerFilter = "speed";
172         params.mExpectedCompilerFilter = "speed";
173         list.add(params);
174 
175         // It respects the adjustment made by the callback.
176         params = new Params();
177         params.mRequestedCompilerFilter = "speed-profile";
178         params.mExpectedCallbackInputCompilerFilter = "speed-profile";
179         params.mCallbackReturnedCompilerFilter = "speed";
180         params.mExpectedCompilerFilter = "speed";
181         list.add(params);
182 
183         // It upgrades the compiler filter before calling the callback.
184         params = new Params();
185         params.mRequestedCompilerFilter = "speed-profile";
186         params.mIsSystemUi = true;
187         params.mExpectedCallbackInputCompilerFilter = "speed";
188         params.mCallbackReturnedCompilerFilter = "speed";
189         params.mExpectedCompilerFilter = "speed";
190         list.add(params);
191 
192         // It downgrades the compiler filter after calling the callback.
193         params = new Params();
194         params.mRequestedCompilerFilter = "speed-profile";
195         params.mExpectedCallbackInputCompilerFilter = "speed-profile";
196         params.mCallbackReturnedCompilerFilter = "speed-profile";
197         params.mIsUseEmbeddedDex = true;
198         params.mExpectedCompilerFilter = "verify";
199         list.add(params);
200 
201         params = new Params();
202         params.mIsPreReboot = true;
203         params.mExpectedOutputIsPreReboot = true;
204         params.mExpectedDeletesRuntimeArtifacts = false;
205         params.mExpectedDeletesSdmSdcFiles = false;
206         list.add(params);
207 
208         params = new Params();
209         params.mIsSystemUi = true;
210         params.mForceCompilerFilter = true;
211         params.mRequestedCompilerFilter = "verify";
212         params.mExpectedCompilerFilter = "verify";
213         list.add(params);
214 
215         params = new Params();
216         params.mForceCompilerFilter = true;
217         params.mRequestedCompilerFilter = "verify";
218         params.mExpectedCallbackInputCompilerFilter = "verify";
219         params.mCallbackReturnedCompilerFilter = "speed";
220         params.mExpectedCompilerFilter = "verify";
221         list.add(params);
222 
223         return list;
224     }
225 
226     @Before
setUp()227     public void setUp() throws Exception {
228         super.setUp();
229 
230         lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(mParams.mIsSystemUi);
231         lenient().when(mInjector.isLauncherPackage(any())).thenReturn(mParams.mIsLauncher);
232         lenient().when(mInjector.isPreReboot()).thenReturn(mParams.mIsPreReboot);
233 
234         lenient()
235                 .when(SystemProperties.getBoolean(eq("dalvik.vm.always_debuggable"), anyBoolean()))
236                 .thenReturn(mParams.mAlwaysDebuggable);
237 
238         lenient().when(mPkg.isVmSafeMode()).thenReturn(mParams.mIsVmSafeMode);
239         lenient().when(mPkg.isDebuggable()).thenReturn(mParams.mIsDebuggable);
240         lenient().when(mPkg.getTargetSdkVersion()).thenReturn(123);
241         lenient()
242                 .when(mPkgState.getHiddenApiEnforcementPolicy())
243                 .thenReturn(mParams.mHiddenApiEnforcementPolicy);
244         lenient().when(mPkg.isUseEmbeddedDex()).thenReturn(mParams.mIsUseEmbeddedDex);
245 
246         // Make all profile-related operations succeed so that "speed-profile" doesn't fall back to
247         // "verify".
248         lenient().when(mArtd.isProfileUsable(any(), any())).thenReturn(true);
249         lenient().when(mArtd.getProfileVisibility(any())).thenReturn(FileVisibility.OTHER_READABLE);
250         lenient().when(mArtd.mergeProfiles(any(), any(), any(), any(), any())).thenReturn(false);
251 
252         lenient().when(mArtd.isInDalvikCache(any())).thenReturn(mParams.mIsInDalvikCache);
253 
254         // By default, no artifacts exist.
255         lenient().when(mArtd.getArtifactsVisibility(any())).thenReturn(FileVisibility.NOT_FOUND);
256 
257         if (mParams.mCallbackReturnedCompilerFilter != null) {
258             mConfig.setAdjustCompilerFilterCallback(
259                     Runnable::run, (packageName, originalCompilerFilter, reason) -> {
260                         assertThat(packageName).isEqualTo(PKG_NAME);
261                         assertThat(originalCompilerFilter)
262                                 .isEqualTo(mParams.mExpectedCallbackInputCompilerFilter);
263                         assertThat(reason).isEqualTo("install");
264                         return mParams.mCallbackReturnedCompilerFilter;
265                     });
266         }
267 
268         if (mParams.mIsSanboxSdkLib) {
269             lenient().when(mPkgState.getAppId()).thenReturn(-1);
270         }
271 
272         mDexoptParams =
273                 new DexoptParams.Builder("install")
274                         .setCompilerFilter(mParams.mRequestedCompilerFilter)
275                         .setPriorityClass(ArtFlags.PRIORITY_INTERACTIVE)
276                         .setFlags(mParams.mForce ? ArtFlags.FLAG_FORCE : 0, ArtFlags.FLAG_FORCE)
277                         .setFlags(mParams.mShouldDowngrade ? ArtFlags.FLAG_SHOULD_DOWNGRADE : 0,
278                                 ArtFlags.FLAG_SHOULD_DOWNGRADE)
279                         .setFlags(mParams.mSkipIfStorageLow ? ArtFlags.FLAG_SKIP_IF_STORAGE_LOW : 0,
280                                 ArtFlags.FLAG_SKIP_IF_STORAGE_LOW)
281                         .setFlags(mParams.mIgnoreProfile ? ArtFlags.FLAG_IGNORE_PROFILE : 0,
282                                 ArtFlags.FLAG_IGNORE_PROFILE)
283                         .setFlags(mParams.mForceCompilerFilter ? ArtFlags.FLAG_FORCE_COMPILER_FILTER
284                                                                : 0,
285                                 ArtFlags.FLAG_FORCE_COMPILER_FILTER)
286                         .build();
287 
288         mPrimaryDexopter =
289                 new PrimaryDexopter(mInjector, mPkgState, mPkg, mDexoptParams, mCancellationSignal);
290     }
291 
292     @Test
testDexopt()293     public void testDexopt() throws Exception {
294         int sharedGid = mParams.mIsSanboxSdkLib ? Process.SYSTEM_UID : SHARED_GID;
295         PermissionSettings permissionSettings = buildPermissionSettings(
296                 buildFsPermission(Process.SYSTEM_UID /* uid */, Process.SYSTEM_UID /* gid */,
297                         false /* isOtherReadable */, true /* isOtherExecutable */),
298                 buildFsPermission(Process.SYSTEM_UID /* uid */, sharedGid /* gid */,
299                         true /* isOtherReadable */),
300                 null /* seContext */);
301 
302         // No need to check `generateAppImage`. It is checked in `PrimaryDexopterTest`.
303         ArgumentMatcher<DexoptOptions> dexoptOptionsMatcher = options
304                 -> options.compilationReason.equals("install") && options.targetSdkVersion == 123
305                 && options.debuggable == mParams.mExpectedIsDebuggable
306                 && options.hiddenApiPolicyEnabled == mParams.mExpectedIsHiddenApiPolicyEnabled
307                 && options.comments.equals(String.format(
308                         "app-name:%s,app-version-name:%s,app-version-code:%d,art-version:%d",
309                         PKG_NAME, APP_VERSION_NAME, APP_VERSION_CODE, ART_VERSION));
310 
311         when(mArtd.createCancellationSignal()).thenReturn(mock(IArtdCancellationSignal.class));
312         lenient()
313                 .when(mDexMetadataHelperInjector.openZipFile(any()))
314                 .thenThrow(NoSuchFileException.class);
315 
316         if (mParams.mIsPreReboot) {
317             doReturn(FileVisibility.OTHER_READABLE)
318                     .when(mArtd)
319                     .getDexFileVisibility("/somewhere/app/foo/base.apk");
320             doReturn(FileVisibility.OTHER_READABLE)
321                     .when(mArtd)
322                     .getDexFileVisibility("/somewhere/app/foo/split_0.apk");
323         }
324 
325         // The first one is normal.
326         doReturn(dexoptIsNeeded())
327                 .when(mArtd)
328                 .getDexoptNeeded("/somewhere/app/foo/base.apk", "arm64", "PCL[]",
329                         mParams.mExpectedCompilerFilter, mParams.mExpectedDexoptTrigger);
330         doReturn(createArtdDexoptResult(false /* cancelled */, 100 /* wallTimeMs */,
331                          400 /* cpuTimeMs */, 30000 /* sizeBytes */, 32000 /* sizeBeforeBytes */))
332                 .when(mArtd)
333                 .dexopt(deepEq(buildOutputArtifacts("/somewhere/app/foo/base.apk", "arm64",
334                                 mParams.mIsInDalvikCache, permissionSettings,
335                                 mParams.mExpectedOutputIsPreReboot)),
336                         eq("/somewhere/app/foo/base.apk"), eq("arm64"), eq("PCL[]"),
337                         eq(mParams.mExpectedCompilerFilter), any() /* profile */,
338                         isNull() /* inputVdex */, isNull() /* dmFile */,
339                         eq(PriorityClass.INTERACTIVE), argThat(dexoptOptionsMatcher), any());
340 
341         // The second one fails on `dexopt`.
342         doReturn(dexoptIsNeeded())
343                 .when(mArtd)
344                 .getDexoptNeeded("/somewhere/app/foo/base.apk", "arm", "PCL[]",
345                         mParams.mExpectedCompilerFilter, mParams.mExpectedDexoptTrigger);
346         doThrow(new ServiceSpecificException(31, "This is an error message."))
347                 .when(mArtd)
348                 .dexopt(deepEq(buildOutputArtifacts("/somewhere/app/foo/base.apk", "arm",
349                                 mParams.mIsInDalvikCache, permissionSettings,
350                                 mParams.mExpectedOutputIsPreReboot)),
351                         eq("/somewhere/app/foo/base.apk"), eq("arm"), eq("PCL[]"),
352                         eq(mParams.mExpectedCompilerFilter), any() /* profile */,
353                         isNull() /* inputVdex */, isNull() /* dmFile */,
354                         eq(PriorityClass.INTERACTIVE), argThat(dexoptOptionsMatcher), any());
355 
356         // The third one doesn't need dexopt.
357         doReturn(dexoptIsNotNeeded())
358                 .when(mArtd)
359                 .getDexoptNeeded("/somewhere/app/foo/split_0.apk", "arm64", "PCL[base.apk]",
360                         mParams.mExpectedCompilerFilter, mParams.mExpectedDexoptTrigger);
361 
362         // The fourth one is normal.
363         doReturn(dexoptIsNeeded())
364                 .when(mArtd)
365                 .getDexoptNeeded("/somewhere/app/foo/split_0.apk", "arm", "PCL[base.apk]",
366                         mParams.mExpectedCompilerFilter, mParams.mExpectedDexoptTrigger);
367         doReturn(createArtdDexoptResult(false /* cancelled */, 200 /* wallTimeMs */,
368                          200 /* cpuTimeMs */, 10000 /* sizeBytes */, 0 /* sizeBeforeBytes */))
369                 .when(mArtd)
370                 .dexopt(deepEq(buildOutputArtifacts("/somewhere/app/foo/split_0.apk", "arm",
371                                 mParams.mIsInDalvikCache, permissionSettings,
372                                 mParams.mExpectedOutputIsPreReboot)),
373                         eq("/somewhere/app/foo/split_0.apk"), eq("arm"), eq("PCL[base.apk]"),
374                         eq(mParams.mExpectedCompilerFilter), any() /* profile */,
375                         isNull() /* inputVdex */, isNull() /* dmFile */,
376                         eq(PriorityClass.INTERACTIVE), argThat(dexoptOptionsMatcher), any());
377 
378         if (mParams.mExpectedDeletesRuntimeArtifacts) {
379             // Only delete runtime artifacts for successful dexopt operations, namely the first one
380             // and the fourth one.
381             doReturn(1l).when(mArtd).deleteRuntimeArtifacts(
382                     deepEq(AidlUtils.buildRuntimeArtifactsPath(
383                             PKG_NAME, "/somewhere/app/foo/base.apk", "arm64")));
384             doReturn(1l).when(mArtd).deleteRuntimeArtifacts(
385                     deepEq(AidlUtils.buildRuntimeArtifactsPath(
386                             PKG_NAME, "/somewhere/app/foo/split_0.apk", "arm")));
387         }
388 
389         if (mParams.mExpectedDeletesSdmSdcFiles) {
390             // Only delete SDM and SDC files for successful dexopt operations, namely the first one
391             // and the fourth one.
392             doReturn(1l).when(mArtd).deleteSdmSdcFiles(
393                     deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths(
394                             "/somewhere/app/foo/base.apk", "arm64", mParams.mIsInDalvikCache)));
395             doReturn(1l).when(mArtd).deleteSdmSdcFiles(
396                     deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths(
397                             "/somewhere/app/foo/split_0.apk", "arm", mParams.mIsInDalvikCache)));
398         }
399 
400         assertThat(mPrimaryDexopter.dexopt())
401                 .comparingElementsUsing(TestingUtils.<DexContainerFileDexoptResult>deepEquality())
402                 .containsExactly(
403                         DexContainerFileDexoptResult.create("/somewhere/app/foo/base.apk",
404                                 true /* isPrimaryAbi */, "arm64-v8a",
405                                 mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_PERFORMED,
406                                 100 /* dex2oatWallTimeMillis */, 400 /* dex2oatCpuTimeMillis */,
407                                 30000 /* sizeBytes */, 32000 /* sizeBeforeBytes */,
408                                 0 /* extendedStatusFlags */, List.of() /* externalProfileErrors */),
409                         DexContainerFileDexoptResult.create("/somewhere/app/foo/base.apk",
410                                 false /* isPrimaryAbi */, "armeabi-v7a",
411                                 mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_FAILED),
412                         DexContainerFileDexoptResult.create("/somewhere/app/foo/split_0.apk",
413                                 true /* isPrimaryAbi */, "arm64-v8a",
414                                 mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_SKIPPED),
415                         DexContainerFileDexoptResult.create("/somewhere/app/foo/split_0.apk",
416                                 false /* isPrimaryAbi */, "armeabi-v7a",
417                                 mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_PERFORMED,
418                                 200 /* dex2oatWallTimeMillis */, 200 /* dex2oatCpuTimeMillis */,
419                                 10000 /* sizeBytes */, 0 /* sizeBeforeBytes */,
420                                 0 /* extendedStatusFlags */,
421                                 List.of() /* externalProfileErrors */));
422 
423         // Verify that there are no more calls than the ones above.
424         verify(mArtd, times(3))
425                 .dexopt(any(), any(), any(), any(), any(), any(), any(), any(), anyInt(), any(),
426                         any());
427 
428         if (!mParams.mExpectedDeletesRuntimeArtifacts) {
429             verify(mArtd, times(0)).deleteRuntimeArtifacts(any());
430         }
431 
432         if (!mParams.mExpectedDeletesSdmSdcFiles) {
433             verify(mArtd, times(0)).deleteSdmSdcFiles(any());
434         }
435     }
436 
437     private static class Params {
438         // Package information.
439         public boolean mIsInDalvikCache = false;
440         public int mHiddenApiEnforcementPolicy = ApplicationInfo.HIDDEN_API_ENFORCEMENT_ENABLED;
441         public boolean mIsVmSafeMode = false;
442         public boolean mIsDebuggable = false;
443         public boolean mIsSystemUi = false;
444         public boolean mIsLauncher = false;
445         public boolean mIsUseEmbeddedDex = false;
446         public boolean mIsSanboxSdkLib = false;
447 
448         // Options.
449         public String mRequestedCompilerFilter = "verify";
450         public String mCallbackReturnedCompilerFilter = null;
451         public boolean mForce = false;
452         public boolean mShouldDowngrade = false;
453         public boolean mSkipIfStorageLow = false;
454         public boolean mIgnoreProfile = false;
455         public boolean mIsPreReboot = false;
456         public boolean mForceCompilerFilter = false;
457 
458         // System properties.
459         public boolean mAlwaysDebuggable = false;
460 
461         // Expectations.
462         public String mExpectedCallbackInputCompilerFilter = "verify";
463         public String mExpectedCompilerFilter = "verify";
464         public int mExpectedDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_BETTER
465                 | DexoptTrigger.PRIMARY_BOOT_IMAGE_BECOMES_USABLE | DexoptTrigger.NEED_EXTRACTION;
466         public boolean mExpectedIsDebuggable = false;
467         public boolean mExpectedIsHiddenApiPolicyEnabled = true;
468         public boolean mExpectedOutputIsPreReboot = false;
469         public boolean mExpectedDeletesRuntimeArtifacts = true;
470         public boolean mExpectedDeletesSdmSdcFiles = true;
471 
toString()472         public String toString() {
473             return String.format("isInDalvikCache=%b,"
474                             + "hiddenApiEnforcementPolicy=%d,"
475                             + "isVmSafeMode=%b,"
476                             + "isDebuggable=%b,"
477                             + "isSystemUi=%b,"
478                             + "isLauncher=%b,"
479                             + "isUseEmbeddedDex=%b,"
480                             + "isSanboxSdkLib=%b,"
481                             + "requestedCompilerFilter=%s,"
482                             + "callbackReturnedCompilerFilter=%s,"
483                             + "force=%b,"
484                             + "shouldDowngrade=%b,"
485                             + "skipIfStorageLow=%b,"
486                             + "ignoreProfile=%b,"
487                             + "isPreReboot=%b,"
488                             + "forceCompilerFilter=%b,"
489                             + "alwaysDebuggable=%b"
490                             + " => "
491                             + "expectedCallbackInputCompilerFilter=%s,"
492                             + "expectedCompilerFilter=%s,"
493                             + "expectedDexoptTrigger=%d,"
494                             + "expectedIsDebuggable=%b,"
495                             + "expectedIsHiddenApiPolicyEnabled=%b,"
496                             + "expectedOutputIsPreReboot=%b,"
497                             + "expectedDeletesRuntimeArtifacts=%b,"
498                             + "expectedDeletesSdmSdcFiles=%b",
499                     mIsInDalvikCache, mHiddenApiEnforcementPolicy, mIsVmSafeMode, mIsDebuggable,
500                     mIsSystemUi, mIsLauncher, mIsUseEmbeddedDex, mIsSanboxSdkLib,
501                     mRequestedCompilerFilter, mCallbackReturnedCompilerFilter, mForce,
502                     mShouldDowngrade, mSkipIfStorageLow, mIgnoreProfile, mIsPreReboot,
503                     mForceCompilerFilter, mAlwaysDebuggable, mExpectedCallbackInputCompilerFilter,
504                     mExpectedCompilerFilter, mExpectedDexoptTrigger, mExpectedIsDebuggable,
505                     mExpectedIsHiddenApiPolicyEnabled, mExpectedOutputIsPreReboot,
506                     mExpectedDeletesRuntimeArtifacts, mExpectedDeletesSdmSdcFiles);
507         }
508     }
509 }
510