• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.content.pm.parsing;
18 
19 import android.annotation.CheckResult;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.apex.ApexInfo;
23 import android.content.pm.ActivityInfo;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.Attribution;
26 import android.content.pm.ComponentInfo;
27 import android.content.pm.ConfigurationInfo;
28 import android.content.pm.FallbackCategoryProvider;
29 import android.content.pm.FeatureGroupInfo;
30 import android.content.pm.FeatureInfo;
31 import android.content.pm.InstrumentationInfo;
32 import android.content.pm.PackageInfo;
33 import android.content.pm.PackageItemInfo;
34 import android.content.pm.PackageManager;
35 import android.content.pm.PackageParser;
36 import android.content.pm.PackageUserState;
37 import android.content.pm.PermissionGroupInfo;
38 import android.content.pm.PermissionInfo;
39 import android.content.pm.ProviderInfo;
40 import android.content.pm.SELinuxUtil;
41 import android.content.pm.ServiceInfo;
42 import android.content.pm.Signature;
43 import android.content.pm.SigningInfo;
44 import android.content.pm.overlay.OverlayPaths;
45 import android.content.pm.parsing.component.ComponentParseUtils;
46 import android.content.pm.parsing.component.ParsedActivity;
47 import android.content.pm.parsing.component.ParsedAttribution;
48 import android.content.pm.parsing.component.ParsedComponent;
49 import android.content.pm.parsing.component.ParsedInstrumentation;
50 import android.content.pm.parsing.component.ParsedMainComponent;
51 import android.content.pm.parsing.component.ParsedPermission;
52 import android.content.pm.parsing.component.ParsedPermissionGroup;
53 import android.content.pm.parsing.component.ParsedProvider;
54 import android.content.pm.parsing.component.ParsedService;
55 import android.content.pm.parsing.component.ParsedUsesPermission;
56 import android.os.Environment;
57 import android.os.UserHandle;
58 
59 import com.android.internal.util.ArrayUtils;
60 
61 import libcore.util.EmptyArray;
62 
63 import java.io.File;
64 import java.util.Collections;
65 import java.util.List;
66 import java.util.Set;
67 
68 /** @hide **/
69 public class PackageInfoWithoutStateUtils {
70 
71     public static final String SYSTEM_DATA_PATH =
72             Environment.getDataDirectoryPath() + File.separator + "system";
73 
74     @Nullable
generate(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId)75     public static PackageInfo generate(ParsingPackageRead pkg, int[] gids,
76             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
77             Set<String> grantedPermissions, PackageUserState state, int userId) {
78         return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions,
79                 state, userId, null);
80     }
81 
82     @Nullable
generate(ParsingPackageRead pkg, ApexInfo apexInfo, int flags)83     public static PackageInfo generate(ParsingPackageRead pkg, ApexInfo apexInfo, int flags) {
84         return generateWithComponents(pkg, EmptyArray.INT, flags, 0, 0, Collections.emptySet(),
85                 new PackageUserState(), UserHandle.getCallingUserId(), apexInfo);
86     }
87 
88     @Nullable
generateWithComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo)89     private static PackageInfo generateWithComponents(ParsingPackageRead pkg, int[] gids,
90             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
91             Set<String> grantedPermissions, PackageUserState state, int userId,
92             @Nullable ApexInfo apexInfo) {
93         ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
94         if (applicationInfo == null) {
95             return null;
96         }
97         PackageInfo info = generateWithoutComponents(pkg, gids, flags, firstInstallTime,
98                 lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);
99 
100         if (info == null) {
101             return null;
102         }
103 
104         if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
105             final int N = pkg.getActivities().size();
106             if (N > 0) {
107                 int num = 0;
108                 final ActivityInfo[] res = new ActivityInfo[N];
109                 for (int i = 0; i < N; i++) {
110                     final ParsedActivity a = pkg.getActivities().get(i);
111                     if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,
112                             flags)) {
113                         if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
114                                 a.getName())) {
115                             continue;
116                         }
117                         res[num++] = generateActivityInfo(pkg, a, flags, state,
118                                 applicationInfo, userId);
119                     }
120                 }
121                 info.activities = ArrayUtils.trimToSize(res, num);
122             }
123         }
124         if ((flags & PackageManager.GET_RECEIVERS) != 0) {
125             final int size = pkg.getReceivers().size();
126             if (size > 0) {
127                 int num = 0;
128                 final ActivityInfo[] res = new ActivityInfo[size];
129                 for (int i = 0; i < size; i++) {
130                     final ParsedActivity a = pkg.getReceivers().get(i);
131                     if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,
132                             flags)) {
133                         res[num++] = generateActivityInfo(pkg, a, flags, state,
134                                 applicationInfo, userId);
135                     }
136                 }
137                 info.receivers = ArrayUtils.trimToSize(res, num);
138             }
139         }
140         if ((flags & PackageManager.GET_SERVICES) != 0) {
141             final int size = pkg.getServices().size();
142             if (size > 0) {
143                 int num = 0;
144                 final ServiceInfo[] res = new ServiceInfo[size];
145                 for (int i = 0; i < size; i++) {
146                     final ParsedService s = pkg.getServices().get(i);
147                     if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), s,
148                             flags)) {
149                         res[num++] = generateServiceInfo(pkg, s, flags, state,
150                                 applicationInfo, userId);
151                     }
152                 }
153                 info.services = ArrayUtils.trimToSize(res, num);
154             }
155         }
156         if ((flags & PackageManager.GET_PROVIDERS) != 0) {
157             final int size = pkg.getProviders().size();
158             if (size > 0) {
159                 int num = 0;
160                 final ProviderInfo[] res = new ProviderInfo[size];
161                 for (int i = 0; i < size; i++) {
162                     final ParsedProvider pr = pkg.getProviders()
163                             .get(i);
164                     if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), pr,
165                             flags)) {
166                         res[num++] = generateProviderInfo(pkg, pr, flags, state,
167                                 applicationInfo, userId);
168                     }
169                 }
170                 info.providers = ArrayUtils.trimToSize(res, num);
171             }
172         }
173         if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
174             int N = pkg.getInstrumentations().size();
175             if (N > 0) {
176                 info.instrumentation = new InstrumentationInfo[N];
177                 for (int i = 0; i < N; i++) {
178                     info.instrumentation[i] = generateInstrumentationInfo(
179                             pkg.getInstrumentations().get(i), pkg, flags, userId,
180                             true /* assignUserFields */);
181                 }
182             }
183         }
184 
185         return info;
186     }
187 
188     @Nullable
generateWithoutComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo)189     public static PackageInfo generateWithoutComponents(ParsingPackageRead pkg, int[] gids,
190             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
191             Set<String> grantedPermissions, PackageUserState state, int userId,
192             @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
193         if (!checkUseInstalled(pkg, state, flags)) {
194             return null;
195         }
196 
197         return generateWithoutComponentsUnchecked(pkg, gids, flags, firstInstallTime,
198                 lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);
199     }
200 
201     /**
202      * This bypasses critical checks that are necessary for usage with data passed outside of
203      * system server.
204      *
205      * Prefer {@link #generateWithoutComponents(ParsingPackageRead, int[], int, long, long, Set,
206      * PackageUserState, int, ApexInfo, ApplicationInfo)}.
207      */
208     @NonNull
generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo)209     public static PackageInfo generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids,
210             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
211             Set<String> grantedPermissions, PackageUserState state, int userId,
212             @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
213         PackageInfo pi = new PackageInfo();
214         pi.packageName = pkg.getPackageName();
215         pi.splitNames = pkg.getSplitNames();
216         pi.versionCode = pkg.getVersionCode();
217         pi.versionCodeMajor = pkg.getVersionCodeMajor();
218         pi.baseRevisionCode = pkg.getBaseRevisionCode();
219         pi.splitRevisionCodes = pkg.getSplitRevisionCodes();
220         pi.versionName = pkg.getVersionName();
221         pi.sharedUserId = pkg.getSharedUserId();
222         pi.sharedUserLabel = pkg.getSharedUserLabel();
223         pi.applicationInfo = applicationInfo;
224         pi.installLocation = pkg.getInstallLocation();
225         if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
226                 || (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
227             pi.requiredForAllUsers = pkg.isRequiredForAllUsers();
228         }
229         pi.restrictedAccountType = pkg.getRestrictedAccountType();
230         pi.requiredAccountType = pkg.getRequiredAccountType();
231         pi.overlayTarget = pkg.getOverlayTarget();
232         pi.targetOverlayableName = pkg.getOverlayTargetName();
233         pi.overlayCategory = pkg.getOverlayCategory();
234         pi.overlayPriority = pkg.getOverlayPriority();
235         pi.mOverlayIsStatic = pkg.isOverlayIsStatic();
236         pi.compileSdkVersion = pkg.getCompileSdkVersion();
237         pi.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();
238         pi.firstInstallTime = firstInstallTime;
239         pi.lastUpdateTime = lastUpdateTime;
240         if ((flags & PackageManager.GET_GIDS) != 0) {
241             pi.gids = gids;
242         }
243         if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {
244             int size = pkg.getConfigPreferences().size();
245             if (size > 0) {
246                 pi.configPreferences = new ConfigurationInfo[size];
247                 pkg.getConfigPreferences().toArray(pi.configPreferences);
248             }
249             size = pkg.getReqFeatures().size();
250             if (size > 0) {
251                 pi.reqFeatures = new FeatureInfo[size];
252                 pkg.getReqFeatures().toArray(pi.reqFeatures);
253             }
254             size = pkg.getFeatureGroups().size();
255             if (size > 0) {
256                 pi.featureGroups = new FeatureGroupInfo[size];
257                 pkg.getFeatureGroups().toArray(pi.featureGroups);
258             }
259         }
260         if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
261             int size = ArrayUtils.size(pkg.getPermissions());
262             if (size > 0) {
263                 pi.permissions = new PermissionInfo[size];
264                 for (int i = 0; i < size; i++) {
265                     pi.permissions[i] = generatePermissionInfo(pkg.getPermissions().get(i),
266                             flags);
267                 }
268             }
269             final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();
270             size = usesPermissions.size();
271             if (size > 0) {
272                 pi.requestedPermissions = new String[size];
273                 pi.requestedPermissionsFlags = new int[size];
274                 for (int i = 0; i < size; i++) {
275                     final ParsedUsesPermission usesPermission = usesPermissions.get(i);
276                     pi.requestedPermissions[i] = usesPermission.name;
277                     // The notion of required permissions is deprecated but for compatibility.
278                     pi.requestedPermissionsFlags[i] |=
279                             PackageInfo.REQUESTED_PERMISSION_REQUIRED;
280                     if (grantedPermissions != null
281                             && grantedPermissions.contains(usesPermission.name)) {
282                         pi.requestedPermissionsFlags[i] |=
283                                 PackageInfo.REQUESTED_PERMISSION_GRANTED;
284                     }
285                     if ((usesPermission.usesPermissionFlags
286                             & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0) {
287                         pi.requestedPermissionsFlags[i] |=
288                                 PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
289                     }
290                 }
291             }
292         }
293         if ((flags & PackageManager.GET_ATTRIBUTIONS) != 0) {
294             int size = ArrayUtils.size(pkg.getAttributions());
295             if (size > 0) {
296                 pi.attributions = new Attribution[size];
297                 for (int i = 0; i < size; i++) {
298                     pi.attributions[i] = generateAttribution(pkg.getAttributions().get(i));
299                 }
300             }
301             if (pkg.areAttributionsUserVisible()) {
302                 pi.applicationInfo.privateFlagsExt
303                         |= ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
304             } else {
305                 pi.applicationInfo.privateFlagsExt
306                         &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
307             }
308         } else {
309             pi.applicationInfo.privateFlagsExt
310                     &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
311         }
312 
313         if (apexInfo != null) {
314             File apexFile = new File(apexInfo.modulePath);
315 
316             pi.applicationInfo.sourceDir = apexFile.getPath();
317             pi.applicationInfo.publicSourceDir = apexFile.getPath();
318             if (apexInfo.isFactory) {
319                 pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
320                 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
321             } else {
322                 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
323                 pi.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
324             }
325             if (apexInfo.isActive) {
326                 pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
327             } else {
328                 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
329             }
330             pi.isApex = true;
331         }
332 
333         PackageParser.SigningDetails signingDetails = pkg.getSigningDetails();
334         // deprecated method of getting signing certificates
335         if ((flags & PackageManager.GET_SIGNATURES) != 0) {
336             if (signingDetails.hasPastSigningCertificates()) {
337                 // Package has included signing certificate rotation information.  Return the oldest
338                 // cert so that programmatic checks keep working even if unaware of key rotation.
339                 pi.signatures = new Signature[1];
340                 pi.signatures[0] = signingDetails.pastSigningCertificates[0];
341             } else if (signingDetails.hasSignatures()) {
342                 // otherwise keep old behavior
343                 int numberOfSigs = signingDetails.signatures.length;
344                 pi.signatures = new Signature[numberOfSigs];
345                 System.arraycopy(signingDetails.signatures, 0, pi.signatures, 0,
346                         numberOfSigs);
347             }
348         }
349 
350         // replacement for GET_SIGNATURES
351         if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
352             if (signingDetails != PackageParser.SigningDetails.UNKNOWN) {
353                 // only return a valid SigningInfo if there is signing information to report
354                 pi.signingInfo = new SigningInfo(signingDetails);
355             } else {
356                 pi.signingInfo = null;
357             }
358         }
359 
360         return pi;
361     }
362 
363     @Nullable
generateApplicationInfo(ParsingPackageRead pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId)364     public static ApplicationInfo generateApplicationInfo(ParsingPackageRead pkg,
365             @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {
366         if (pkg == null) {
367             return null;
368         }
369 
370         if (!checkUseInstalled(pkg, state, flags)) {
371             return null;
372         }
373 
374         return generateApplicationInfoUnchecked(pkg, flags, state, userId,
375                 true /* assignUserFields */);
376     }
377 
378     /**
379      * This bypasses critical checks that are necessary for usage with data passed outside of
380      * system server.
381      *
382      * Prefer {@link #generateApplicationInfo(ParsingPackageRead, int, PackageUserState, int)}.
383      *
384      * @param assignUserFields whether to fill the returned {@link ApplicationInfo} with user
385      *                         specific fields. This can be skipped when building from a system
386      *                         server package, as there are cached strings which can be used rather
387      *                         than querying and concatenating the comparatively expensive
388      *                         {@link Environment#getDataDirectory(String)}}.
389      */
390     @NonNull
generateApplicationInfoUnchecked(@onNull ParsingPackageRead pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId, boolean assignUserFields)391     public static ApplicationInfo generateApplicationInfoUnchecked(@NonNull ParsingPackageRead pkg,
392             @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
393             boolean assignUserFields) {
394         // Make shallow copy so we can store the metadata/libraries safely
395         ApplicationInfo ai = pkg.toAppInfoWithoutState();
396 
397         if (assignUserFields) {
398             assignUserFields(pkg, ai, userId);
399         }
400 
401         if ((flags & PackageManager.GET_META_DATA) == 0) {
402             ai.metaData = null;
403         }
404         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) {
405             ai.sharedLibraryFiles = null;
406             ai.sharedLibraryInfos = null;
407         }
408 
409         // CompatibilityMode is global state.
410         if (!android.content.pm.PackageParser.sCompatibilityModeEnabled) {
411             ai.disableCompatibilityMode();
412         }
413 
414         ai.flags |= flag(state.stopped, ApplicationInfo.FLAG_STOPPED)
415                 | flag(state.installed, ApplicationInfo.FLAG_INSTALLED)
416                 | flag(state.suspended, ApplicationInfo.FLAG_SUSPENDED);
417         ai.privateFlags |= flag(state.instantApp, ApplicationInfo.PRIVATE_FLAG_INSTANT)
418                 | flag(state.virtualPreload, ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
419                 | flag(state.hidden, ApplicationInfo.PRIVATE_FLAG_HIDDEN);
420 
421         if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
422             ai.enabled = true;
423         } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
424             ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
425         } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
426                 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
427             ai.enabled = false;
428         }
429         ai.enabledSetting = state.enabled;
430         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
431             ai.category = state.categoryHint;
432         }
433         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
434             ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
435         }
436         ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
437         final OverlayPaths overlayPaths = state.getAllOverlayPaths();
438         if (overlayPaths != null) {
439             ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]);
440             ai.overlayPaths = overlayPaths.getOverlayPaths().toArray(new String[0]);
441         }
442 
443         return ai;
444     }
445 
446     @Nullable
generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)447     public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a,
448             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
449             @Nullable ApplicationInfo applicationInfo, int userId) {
450         if (a == null) return null;
451         if (!checkUseInstalled(pkg, state, flags)) {
452             return null;
453         }
454         if (applicationInfo == null) {
455             applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
456         }
457         if (applicationInfo == null) {
458             return null;
459         }
460 
461         return generateActivityInfoUnchecked(a, flags, applicationInfo);
462     }
463 
464     /**
465      * This bypasses critical checks that are necessary for usage with data passed outside of
466      * system server.
467      *
468      * Prefer {@link #generateActivityInfo(ParsingPackageRead, ParsedActivity, int,
469      * PackageUserState, ApplicationInfo, int)}.
470      */
471     @NonNull
generateActivityInfoUnchecked(@onNull ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, @NonNull ApplicationInfo applicationInfo)472     public static ActivityInfo generateActivityInfoUnchecked(@NonNull ParsedActivity a,
473             @PackageManager.ComponentInfoFlags int flags,
474             @NonNull ApplicationInfo applicationInfo) {
475         // Make shallow copies so we can store the metadata safely
476         ActivityInfo ai = new ActivityInfo();
477         assignSharedFieldsForComponentInfo(ai, a);
478         ai.targetActivity = a.getTargetActivity();
479         ai.processName = a.getProcessName();
480         ai.exported = a.isExported();
481         ai.theme = a.getTheme();
482         ai.uiOptions = a.getUiOptions();
483         ai.parentActivityName = a.getParentActivityName();
484         ai.permission = a.getPermission();
485         ai.taskAffinity = a.getTaskAffinity();
486         ai.flags = a.getFlags();
487         ai.privateFlags = a.getPrivateFlags();
488         ai.launchMode = a.getLaunchMode();
489         ai.documentLaunchMode = a.getDocumentLaunchMode();
490         ai.maxRecents = a.getMaxRecents();
491         ai.configChanges = a.getConfigChanges();
492         ai.softInputMode = a.getSoftInputMode();
493         ai.persistableMode = a.getPersistableMode();
494         ai.lockTaskLaunchMode = a.getLockTaskLaunchMode();
495         ai.screenOrientation = a.getScreenOrientation();
496         ai.resizeMode = a.getResizeMode();
497         Float maxAspectRatio = a.getMaxAspectRatio();
498         ai.setMaxAspectRatio(maxAspectRatio != null ? maxAspectRatio : 0f);
499         Float minAspectRatio = a.getMinAspectRatio();
500         ai.setMinAspectRatio(minAspectRatio != null ? minAspectRatio : 0f);
501         ai.supportsSizeChanges = a.getSupportsSizeChanges();
502         ai.requestedVrComponent = a.getRequestedVrComponent();
503         ai.rotationAnimation = a.getRotationAnimation();
504         ai.colorMode = a.getColorMode();
505         ai.windowLayout = a.getWindowLayout();
506         ai.attributionTags = a.getAttributionTags();
507         if ((flags & PackageManager.GET_META_DATA) != 0) {
508             ai.metaData = a.getMetaData();
509         }
510         ai.applicationInfo = applicationInfo;
511         return ai;
512     }
513 
514     @Nullable
generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)515     public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a,
516             @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
517         return generateActivityInfo(pkg, a, flags, state, null, userId);
518     }
519 
520     @Nullable
generateServiceInfo(ParsingPackageRead pkg, ParsedService s, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)521     public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s,
522             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
523             @Nullable ApplicationInfo applicationInfo, int userId) {
524         if (s == null) return null;
525         if (!checkUseInstalled(pkg, state, flags)) {
526             return null;
527         }
528         if (applicationInfo == null) {
529             applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
530         }
531         if (applicationInfo == null) {
532             return null;
533         }
534 
535         return generateServiceInfoUnchecked(s, flags,  applicationInfo);
536     }
537 
538     /**
539      * This bypasses critical checks that are necessary for usage with data passed outside of
540      * system server.
541      *
542      * Prefer {@link #generateServiceInfo(ParsingPackageRead, ParsedService, int, PackageUserState,
543      * ApplicationInfo, int)}.
544      */
545     @NonNull
generateServiceInfoUnchecked(@onNull ParsedService s, @PackageManager.ComponentInfoFlags int flags, @NonNull ApplicationInfo applicationInfo)546     public static ServiceInfo generateServiceInfoUnchecked(@NonNull ParsedService s,
547             @PackageManager.ComponentInfoFlags int flags,
548             @NonNull ApplicationInfo applicationInfo) {
549         // Make shallow copies so we can store the metadata safely
550         ServiceInfo si = new ServiceInfo();
551         assignSharedFieldsForComponentInfo(si, s);
552         si.exported = s.isExported();
553         si.flags = s.getFlags();
554         si.permission = s.getPermission();
555         si.processName = s.getProcessName();
556         si.mForegroundServiceType = s.getForegroundServiceType();
557         si.applicationInfo = applicationInfo;
558         if ((flags & PackageManager.GET_META_DATA) != 0) {
559             si.metaData = s.getMetaData();
560         }
561         return si;
562     }
563 
564     @Nullable
generateServiceInfo(ParsingPackageRead pkg, ParsedService s, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)565     public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s,
566             @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
567         return generateServiceInfo(pkg, s, flags, state, null, userId);
568     }
569 
570     @Nullable
generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)571     public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p,
572             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
573             @Nullable ApplicationInfo applicationInfo, int userId) {
574         if (p == null) return null;
575         if (!checkUseInstalled(pkg, state, flags)) {
576             return null;
577         }
578         if (applicationInfo == null) {
579             applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
580         }
581         if (applicationInfo == null) {
582             return null;
583         }
584 
585         return generateProviderInfoUnchecked(p, flags, applicationInfo);
586     }
587 
588     /**
589      * This bypasses critical checks that are necessary for usage with data passed outside of
590      * system server.
591      *
592      * Prefer {@link #generateProviderInfo(ParsingPackageRead, ParsedProvider, int,
593      * PackageUserState, ApplicationInfo, int)}.
594      */
595     @NonNull
generateProviderInfoUnchecked(@onNull ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, @NonNull ApplicationInfo applicationInfo)596     public static ProviderInfo generateProviderInfoUnchecked(@NonNull ParsedProvider p,
597             @PackageManager.ComponentInfoFlags int flags,
598             @NonNull ApplicationInfo applicationInfo) {
599         // Make shallow copies so we can store the metadata safely
600         ProviderInfo pi = new ProviderInfo();
601         assignSharedFieldsForComponentInfo(pi, p);
602         pi.exported = p.isExported();
603         pi.flags = p.getFlags();
604         pi.processName = p.getProcessName();
605         pi.authority = p.getAuthority();
606         pi.isSyncable = p.isSyncable();
607         pi.readPermission = p.getReadPermission();
608         pi.writePermission = p.getWritePermission();
609         pi.grantUriPermissions = p.isGrantUriPermissions();
610         pi.forceUriPermissions = p.isForceUriPermissions();
611         pi.multiprocess = p.isMultiProcess();
612         pi.initOrder = p.getInitOrder();
613         pi.uriPermissionPatterns = p.getUriPermissionPatterns();
614         pi.pathPermissions = p.getPathPermissions();
615         if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
616             pi.uriPermissionPatterns = null;
617         }
618         if ((flags & PackageManager.GET_META_DATA) != 0) {
619             pi.metaData = p.getMetaData();
620         }
621         pi.applicationInfo = applicationInfo;
622         return pi;
623     }
624 
625     @Nullable
generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)626     public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p,
627             @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
628         return generateProviderInfo(pkg, p, flags, state, null, userId);
629     }
630 
631     /**
632      * @param assignUserFields see {@link #generateApplicationInfoUnchecked(ParsingPackageRead, int,
633      *                         PackageUserState, int, boolean)}
634      */
635     @Nullable
generateInstrumentationInfo(ParsedInstrumentation i, ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags int flags, int userId, boolean assignUserFields)636     public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
637             ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags int flags, int userId,
638             boolean assignUserFields) {
639         if (i == null) return null;
640 
641         InstrumentationInfo ii = new InstrumentationInfo();
642         assignSharedFieldsForPackageItemInfo(ii, i);
643         ii.targetPackage = i.getTargetPackage();
644         ii.targetProcesses = i.getTargetProcesses();
645         ii.handleProfiling = i.isHandleProfiling();
646         ii.functionalTest = i.isFunctionalTest();
647 
648         ii.sourceDir = pkg.getBaseApkPath();
649         ii.publicSourceDir = pkg.getBaseApkPath();
650         ii.splitNames = pkg.getSplitNames();
651         ii.splitSourceDirs = pkg.getSplitCodePaths();
652         ii.splitPublicSourceDirs = pkg.getSplitCodePaths();
653         ii.splitDependencies = pkg.getSplitDependencies();
654 
655         if (assignUserFields) {
656             assignUserFields(pkg, ii, userId);
657         }
658 
659         if ((flags & PackageManager.GET_META_DATA) == 0) {
660             return ii;
661         }
662         ii.metaData = i.getMetaData();
663         return ii;
664     }
665 
666     @Nullable
generatePermissionInfo(ParsedPermission p, @PackageManager.ComponentInfoFlags int flags)667     public static PermissionInfo generatePermissionInfo(ParsedPermission p,
668             @PackageManager.ComponentInfoFlags int flags) {
669         if (p == null) return null;
670 
671         PermissionInfo pi = new PermissionInfo(p.getBackgroundPermission());
672 
673         assignSharedFieldsForPackageItemInfo(pi, p);
674 
675         pi.group = p.getGroup();
676         pi.requestRes = p.getRequestRes();
677         pi.protectionLevel = p.getProtectionLevel();
678         pi.descriptionRes = p.getDescriptionRes();
679         pi.flags = p.getFlags();
680         pi.knownCerts = p.getKnownCerts();
681 
682         if ((flags & PackageManager.GET_META_DATA) == 0) {
683             return pi;
684         }
685         pi.metaData = p.getMetaData();
686         return pi;
687     }
688 
689     @Nullable
generatePermissionGroupInfo(ParsedPermissionGroup pg, @PackageManager.ComponentInfoFlags int flags)690     public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
691             @PackageManager.ComponentInfoFlags int flags) {
692         if (pg == null) return null;
693 
694         PermissionGroupInfo pgi = new PermissionGroupInfo(
695                 pg.getRequestDetailResourceId(),
696                 pg.getBackgroundRequestResourceId(),
697                 pg.getBackgroundRequestDetailResourceId()
698         );
699 
700         assignSharedFieldsForPackageItemInfo(pgi, pg);
701         pgi.descriptionRes = pg.getDescriptionRes();
702         pgi.priority = pg.getPriority();
703         pgi.requestRes = pg.getRequestRes();
704         pgi.flags = pg.getFlags();
705 
706         if ((flags & PackageManager.GET_META_DATA) == 0) {
707             return pgi;
708         }
709         pgi.metaData = pg.getMetaData();
710         return pgi;
711     }
712 
713     @Nullable
generateAttribution(ParsedAttribution pa)714     public static Attribution generateAttribution(ParsedAttribution pa) {
715         if (pa == null) return null;
716         return new Attribution(pa.tag, pa.label);
717     }
718 
assignSharedFieldsForComponentInfo(@onNull ComponentInfo componentInfo, @NonNull ParsedMainComponent mainComponent)719     private static void assignSharedFieldsForComponentInfo(@NonNull ComponentInfo componentInfo,
720             @NonNull ParsedMainComponent mainComponent) {
721         assignSharedFieldsForPackageItemInfo(componentInfo, mainComponent);
722         componentInfo.descriptionRes = mainComponent.getDescriptionRes();
723         componentInfo.directBootAware = mainComponent.isDirectBootAware();
724         componentInfo.enabled = mainComponent.isEnabled();
725         componentInfo.splitName = mainComponent.getSplitName();
726         componentInfo.attributionTags = mainComponent.getAttributionTags();
727     }
728 
assignSharedFieldsForPackageItemInfo( @onNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component)729     private static void assignSharedFieldsForPackageItemInfo(
730             @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component) {
731         packageItemInfo.nonLocalizedLabel = ComponentParseUtils.getNonLocalizedLabel(component);
732         packageItemInfo.icon = ComponentParseUtils.getIcon(component);
733 
734         packageItemInfo.banner = component.getBanner();
735         packageItemInfo.labelRes = component.getLabelRes();
736         packageItemInfo.logo = component.getLogo();
737         packageItemInfo.name = component.getName();
738         packageItemInfo.packageName = component.getPackageName();
739     }
740 
741     @CheckResult
flag(boolean hasFlag, int flag)742     private static int flag(boolean hasFlag, int flag) {
743         if (hasFlag) {
744             return flag;
745         } else {
746             return 0;
747         }
748     }
749 
750     /** @see ApplicationInfo#flags */
appInfoFlags(ParsingPackageRead pkg)751     public static int appInfoFlags(ParsingPackageRead pkg) {
752         // @formatter:off
753         return flag(pkg.isExternalStorage(), ApplicationInfo.FLAG_EXTERNAL_STORAGE)
754                 | flag(pkg.isBaseHardwareAccelerated(), ApplicationInfo.FLAG_HARDWARE_ACCELERATED)
755                 | flag(pkg.isAllowBackup(), ApplicationInfo.FLAG_ALLOW_BACKUP)
756                 | flag(pkg.isKillAfterRestore(), ApplicationInfo.FLAG_KILL_AFTER_RESTORE)
757                 | flag(pkg.isRestoreAnyVersion(), ApplicationInfo.FLAG_RESTORE_ANY_VERSION)
758                 | flag(pkg.isFullBackupOnly(), ApplicationInfo.FLAG_FULL_BACKUP_ONLY)
759                 | flag(pkg.isPersistent(), ApplicationInfo.FLAG_PERSISTENT)
760                 | flag(pkg.isDebuggable(), ApplicationInfo.FLAG_DEBUGGABLE)
761                 | flag(pkg.isVmSafeMode(), ApplicationInfo.FLAG_VM_SAFE_MODE)
762                 | flag(pkg.isHasCode(), ApplicationInfo.FLAG_HAS_CODE)
763                 | flag(pkg.isAllowTaskReparenting(), ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING)
764                 | flag(pkg.isAllowClearUserData(), ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)
765                 | flag(pkg.isLargeHeap(), ApplicationInfo.FLAG_LARGE_HEAP)
766                 | flag(pkg.isUsesCleartextTraffic(), ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC)
767                 | flag(pkg.isSupportsRtl(), ApplicationInfo.FLAG_SUPPORTS_RTL)
768                 | flag(pkg.isTestOnly(), ApplicationInfo.FLAG_TEST_ONLY)
769                 | flag(pkg.isMultiArch(), ApplicationInfo.FLAG_MULTIARCH)
770                 | flag(pkg.isExtractNativeLibs(), ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS)
771                 | flag(pkg.isGame(), ApplicationInfo.FLAG_IS_GAME)
772                 | flag(pkg.isSupportsSmallScreens(), ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS)
773                 | flag(pkg.isSupportsNormalScreens(), ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS)
774                 | flag(pkg.isSupportsLargeScreens(), ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS)
775                 | flag(pkg.isSupportsExtraLargeScreens(), ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS)
776                 | flag(pkg.isResizeable(), ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS)
777                 | flag(pkg.isAnyDensity(), ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES);
778         // @formatter:on
779     }
780 
781     /** @see ApplicationInfo#privateFlags */
appInfoPrivateFlags(ParsingPackageRead pkg)782     public static int appInfoPrivateFlags(ParsingPackageRead pkg) {
783         // @formatter:off
784         int privateFlags = flag(pkg.isStaticSharedLibrary(), ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY)
785                 | flag(pkg.isOverlay(), ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY)
786                 | flag(pkg.isIsolatedSplitLoading(), ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING)
787                 | flag(pkg.isHasDomainUrls(), ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS)
788                 | flag(pkg.isProfileableByShell(), ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL)
789                 | flag(pkg.isBackupInForeground(), ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND)
790                 | flag(pkg.isUseEmbeddedDex(), ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX)
791                 | flag(pkg.isDefaultToDeviceProtectedStorage(), ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE)
792                 | flag(pkg.isDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE)
793                 | flag(pkg.isPartiallyDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE)
794                 | flag(pkg.isAllowClearUserDataOnFailedRestore(), ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE)
795                 | flag(pkg.isAllowAudioPlaybackCapture(), ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE)
796                 | flag(pkg.isRequestLegacyExternalStorage(), ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE)
797                 | flag(pkg.isUsesNonSdkApi(), ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API)
798                 | flag(pkg.isHasFragileUserData(), ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA)
799                 | flag(pkg.isCantSaveState(), ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
800                 | flag(pkg.isResizeableActivityViaSdkVersion(), ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION)
801                 | flag(pkg.isAllowNativeHeapPointerTagging(), ApplicationInfo.PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING);
802         // @formatter:on
803 
804         Boolean resizeableActivity = pkg.getResizeableActivity();
805         if (resizeableActivity != null) {
806             if (resizeableActivity) {
807                 privateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
808             } else {
809                 privateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
810             }
811         }
812 
813         return privateFlags;
814     }
815 
816     /** @see ApplicationInfo#privateFlagsExt */
appInfoPrivateFlagsExt(ParsingPackageRead pkg)817     public static int appInfoPrivateFlagsExt(ParsingPackageRead pkg) {
818         // @formatter:off
819         int privateFlagsExt =
820                 flag(pkg.isProfileable(), ApplicationInfo.PRIVATE_FLAG_EXT_PROFILEABLE)
821                 | flag(pkg.hasRequestForegroundServiceExemption(),
822                         ApplicationInfo.PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION)
823                 | flag(pkg.areAttributionsUserVisible(),
824                         ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE);
825         // @formatter:on
826         return privateFlagsExt;
827     }
828 
checkUseInstalled(ParsingPackageRead pkg, PackageUserState state, @PackageManager.PackageInfoFlags int flags)829     private static boolean checkUseInstalled(ParsingPackageRead pkg, PackageUserState state,
830             @PackageManager.PackageInfoFlags int flags) {
831         // If available for the target user
832         return state.isAvailable(flags);
833     }
834 
835     @NonNull
getDataDir(ParsingPackageRead pkg, int userId)836     public static File getDataDir(ParsingPackageRead pkg, int userId) {
837         if ("android".equals(pkg.getPackageName())) {
838             return Environment.getDataSystemDirectory();
839         }
840 
841         if (pkg.isDefaultToDeviceProtectedStorage()
842                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
843             return getDeviceProtectedDataDir(pkg, userId);
844         } else {
845             return getCredentialProtectedDataDir(pkg, userId);
846         }
847     }
848 
849     @NonNull
getDeviceProtectedDataDir(ParsingPackageRead pkg, int userId)850     public static File getDeviceProtectedDataDir(ParsingPackageRead pkg, int userId) {
851         return Environment.getDataUserDePackageDirectory(pkg.getVolumeUuid(), userId,
852                 pkg.getPackageName());
853     }
854 
855     @NonNull
getCredentialProtectedDataDir(ParsingPackageRead pkg, int userId)856     public static File getCredentialProtectedDataDir(ParsingPackageRead pkg, int userId) {
857         return Environment.getDataUserCePackageDirectory(pkg.getVolumeUuid(), userId,
858                 pkg.getPackageName());
859     }
860 
assignUserFields(ParsingPackageRead pkg, ApplicationInfo info, int userId)861     private static void assignUserFields(ParsingPackageRead pkg, ApplicationInfo info, int userId) {
862         // This behavior is undefined for no-state ApplicationInfos when called by a public API,
863         // since the uid is never assigned by the system. It will always effectively be appId 0.
864         info.uid = UserHandle.getUid(userId, UserHandle.getAppId(info.uid));
865 
866         String pkgName = pkg.getPackageName();
867         if ("android".equals(pkgName)) {
868             info.dataDir = SYSTEM_DATA_PATH;
869             return;
870         }
871 
872         // For performance reasons, all these paths are built as strings
873         String baseDataDirPrefix =
874                 Environment.getDataDirectoryPath(pkg.getVolumeUuid()) + File.separator;
875         String userIdPkgSuffix = File.separator + userId + File.separator + pkgName;
876         info.credentialProtectedDataDir = baseDataDirPrefix + Environment.DIR_USER_CE
877                 + userIdPkgSuffix;
878         info.deviceProtectedDataDir = baseDataDirPrefix + Environment.DIR_USER_DE + userIdPkgSuffix;
879 
880         if (pkg.isDefaultToDeviceProtectedStorage()
881                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
882             info.dataDir = info.deviceProtectedDataDir;
883         } else {
884             info.dataDir = info.credentialProtectedDataDir;
885         }
886     }
887 
assignUserFields(ParsingPackageRead pkg, InstrumentationInfo info, int userId)888     private static void assignUserFields(ParsingPackageRead pkg, InstrumentationInfo info,
889             int userId) {
890         String pkgName = pkg.getPackageName();
891         if ("android".equals(pkgName)) {
892             info.dataDir = SYSTEM_DATA_PATH;
893             return;
894         }
895 
896         // For performance reasons, all these paths are built as strings
897         String baseDataDirPrefix =
898                 Environment.getDataDirectoryPath(pkg.getVolumeUuid()) + File.separator;
899         String userIdPkgSuffix = File.separator + userId + File.separator + pkgName;
900         info.credentialProtectedDataDir = baseDataDirPrefix + Environment.DIR_USER_CE
901                 + userIdPkgSuffix;
902         info.deviceProtectedDataDir = baseDataDirPrefix + Environment.DIR_USER_DE + userIdPkgSuffix;
903 
904         if (pkg.isDefaultToDeviceProtectedStorage()
905                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
906             info.dataDir = info.deviceProtectedDataDir;
907         } else {
908             info.dataDir = info.credentialProtectedDataDir;
909         }
910     }
911 }
912