1 /*
2  * Copyright (C) 2011 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.pm;
18 
19 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
20 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
21 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.UserIdInt;
26 import android.content.ComponentName;
27 import android.content.pm.ApplicationInfo;
28 import android.content.pm.IncrementalStatesInfo;
29 import android.content.pm.PackageManager.UninstallReason;
30 import android.content.pm.PackageParser;
31 import android.content.pm.PackageUserState;
32 import android.content.pm.Signature;
33 import android.content.pm.SuspendDialogInfo;
34 import android.content.pm.overlay.OverlayPaths;
35 import android.os.PersistableBundle;
36 import android.os.incremental.IncrementalManager;
37 import android.service.pm.PackageProto;
38 import android.util.ArrayMap;
39 import android.util.ArraySet;
40 import android.util.SparseArray;
41 import android.util.proto.ProtoOutputStream;
42 
43 import com.android.internal.annotations.VisibleForTesting;
44 import com.android.server.pm.parsing.pkg.AndroidPackage;
45 
46 import java.io.File;
47 import java.util.Arrays;
48 import java.util.Map;
49 import java.util.Objects;
50 import java.util.Set;
51 import java.util.function.Predicate;
52 
53 /**
54  * Settings base class for pending and resolved classes.
55  */
56 public abstract class PackageSettingBase extends SettingBase {
57 
58     private static final int[] EMPTY_INT_ARRAY = new int[0];
59 
60     public final String name;
61     final String realName;
62 
63     /** @see AndroidPackage#getPath() */
64     private File mPath;
65     private String mPathString;
66 
67     String[] usesStaticLibraries;
68     long[] usesStaticLibrariesVersions;
69 
70     /**
71      * The path under which native libraries have been unpacked. This path is
72      * always derived at runtime, and is only stored here for cleanup when a
73      * package is uninstalled.
74      */
75     @Deprecated
76     String legacyNativeLibraryPathString;
77 
78     /**
79      * The primary CPU abi for this package.
80      */
81     public String primaryCpuAbiString;
82 
83     /**
84      * The secondary CPU abi for this package.
85      */
86     public String secondaryCpuAbiString;
87 
88     /**
89      * The install time CPU override, if any. This value is written at install time
90      * and doesn't change during the life of an install. If non-null,
91      * {@code primaryCpuAbiString} will contain the same value.
92      */
93     String cpuAbiOverrideString;
94 
95     long timeStamp;
96     long firstInstallTime;
97     long lastUpdateTime;
98     long versionCode;
99 
100     boolean uidError;
101 
102     PackageSignatures signatures;
103 
104     boolean installPermissionsFixed;
105 
106     PackageKeySetData keySetData = new PackageKeySetData();
107 
108     static final PackageUserState DEFAULT_USER_STATE = new PackageUserState();
109 
110     // Whether this package is currently stopped, thus can not be
111     // started until explicitly launched by the user.
112     private final SparseArray<PackageUserState> mUserState = new SparseArray<>();
113 
114     /**
115      * Non-persisted value. During an "upgrade without restart", we need the set
116      * of all previous code paths so we can surgically add the new APKs to the
117      * active classloader. If at any point an application is upgraded with a
118      * restart, this field will be cleared since the classloader would be created
119      * using the full set of code paths when the package's process is started.
120      */
121     Set<String> mOldCodePaths;
122 
123     /** Information about how this package was installed/updated. */
124     @NonNull InstallSource installSource;
125     /** UUID of {@link VolumeInfo} hosting this app */
126     String volumeUuid;
127     /** The category of this app, as hinted by the installer */
128     int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
129     /** Whether or not an update is available. Ostensibly only for instant apps. */
130     boolean updateAvailable;
131 
132     boolean forceQueryableOverride;
133 
134     @NonNull
135     public IncrementalStates incrementalStates;
136 
PackageSettingBase(String name, String realName, @NonNull File path, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, String cpuAbiOverrideString, long pVersionCode, int pkgFlags, int pkgPrivateFlags, String[] usesStaticLibraries, long[] usesStaticLibrariesVersions)137     PackageSettingBase(String name, String realName, @NonNull File path,
138             String legacyNativeLibraryPathString, String primaryCpuAbiString,
139             String secondaryCpuAbiString, String cpuAbiOverrideString,
140             long pVersionCode, int pkgFlags, int pkgPrivateFlags,
141             String[] usesStaticLibraries, long[] usesStaticLibrariesVersions) {
142         super(pkgFlags, pkgPrivateFlags);
143         this.name = name;
144         this.realName = realName;
145         this.usesStaticLibraries = usesStaticLibraries;
146         this.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
147         setPath(path);
148         this.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
149         this.primaryCpuAbiString = primaryCpuAbiString;
150         this.secondaryCpuAbiString = secondaryCpuAbiString;
151         this.cpuAbiOverrideString = cpuAbiOverrideString;
152         this.versionCode = pVersionCode;
153         this.signatures = new PackageSignatures();
154         this.installSource = InstallSource.EMPTY;
155         this.incrementalStates = new IncrementalStates();
156     }
157 
158     /**
159      * New instance of PackageSetting with one-level-deep cloning.
160      * <p>
161      * IMPORTANT: With a shallow copy, we do NOT create new contained objects.
162      * This means, for example, changes to the user state of the original PackageSetting
163      * will also change the user state in its copy.
164      */
PackageSettingBase(PackageSettingBase base, String realName)165     PackageSettingBase(PackageSettingBase base, String realName) {
166         super(base);
167         name = base.name;
168         this.realName = realName;
169         doCopy(base);
170     }
171 
172     // A copy constructor used to create snapshots.  The boolean is present only to
173     // match up with the constructor in PackageSetting.
PackageSettingBase(PackageSettingBase orig, boolean snapshot)174     PackageSettingBase(PackageSettingBase orig, boolean snapshot) {
175         super(orig);
176         name = orig.name;
177         realName = orig.realName;
178         doCopy(orig);
179         // Clone the user states.
180         for (int i = 0; i < mUserState.size(); i++) {
181             mUserState.put(mUserState.keyAt(i), new PackageUserState(mUserState.valueAt(i)));
182         }
183     }
184 
setInstallerPackageName(String packageName)185     public void setInstallerPackageName(String packageName) {
186         installSource = installSource.setInstallerPackage(packageName);
187         onChanged();
188     }
189 
setInstallSource(InstallSource installSource)190     public void setInstallSource(InstallSource installSource) {
191         this.installSource = Objects.requireNonNull(installSource);
192         onChanged();
193     }
194 
removeInstallerPackage(String packageName)195     void removeInstallerPackage(String packageName) {
196         installSource = installSource.removeInstallerPackage(packageName);
197         onChanged();
198     }
199 
setIsOrphaned(boolean isOrphaned)200     public void setIsOrphaned(boolean isOrphaned) {
201         installSource = installSource.setIsOrphaned(isOrphaned);
202         onChanged();
203     }
204 
setVolumeUuid(String volumeUuid)205     public void setVolumeUuid(String volumeUuid) {
206         this.volumeUuid = volumeUuid;
207         onChanged();
208     }
209 
getVolumeUuid()210     public String getVolumeUuid() {
211         return volumeUuid;
212     }
213 
setTimeStamp(long newStamp)214     public void setTimeStamp(long newStamp) {
215         timeStamp = newStamp;
216         onChanged();
217     }
218 
setUpdateAvailable(boolean updateAvailable)219     public void setUpdateAvailable(boolean updateAvailable) {
220         this.updateAvailable = updateAvailable;
221         onChanged();
222     }
223 
isUpdateAvailable()224     public boolean isUpdateAvailable() {
225         return updateAvailable;
226     }
227 
isSharedUser()228     public boolean isSharedUser() {
229         return false;
230     }
231 
getSignatures()232     public Signature[] getSignatures() {
233         return signatures.mSigningDetails.signatures;
234     }
235 
getSigningDetails()236     public PackageParser.SigningDetails getSigningDetails() {
237         return signatures.mSigningDetails;
238     }
239 
240     /**
241      * Makes a shallow copy of the given package settings.
242      *
243      * NOTE: For some fields [such as keySetData, signatures, mUserState, verificationInfo, etc...],
244      * the original object is copied and a new one is not created.
245      */
copyFrom(PackageSettingBase orig)246     public void copyFrom(PackageSettingBase orig) {
247         super.copyFrom(orig);
248         doCopy(orig);
249     }
250 
doCopy(PackageSettingBase orig)251     private void doCopy(PackageSettingBase orig) {
252         setPath(orig.getPath());
253         cpuAbiOverrideString = orig.cpuAbiOverrideString;
254         firstInstallTime = orig.firstInstallTime;
255         installPermissionsFixed = orig.installPermissionsFixed;
256         installSource = orig.installSource;
257         keySetData = orig.keySetData;
258         lastUpdateTime = orig.lastUpdateTime;
259         legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
260         // Intentionally skip mOldCodePaths; it's not relevant for copies
261         primaryCpuAbiString = orig.primaryCpuAbiString;
262         secondaryCpuAbiString = orig.secondaryCpuAbiString;
263         signatures = orig.signatures;
264         timeStamp = orig.timeStamp;
265         uidError = orig.uidError;
266         mUserState.clear();
267         for (int i = 0; i < orig.mUserState.size(); i++) {
268             mUserState.put(orig.mUserState.keyAt(i), orig.mUserState.valueAt(i));
269         }
270         versionCode = orig.versionCode;
271         volumeUuid = orig.volumeUuid;
272         categoryHint = orig.categoryHint;
273         usesStaticLibraries = orig.usesStaticLibraries != null
274                 ? Arrays.copyOf(orig.usesStaticLibraries,
275                         orig.usesStaticLibraries.length) : null;
276         usesStaticLibrariesVersions = orig.usesStaticLibrariesVersions != null
277                 ? Arrays.copyOf(orig.usesStaticLibrariesVersions,
278                        orig.usesStaticLibrariesVersions.length) : null;
279         updateAvailable = orig.updateAvailable;
280         forceQueryableOverride = orig.forceQueryableOverride;
281         incrementalStates = orig.incrementalStates;
282     }
283 
284     @VisibleForTesting
modifyUserState(int userId)285     PackageUserState modifyUserState(int userId) {
286         PackageUserState state = mUserState.get(userId);
287         if (state == null) {
288             state = new PackageUserState();
289             mUserState.put(userId, state);
290             onChanged();
291         }
292         return state;
293     }
294 
readUserState(int userId)295     public PackageUserState readUserState(int userId) {
296         PackageUserState state = mUserState.get(userId);
297         if (state == null) {
298             return DEFAULT_USER_STATE;
299         }
300         state.categoryHint = categoryHint;
301         return state;
302     }
303 
setEnabled(int state, int userId, String callingPackage)304     void setEnabled(int state, int userId, String callingPackage) {
305         PackageUserState st = modifyUserState(userId);
306         st.enabled = state;
307         st.lastDisableAppCaller = callingPackage;
308         onChanged();
309     }
310 
getEnabled(int userId)311     int getEnabled(int userId) {
312         return readUserState(userId).enabled;
313     }
314 
getLastDisabledAppCaller(int userId)315     String getLastDisabledAppCaller(int userId) {
316         return readUserState(userId).lastDisableAppCaller;
317     }
318 
setInstalled(boolean inst, int userId)319     void setInstalled(boolean inst, int userId) {
320         modifyUserState(userId).installed = inst;
321         onChanged();
322     }
323 
getInstalled(int userId)324     boolean getInstalled(int userId) {
325         return readUserState(userId).installed;
326     }
327 
getInstallReason(int userId)328     int getInstallReason(int userId) {
329         return readUserState(userId).installReason;
330     }
331 
setInstallReason(int installReason, int userId)332     void setInstallReason(int installReason, int userId) {
333         modifyUserState(userId).installReason = installReason;
334         onChanged();
335     }
336 
getUninstallReason(int userId)337     int getUninstallReason(int userId) {
338         return readUserState(userId).uninstallReason;
339     }
340 
setUninstallReason(@ninstallReason int uninstallReason, int userId)341     void setUninstallReason(@UninstallReason int uninstallReason, int userId) {
342         modifyUserState(userId).uninstallReason = uninstallReason;
343         onChanged();
344     }
345 
setOverlayPaths(OverlayPaths overlayPaths, int userId)346     boolean setOverlayPaths(OverlayPaths overlayPaths, int userId) {
347         boolean returnValue = modifyUserState(userId).setOverlayPaths(overlayPaths);
348         onChanged();
349         return returnValue;
350     }
351 
getOverlayPaths(int userId)352     OverlayPaths getOverlayPaths(int userId) {
353         return readUserState(userId).getOverlayPaths();
354     }
355 
setOverlayPathsForLibrary(String libName, OverlayPaths overlayPaths, int userId)356     boolean setOverlayPathsForLibrary(String libName, OverlayPaths overlayPaths,
357             int userId) {
358         boolean returnValue =  modifyUserState(userId)
359                 .setSharedLibraryOverlayPaths(libName, overlayPaths);
360         onChanged();
361         return returnValue;
362     }
363 
getOverlayPathsForLibrary(int userId)364     Map<String, OverlayPaths> getOverlayPathsForLibrary(int userId) {
365         return readUserState(userId).getSharedLibraryOverlayPaths();
366     }
367 
368     /**
369      * Only use for testing. Do NOT use in production code.
370      */
371     @VisibleForTesting
372     @Deprecated
getUserState()373     public SparseArray<PackageUserState> getUserState() {
374         return mUserState;
375     }
376 
isAnyInstalled(int[] users)377     boolean isAnyInstalled(int[] users) {
378         for (int user: users) {
379             if (readUserState(user).installed) {
380                 return true;
381             }
382         }
383         return false;
384     }
385 
queryInstalledUsers(int[] users, boolean installed)386     int[] queryInstalledUsers(int[] users, boolean installed) {
387         int num = 0;
388         for (int user : users) {
389             if (getInstalled(user) == installed) {
390                 num++;
391             }
392         }
393         int[] res = new int[num];
394         num = 0;
395         for (int user : users) {
396             if (getInstalled(user) == installed) {
397                 res[num] = user;
398                 num++;
399             }
400         }
401         return res;
402     }
403 
getCeDataInode(int userId)404     long getCeDataInode(int userId) {
405         return readUserState(userId).ceDataInode;
406     }
407 
setCeDataInode(long ceDataInode, int userId)408     void setCeDataInode(long ceDataInode, int userId) {
409         modifyUserState(userId).ceDataInode = ceDataInode;
410         onChanged();
411     }
412 
getStopped(int userId)413     boolean getStopped(int userId) {
414         return readUserState(userId).stopped;
415     }
416 
setStopped(boolean stop, int userId)417     void setStopped(boolean stop, int userId) {
418         modifyUserState(userId).stopped = stop;
419         onChanged();
420     }
421 
getNotLaunched(int userId)422     boolean getNotLaunched(int userId) {
423         return readUserState(userId).notLaunched;
424     }
425 
setNotLaunched(boolean stop, int userId)426     void setNotLaunched(boolean stop, int userId) {
427         modifyUserState(userId).notLaunched = stop;
428         onChanged();
429     }
430 
getHidden(int userId)431     boolean getHidden(int userId) {
432         return readUserState(userId).hidden;
433     }
434 
setHidden(boolean hidden, int userId)435     void setHidden(boolean hidden, int userId) {
436         modifyUserState(userId).hidden = hidden;
437         onChanged();
438     }
439 
getDistractionFlags(int userId)440     int getDistractionFlags(int userId) {
441         return readUserState(userId).distractionFlags;
442     }
443 
setDistractionFlags(int distractionFlags, int userId)444     void setDistractionFlags(int distractionFlags, int userId) {
445         modifyUserState(userId).distractionFlags = distractionFlags;
446         onChanged();
447     }
448 
getSuspended(int userId)449     boolean getSuspended(int userId) {
450         return readUserState(userId).suspended;
451     }
452 
isSuspendedBy(String suspendingPackage, int userId)453     boolean isSuspendedBy(String suspendingPackage, int userId) {
454         final PackageUserState state = readUserState(userId);
455         return state.suspendParams != null && state.suspendParams.containsKey(suspendingPackage);
456     }
457 
addOrUpdateSuspension(String suspendingPackage, SuspendDialogInfo dialogInfo, PersistableBundle appExtras, PersistableBundle launcherExtras, int userId)458     boolean addOrUpdateSuspension(String suspendingPackage, SuspendDialogInfo dialogInfo,
459             PersistableBundle appExtras, PersistableBundle launcherExtras, int userId) {
460         final PackageUserState existingUserState = modifyUserState(userId);
461         final PackageUserState.SuspendParams newSuspendParams =
462                 PackageUserState.SuspendParams.getInstanceOrNull(dialogInfo, appExtras,
463                         launcherExtras);
464         if (existingUserState.suspendParams == null) {
465             existingUserState.suspendParams = new ArrayMap<>();
466         }
467         final PackageUserState.SuspendParams oldSuspendParams =
468                 existingUserState.suspendParams.put(suspendingPackage, newSuspendParams);
469         existingUserState.suspended = true;
470         onChanged();
471         return !Objects.equals(oldSuspendParams, newSuspendParams);
472     }
473 
removeSuspension(String suspendingPackage, int userId)474     boolean removeSuspension(String suspendingPackage, int userId) {
475         boolean wasModified = false;
476         final PackageUserState existingUserState = modifyUserState(userId);
477         if (existingUserState.suspendParams != null) {
478             if (existingUserState.suspendParams.remove(suspendingPackage) != null) {
479                 wasModified = true;
480             }
481             if (existingUserState.suspendParams.size() == 0) {
482                 existingUserState.suspendParams = null;
483             }
484         }
485         existingUserState.suspended = (existingUserState.suspendParams != null);
486         onChanged();
487         return wasModified;
488     }
489 
removeSuspension(Predicate<String> suspendingPackagePredicate, int userId)490     void removeSuspension(Predicate<String> suspendingPackagePredicate, int userId) {
491         final PackageUserState existingUserState = modifyUserState(userId);
492         if (existingUserState.suspendParams != null) {
493             for (int i = existingUserState.suspendParams.size() - 1; i >= 0; i--) {
494                 final String suspendingPackage = existingUserState.suspendParams.keyAt(i);
495                 if (suspendingPackagePredicate.test(suspendingPackage)) {
496                     existingUserState.suspendParams.removeAt(i);
497                 }
498             }
499             if (existingUserState.suspendParams.size() == 0) {
500                 existingUserState.suspendParams = null;
501             }
502         }
503         existingUserState.suspended = (existingUserState.suspendParams != null);
504         onChanged();
505     }
506 
getInstantApp(int userId)507     public boolean getInstantApp(int userId) {
508         return readUserState(userId).instantApp;
509     }
510 
setInstantApp(boolean instantApp, int userId)511     void setInstantApp(boolean instantApp, int userId) {
512         modifyUserState(userId).instantApp = instantApp;
513         onChanged();
514     }
515 
getVirtulalPreload(int userId)516     boolean getVirtulalPreload(int userId) {
517         return readUserState(userId).virtualPreload;
518     }
519 
setVirtualPreload(boolean virtualPreload, int userId)520     void setVirtualPreload(boolean virtualPreload, int userId) {
521         modifyUserState(userId).virtualPreload = virtualPreload;
522         onChanged();
523     }
524 
setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped, boolean notLaunched, boolean hidden, int distractionFlags, boolean suspended, ArrayMap<String, PackageUserState.SuspendParams> suspendParams, boolean instantApp, boolean virtualPreload, String lastDisableAppCaller, ArraySet<String> enabledComponents, ArraySet<String> disabledComponents, int installReason, int uninstallReason, String harmfulAppWarning, String splashScreenTheme)525     void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
526             boolean notLaunched, boolean hidden, int distractionFlags, boolean suspended,
527             ArrayMap<String, PackageUserState.SuspendParams> suspendParams, boolean instantApp,
528             boolean virtualPreload, String lastDisableAppCaller,
529             ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
530             int installReason, int uninstallReason, String harmfulAppWarning,
531             String splashScreenTheme) {
532         PackageUserState state = modifyUserState(userId);
533         state.ceDataInode = ceDataInode;
534         state.enabled = enabled;
535         state.installed = installed;
536         state.stopped = stopped;
537         state.notLaunched = notLaunched;
538         state.hidden = hidden;
539         state.distractionFlags = distractionFlags;
540         state.suspended = suspended;
541         state.suspendParams = suspendParams;
542         state.lastDisableAppCaller = lastDisableAppCaller;
543         state.enabledComponents = enabledComponents;
544         state.disabledComponents = disabledComponents;
545         state.installReason = installReason;
546         state.uninstallReason = uninstallReason;
547         state.instantApp = instantApp;
548         state.virtualPreload = virtualPreload;
549         state.harmfulAppWarning = harmfulAppWarning;
550         state.splashScreenTheme = splashScreenTheme;
551         onChanged();
552     }
553 
setUserState(int userId, PackageUserState otherState)554     void setUserState(int userId, PackageUserState otherState) {
555         setUserState(userId, otherState.ceDataInode, otherState.enabled, otherState.installed,
556                 otherState.stopped, otherState.notLaunched, otherState.hidden,
557                 otherState.distractionFlags, otherState.suspended, otherState.suspendParams,
558                 otherState.instantApp,
559                 otherState.virtualPreload, otherState.lastDisableAppCaller,
560                 otherState.enabledComponents, otherState.disabledComponents,
561                 otherState.installReason, otherState.uninstallReason, otherState.harmfulAppWarning,
562                 otherState.splashScreenTheme);
563     }
564 
getEnabledComponents(int userId)565     ArraySet<String> getEnabledComponents(int userId) {
566         return readUserState(userId).enabledComponents;
567     }
568 
getDisabledComponents(int userId)569     ArraySet<String> getDisabledComponents(int userId) {
570         return readUserState(userId).disabledComponents;
571     }
572 
setEnabledComponents(ArraySet<String> components, int userId)573     void setEnabledComponents(ArraySet<String> components, int userId) {
574         modifyUserState(userId).enabledComponents = components;
575         onChanged();
576     }
577 
setDisabledComponents(ArraySet<String> components, int userId)578     void setDisabledComponents(ArraySet<String> components, int userId) {
579         modifyUserState(userId).disabledComponents = components;
580         onChanged();
581     }
582 
setEnabledComponentsCopy(ArraySet<String> components, int userId)583     void setEnabledComponentsCopy(ArraySet<String> components, int userId) {
584         modifyUserState(userId).enabledComponents = components != null
585                 ? new ArraySet<String>(components) : null;
586         onChanged();
587     }
588 
setDisabledComponentsCopy(ArraySet<String> components, int userId)589     void setDisabledComponentsCopy(ArraySet<String> components, int userId) {
590         modifyUserState(userId).disabledComponents = components != null
591                 ? new ArraySet<String>(components) : null;
592         onChanged();
593     }
594 
modifyUserStateComponents(int userId, boolean disabled, boolean enabled)595     PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) {
596         PackageUserState state = modifyUserState(userId);
597         boolean changed = false;
598         if (disabled && state.disabledComponents == null) {
599             state.disabledComponents = new ArraySet<String>(1);
600             changed = true;
601         }
602         if (enabled && state.enabledComponents == null) {
603             state.enabledComponents = new ArraySet<String>(1);
604             changed = true;
605         }
606         if (changed) {
607             onChanged();
608         }
609         return state;
610     }
611 
addDisabledComponent(String componentClassName, int userId)612     void addDisabledComponent(String componentClassName, int userId) {
613         modifyUserStateComponents(userId, true, false).disabledComponents.add(componentClassName);
614         onChanged();
615     }
616 
addEnabledComponent(String componentClassName, int userId)617     void addEnabledComponent(String componentClassName, int userId) {
618         modifyUserStateComponents(userId, false, true).enabledComponents.add(componentClassName);
619         onChanged();
620     }
621 
enableComponentLPw(String componentClassName, int userId)622     boolean enableComponentLPw(String componentClassName, int userId) {
623         PackageUserState state = modifyUserStateComponents(userId, false, true);
624         boolean changed = state.disabledComponents != null
625                 ? state.disabledComponents.remove(componentClassName) : false;
626         changed |= state.enabledComponents.add(componentClassName);
627         if (changed) {
628             onChanged();
629         }
630         return changed;
631     }
632 
disableComponentLPw(String componentClassName, int userId)633     boolean disableComponentLPw(String componentClassName, int userId) {
634         PackageUserState state = modifyUserStateComponents(userId, true, false);
635         boolean changed = state.enabledComponents != null
636                 ? state.enabledComponents.remove(componentClassName) : false;
637         changed |= state.disabledComponents.add(componentClassName);
638         if (changed) {
639             onChanged();
640         }
641         return changed;
642     }
643 
restoreComponentLPw(String componentClassName, int userId)644     boolean restoreComponentLPw(String componentClassName, int userId) {
645         PackageUserState state = modifyUserStateComponents(userId, true, true);
646         boolean changed = state.disabledComponents != null
647                 ? state.disabledComponents.remove(componentClassName) : false;
648         changed |= state.enabledComponents != null
649                 ? state.enabledComponents.remove(componentClassName) : false;
650         if (changed) {
651             onChanged();
652         }
653         return changed;
654     }
655 
getCurrentEnabledStateLPr(String componentName, int userId)656     int getCurrentEnabledStateLPr(String componentName, int userId) {
657         PackageUserState state = readUserState(userId);
658         if (state.enabledComponents != null && state.enabledComponents.contains(componentName)) {
659             return COMPONENT_ENABLED_STATE_ENABLED;
660         } else if (state.disabledComponents != null
661                 && state.disabledComponents.contains(componentName)) {
662             return COMPONENT_ENABLED_STATE_DISABLED;
663         } else {
664             return COMPONENT_ENABLED_STATE_DEFAULT;
665         }
666     }
667 
removeUser(int userId)668     void removeUser(int userId) {
669         mUserState.delete(userId);
670         onChanged();
671     }
672 
getNotInstalledUserIds()673     public int[] getNotInstalledUserIds() {
674         int count = 0;
675         int userStateCount = mUserState.size();
676         for (int i = 0; i < userStateCount; i++) {
677             if (!mUserState.valueAt(i).installed) {
678                 count++;
679             }
680         }
681         if (count == 0) return EMPTY_INT_ARRAY;
682         int[] excludedUserIds = new int[count];
683         int idx = 0;
684         for (int i = 0; i < userStateCount; i++) {
685             if (!mUserState.valueAt(i).installed) {
686                 excludedUserIds[idx++] = mUserState.keyAt(i);
687             }
688         }
689         return excludedUserIds;
690     }
691 
writeUsersInfoToProto(ProtoOutputStream proto, long fieldId)692     protected void writeUsersInfoToProto(ProtoOutputStream proto, long fieldId) {
693         int count = mUserState.size();
694         for (int i = 0; i < count; i++) {
695             final long userToken = proto.start(fieldId);
696             final int userId = mUserState.keyAt(i);
697             final PackageUserState state = mUserState.valueAt(i);
698             proto.write(PackageProto.UserInfoProto.ID, userId);
699             final int installType;
700             if (state.instantApp) {
701                 installType = PackageProto.UserInfoProto.INSTANT_APP_INSTALL;
702             } else if (state.installed) {
703                 installType = PackageProto.UserInfoProto.FULL_APP_INSTALL;
704             } else {
705                 installType = PackageProto.UserInfoProto.NOT_INSTALLED_FOR_USER;
706             }
707             proto.write(PackageProto.UserInfoProto.INSTALL_TYPE, installType);
708             proto.write(PackageProto.UserInfoProto.IS_HIDDEN, state.hidden);
709             proto.write(PackageProto.UserInfoProto.DISTRACTION_FLAGS, state.distractionFlags);
710             proto.write(PackageProto.UserInfoProto.IS_SUSPENDED, state.suspended);
711             if (state.suspended) {
712                 for (int j = 0; j < state.suspendParams.size(); j++) {
713                     proto.write(PackageProto.UserInfoProto.SUSPENDING_PACKAGE,
714                             state.suspendParams.keyAt(j));
715                 }
716             }
717             proto.write(PackageProto.UserInfoProto.IS_STOPPED, state.stopped);
718             proto.write(PackageProto.UserInfoProto.IS_LAUNCHED, !state.notLaunched);
719             proto.write(PackageProto.UserInfoProto.ENABLED_STATE, state.enabled);
720             proto.write(
721                     PackageProto.UserInfoProto.LAST_DISABLED_APP_CALLER,
722                     state.lastDisableAppCaller);
723             proto.end(userToken);
724         }
725     }
726 
setHarmfulAppWarning(int userId, String harmfulAppWarning)727     void setHarmfulAppWarning(int userId, String harmfulAppWarning) {
728         PackageUserState userState = modifyUserState(userId);
729         userState.harmfulAppWarning = harmfulAppWarning;
730         onChanged();
731     }
732 
getHarmfulAppWarning(int userId)733     String getHarmfulAppWarning(int userId) {
734         PackageUserState userState = readUserState(userId);
735         return userState.harmfulAppWarning;
736     }
737 
738     /**
739      * @see #mPath
740      */
setPath(@onNull File path)741     PackageSettingBase setPath(@NonNull File path) {
742         this.mPath = path;
743         this.mPathString = path.toString();
744         onChanged();
745         return this;
746     }
747 
748     /** @see #mPath */
getPath()749     File getPath() {
750         return mPath;
751     }
752 
753     /** @see #mPath */
getPathString()754     String getPathString() {
755         return mPathString;
756     }
757 
758     /**
759      * @see PackageUserState#overrideLabelAndIcon(ComponentName, String, Integer)
760      *
761      * @param userId the specific user to change the label/icon for
762      */
763     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
overrideNonLocalizedLabelAndIcon(@onNull ComponentName component, @Nullable String label, @Nullable Integer icon, @UserIdInt int userId)764     public boolean overrideNonLocalizedLabelAndIcon(@NonNull ComponentName component,
765             @Nullable String label, @Nullable Integer icon, @UserIdInt int userId) {
766         boolean returnValue = modifyUserState(userId).overrideLabelAndIcon(component, label, icon);
767         onChanged();
768         return returnValue;
769     }
770 
771     /**
772      * @see PackageUserState#resetOverrideComponentLabelIcon()
773      *
774      * @param userId the specific user to reset
775      */
resetOverrideComponentLabelIcon(@serIdInt int userId)776     public void resetOverrideComponentLabelIcon(@UserIdInt int userId) {
777         modifyUserState(userId).resetOverrideComponentLabelIcon();
778         onChanged();
779     }
780 
781     /**
782      * @param userId    the specified user to modify the theme for
783      * @param themeName the theme name to persist
784      * @see android.window.SplashScreen#setSplashScreenTheme(int)
785      */
setSplashScreenTheme(@serIdInt int userId, @Nullable String themeName)786     public void setSplashScreenTheme(@UserIdInt int userId, @Nullable String themeName) {
787         modifyUserState(userId).splashScreenTheme = themeName;
788         onChanged();
789     }
790 
791     /**
792      * @param userId the specified user to get the theme setting from
793      * @return the theme name previously persisted for the user or null
794      * if no splashscreen theme is persisted.
795      * @see android.window.SplashScreen#setSplashScreenTheme(int)
796      */
797     @Nullable
getSplashScreenTheme(@serIdInt int userId)798     public String getSplashScreenTheme(@UserIdInt int userId) {
799         return readUserState(userId).splashScreenTheme;
800     }
801 
802     /**
803      * @return True if package is still being loaded, false if the package is fully loaded.
804      */
isPackageLoading()805     public boolean isPackageLoading() {
806         return getIncrementalStates().isLoading();
807     }
808 
809     /**
810      * @return all current states in a Parcelable.
811      */
getIncrementalStates()812     public IncrementalStatesInfo getIncrementalStates() {
813         return incrementalStates.getIncrementalStatesInfo();
814     }
815 
816     /**
817      * Called to indicate that the package installation has been committed. This will create a
818      * new loading state with default values.
819      * For a package installed on Incremental, the loading state is true.
820      * For non-Incremental packages, the loading state is false.
821      */
setStatesOnCommit()822     public void setStatesOnCommit() {
823         incrementalStates.onCommit(IncrementalManager.isIncrementalPath(getPathString()));
824         onChanged();
825     }
826 
827     /**
828      * Called to set the callback to listen for loading state changes.
829      */
setIncrementalStatesCallback(IncrementalStates.Callback callback)830     public void setIncrementalStatesCallback(IncrementalStates.Callback callback) {
831         incrementalStates.setCallback(callback);
832         onChanged();
833     }
834 
835     /**
836      * Called to report progress changes. This might trigger loading state change.
837      * @see IncrementalStates#setProgress(float)
838      */
setLoadingProgress(float progress)839     public void setLoadingProgress(float progress) {
840         incrementalStates.setProgress(progress);
841         onChanged();
842     }
843 
getFirstInstallTime()844     public long getFirstInstallTime() {
845         return firstInstallTime;
846     }
847 
getName()848     public String getName() {
849         return name;
850     }
851 
updateFrom(PackageSettingBase other)852     protected PackageSettingBase updateFrom(PackageSettingBase other) {
853         super.copyFrom(other);
854         setPath(other.getPath());
855         this.usesStaticLibraries = other.usesStaticLibraries;
856         this.usesStaticLibrariesVersions = other.usesStaticLibrariesVersions;
857         this.legacyNativeLibraryPathString = other.legacyNativeLibraryPathString;
858         this.primaryCpuAbiString = other.primaryCpuAbiString;
859         this.secondaryCpuAbiString = other.secondaryCpuAbiString;
860         this.cpuAbiOverrideString = other.cpuAbiOverrideString;
861         this.timeStamp = other.timeStamp;
862         this.firstInstallTime = other.firstInstallTime;
863         this.lastUpdateTime = other.lastUpdateTime;
864         this.versionCode = other.versionCode;
865         this.uidError = other.uidError;
866         this.signatures = other.signatures;
867         this.installPermissionsFixed = other.installPermissionsFixed;
868         this.keySetData = other.keySetData;
869         this.installSource = other.installSource;
870         this.volumeUuid = other.volumeUuid;
871         this.categoryHint = other.categoryHint;
872         this.updateAvailable = other.updateAvailable;
873         this.forceQueryableOverride = other.forceQueryableOverride;
874         this.incrementalStates = other.incrementalStates;
875 
876         if (mOldCodePaths != null) {
877             if (other.mOldCodePaths != null) {
878                 mOldCodePaths.clear();
879                 mOldCodePaths.addAll(other.mOldCodePaths);
880             } else {
881                 mOldCodePaths = null;
882             }
883         }
884         mUserState.clear();
885         for (int i = 0; i < other.mUserState.size(); i++) {
886             mUserState.put(other.mUserState.keyAt(i), other.mUserState.valueAt(i));
887         }
888         onChanged();
889         return this;
890     }
891 }
892