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
17package com.android.server.pm;
18
19import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
20import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
21import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
22
23import android.content.pm.ApplicationInfo;
24import android.content.pm.IntentFilterVerificationInfo;
25import android.content.pm.PackageManager;
26import android.content.pm.PackageParser;
27import android.content.pm.PackageUserState;
28import android.content.pm.Signature;
29import android.os.BaseBundle;
30import android.os.PersistableBundle;
31import android.service.pm.PackageProto;
32import android.util.ArraySet;
33import android.util.SparseArray;
34import android.util.proto.ProtoOutputStream;
35
36import com.android.internal.annotations.VisibleForTesting;
37
38import java.io.File;
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.List;
42import java.util.Set;
43
44/**
45 * Settings base class for pending and resolved classes.
46 */
47public abstract class PackageSettingBase extends SettingBase {
48
49    private static final int[] EMPTY_INT_ARRAY = new int[0];
50
51    public final String name;
52    final String realName;
53
54    String parentPackageName;
55    List<String> childPackageNames;
56
57    /**
58     * Path where this package was found on disk. For monolithic packages
59     * this is path to single base APK file; for cluster packages this is
60     * path to the cluster directory.
61     */
62    File codePath;
63    String codePathString;
64    File resourcePath;
65    String resourcePathString;
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    String primaryCpuAbiString;
82
83    /**
84     * The secondary CPU abi for this package.
85     */
86    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> userState = new SparseArray<PackageUserState>();
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> oldCodePaths;
122
123    /** Package name of the app that installed this package */
124    String installerPackageName;
125    /** Indicates if the package that installed this app has been uninstalled */
126    boolean isOrphaned;
127    /** UUID of {@link VolumeInfo} hosting this app */
128    String volumeUuid;
129    /** The category of this app, as hinted by the installer */
130    int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
131    /** Whether or not an update is available. Ostensibly only for instant apps. */
132    boolean updateAvailable;
133
134    IntentFilterVerificationInfo verificationInfo;
135
136    PackageSettingBase(String name, String realName, File codePath, File resourcePath,
137            String legacyNativeLibraryPathString, String primaryCpuAbiString,
138            String secondaryCpuAbiString, String cpuAbiOverrideString,
139            long pVersionCode, int pkgFlags, int pkgPrivateFlags,
140            String parentPackageName, List<String> childPackageNames,
141            String[] usesStaticLibraries, long[] usesStaticLibrariesVersions) {
142        super(pkgFlags, pkgPrivateFlags);
143        this.name = name;
144        this.realName = realName;
145        this.parentPackageName = parentPackageName;
146        this.childPackageNames = (childPackageNames != null)
147                ? new ArrayList<>(childPackageNames) : null;
148        this.usesStaticLibraries = usesStaticLibraries;
149        this.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
150        init(codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString,
151                secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode);
152    }
153
154    /**
155     * New instance of PackageSetting with one-level-deep cloning.
156     * <p>
157     * IMPORTANT: With a shallow copy, we do NOT create new contained objects.
158     * This means, for example, changes to the user state of the original PackageSetting
159     * will also change the user state in its copy.
160     */
161    PackageSettingBase(PackageSettingBase base, String realName) {
162        super(base);
163        name = base.name;
164        this.realName = realName;
165        doCopy(base);
166    }
167
168    void init(File codePath, File resourcePath, String legacyNativeLibraryPathString,
169              String primaryCpuAbiString, String secondaryCpuAbiString,
170              String cpuAbiOverrideString, long pVersionCode) {
171        this.codePath = codePath;
172        this.codePathString = codePath.toString();
173        this.resourcePath = resourcePath;
174        this.resourcePathString = resourcePath.toString();
175        this.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
176        this.primaryCpuAbiString = primaryCpuAbiString;
177        this.secondaryCpuAbiString = secondaryCpuAbiString;
178        this.cpuAbiOverrideString = cpuAbiOverrideString;
179        this.versionCode = pVersionCode;
180        this.signatures = new PackageSignatures();
181    }
182
183    public void setInstallerPackageName(String packageName) {
184        installerPackageName = packageName;
185    }
186
187    public String getInstallerPackageName() {
188        return installerPackageName;
189    }
190
191    public void setVolumeUuid(String volumeUuid) {
192        this.volumeUuid = volumeUuid;
193    }
194
195    public String getVolumeUuid() {
196        return volumeUuid;
197    }
198
199    public void setTimeStamp(long newStamp) {
200        timeStamp = newStamp;
201    }
202
203    public void setUpdateAvailable(boolean updateAvailable) {
204        this.updateAvailable = updateAvailable;
205    }
206
207    public boolean isUpdateAvailable() {
208        return updateAvailable;
209    }
210
211    public boolean isSharedUser() {
212        return false;
213    }
214
215    public Signature[] getSignatures() {
216        return signatures.mSigningDetails.signatures;
217    }
218
219    public PackageParser.SigningDetails getSigningDetails() {
220        return signatures.mSigningDetails;
221    }
222
223    /**
224     * Makes a shallow copy of the given package settings.
225     *
226     * NOTE: For some fields [such as keySetData, signatures, userState, verificationInfo, etc...],
227     * the original object is copied and a new one is not created.
228     */
229    public void copyFrom(PackageSettingBase orig) {
230        super.copyFrom(orig);
231        doCopy(orig);
232    }
233
234    private void doCopy(PackageSettingBase orig) {
235        childPackageNames = (orig.childPackageNames != null)
236                ? new ArrayList<>(orig.childPackageNames) : null;
237        codePath = orig.codePath;
238        codePathString = orig.codePathString;
239        cpuAbiOverrideString = orig.cpuAbiOverrideString;
240        firstInstallTime = orig.firstInstallTime;
241        installPermissionsFixed = orig.installPermissionsFixed;
242        installerPackageName = orig.installerPackageName;
243        isOrphaned = orig.isOrphaned;
244        keySetData = orig.keySetData;
245        lastUpdateTime = orig.lastUpdateTime;
246        legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
247        // Intentionally skip oldCodePaths; it's not relevant for copies
248        parentPackageName = orig.parentPackageName;
249        primaryCpuAbiString = orig.primaryCpuAbiString;
250        resourcePath = orig.resourcePath;
251        resourcePathString = orig.resourcePathString;
252        secondaryCpuAbiString = orig.secondaryCpuAbiString;
253        signatures = orig.signatures;
254        timeStamp = orig.timeStamp;
255        uidError = orig.uidError;
256        userState.clear();
257        for (int i=0; i<orig.userState.size(); i++) {
258            userState.put(orig.userState.keyAt(i), orig.userState.valueAt(i));
259        }
260        verificationInfo = orig.verificationInfo;
261        versionCode = orig.versionCode;
262        volumeUuid = orig.volumeUuid;
263        categoryHint = orig.categoryHint;
264        usesStaticLibraries = orig.usesStaticLibraries != null
265                ? Arrays.copyOf(orig.usesStaticLibraries,
266                        orig.usesStaticLibraries.length) : null;
267        usesStaticLibrariesVersions = orig.usesStaticLibrariesVersions != null
268                ? Arrays.copyOf(orig.usesStaticLibrariesVersions,
269                       orig.usesStaticLibrariesVersions.length) : null;
270        updateAvailable = orig.updateAvailable;
271    }
272
273    private PackageUserState modifyUserState(int userId) {
274        PackageUserState state = userState.get(userId);
275        if (state == null) {
276            state = new PackageUserState();
277            userState.put(userId, state);
278        }
279        return state;
280    }
281
282    public PackageUserState readUserState(int userId) {
283        PackageUserState state = userState.get(userId);
284        if (state == null) {
285            return DEFAULT_USER_STATE;
286        }
287        state.categoryHint = categoryHint;
288        return state;
289    }
290
291    void setEnabled(int state, int userId, String callingPackage) {
292        PackageUserState st = modifyUserState(userId);
293        st.enabled = state;
294        st.lastDisableAppCaller = callingPackage;
295    }
296
297    int getEnabled(int userId) {
298        return readUserState(userId).enabled;
299    }
300
301    String getLastDisabledAppCaller(int userId) {
302        return readUserState(userId).lastDisableAppCaller;
303    }
304
305    void setInstalled(boolean inst, int userId) {
306        modifyUserState(userId).installed = inst;
307    }
308
309    boolean getInstalled(int userId) {
310        return readUserState(userId).installed;
311    }
312
313    int getInstallReason(int userId) {
314        return readUserState(userId).installReason;
315    }
316
317    void setInstallReason(int installReason, int userId) {
318        modifyUserState(userId).installReason = installReason;
319    }
320
321    void setOverlayPaths(List<String> overlayPaths, int userId) {
322        modifyUserState(userId).overlayPaths = overlayPaths == null ? null :
323            overlayPaths.toArray(new String[overlayPaths.size()]);
324    }
325
326    String[] getOverlayPaths(int userId) {
327        return readUserState(userId).overlayPaths;
328    }
329
330    /** Only use for testing. Do NOT use in production code. */
331    @VisibleForTesting
332    SparseArray<PackageUserState> getUserState() {
333        return userState;
334    }
335
336    boolean isAnyInstalled(int[] users) {
337        for (int user: users) {
338            if (readUserState(user).installed) {
339                return true;
340            }
341        }
342        return false;
343    }
344
345    int[] queryInstalledUsers(int[] users, boolean installed) {
346        int num = 0;
347        for (int user : users) {
348            if (getInstalled(user) == installed) {
349                num++;
350            }
351        }
352        int[] res = new int[num];
353        num = 0;
354        for (int user : users) {
355            if (getInstalled(user) == installed) {
356                res[num] = user;
357                num++;
358            }
359        }
360        return res;
361    }
362
363    long getCeDataInode(int userId) {
364        return readUserState(userId).ceDataInode;
365    }
366
367    void setCeDataInode(long ceDataInode, int userId) {
368        modifyUserState(userId).ceDataInode = ceDataInode;
369    }
370
371    boolean getStopped(int userId) {
372        return readUserState(userId).stopped;
373    }
374
375    void setStopped(boolean stop, int userId) {
376        modifyUserState(userId).stopped = stop;
377    }
378
379    boolean getNotLaunched(int userId) {
380        return readUserState(userId).notLaunched;
381    }
382
383    void setNotLaunched(boolean stop, int userId) {
384        modifyUserState(userId).notLaunched = stop;
385    }
386
387    boolean getHidden(int userId) {
388        return readUserState(userId).hidden;
389    }
390
391    void setHidden(boolean hidden, int userId) {
392        modifyUserState(userId).hidden = hidden;
393    }
394
395    boolean getSuspended(int userId) {
396        return readUserState(userId).suspended;
397    }
398
399    void setSuspended(boolean suspended, String suspendingPackage, String dialogMessage,
400            PersistableBundle appExtras, PersistableBundle launcherExtras, int userId) {
401        final PackageUserState existingUserState = modifyUserState(userId);
402        existingUserState.suspended = suspended;
403        existingUserState.suspendingPackage = suspended ? suspendingPackage : null;
404        existingUserState.dialogMessage = suspended ? dialogMessage : null;
405        existingUserState.suspendedAppExtras = suspended ? appExtras : null;
406        existingUserState.suspendedLauncherExtras = suspended ? launcherExtras : null;
407    }
408
409    public boolean getInstantApp(int userId) {
410        return readUserState(userId).instantApp;
411    }
412
413    void setInstantApp(boolean instantApp, int userId) {
414        modifyUserState(userId).instantApp = instantApp;
415    }
416
417    boolean getVirtulalPreload(int userId) {
418        return readUserState(userId).virtualPreload;
419    }
420
421    void setVirtualPreload(boolean virtualPreload, int userId) {
422        modifyUserState(userId).virtualPreload = virtualPreload;
423    }
424
425    void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
426            boolean notLaunched, boolean hidden, boolean suspended, String suspendingPackage,
427            String dialogMessage, PersistableBundle suspendedAppExtras,
428            PersistableBundle suspendedLauncherExtras, boolean instantApp,
429            boolean virtualPreload, String lastDisableAppCaller,
430            ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
431            int domainVerifState, int linkGeneration, int installReason,
432            String harmfulAppWarning) {
433        PackageUserState state = modifyUserState(userId);
434        state.ceDataInode = ceDataInode;
435        state.enabled = enabled;
436        state.installed = installed;
437        state.stopped = stopped;
438        state.notLaunched = notLaunched;
439        state.hidden = hidden;
440        state.suspended = suspended;
441        state.suspendingPackage = suspendingPackage;
442        state.dialogMessage = dialogMessage;
443        state.suspendedAppExtras = suspendedAppExtras;
444        state.suspendedLauncherExtras = suspendedLauncherExtras;
445        state.lastDisableAppCaller = lastDisableAppCaller;
446        state.enabledComponents = enabledComponents;
447        state.disabledComponents = disabledComponents;
448        state.domainVerificationStatus = domainVerifState;
449        state.appLinkGeneration = linkGeneration;
450        state.installReason = installReason;
451        state.instantApp = instantApp;
452        state.virtualPreload = virtualPreload;
453        state.harmfulAppWarning = harmfulAppWarning;
454    }
455
456    ArraySet<String> getEnabledComponents(int userId) {
457        return readUserState(userId).enabledComponents;
458    }
459
460    ArraySet<String> getDisabledComponents(int userId) {
461        return readUserState(userId).disabledComponents;
462    }
463
464    void setEnabledComponents(ArraySet<String> components, int userId) {
465        modifyUserState(userId).enabledComponents = components;
466    }
467
468    void setDisabledComponents(ArraySet<String> components, int userId) {
469        modifyUserState(userId).disabledComponents = components;
470    }
471
472    void setEnabledComponentsCopy(ArraySet<String> components, int userId) {
473        modifyUserState(userId).enabledComponents = components != null
474                ? new ArraySet<String>(components) : null;
475    }
476
477    void setDisabledComponentsCopy(ArraySet<String> components, int userId) {
478        modifyUserState(userId).disabledComponents = components != null
479                ? new ArraySet<String>(components) : null;
480    }
481
482    PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) {
483        PackageUserState state = modifyUserState(userId);
484        if (disabled && state.disabledComponents == null) {
485            state.disabledComponents = new ArraySet<String>(1);
486        }
487        if (enabled && state.enabledComponents == null) {
488            state.enabledComponents = new ArraySet<String>(1);
489        }
490        return state;
491    }
492
493    void addDisabledComponent(String componentClassName, int userId) {
494        modifyUserStateComponents(userId, true, false).disabledComponents.add(componentClassName);
495    }
496
497    void addEnabledComponent(String componentClassName, int userId) {
498        modifyUserStateComponents(userId, false, true).enabledComponents.add(componentClassName);
499    }
500
501    boolean enableComponentLPw(String componentClassName, int userId) {
502        PackageUserState state = modifyUserStateComponents(userId, false, true);
503        boolean changed = state.disabledComponents != null
504                ? state.disabledComponents.remove(componentClassName) : false;
505        changed |= state.enabledComponents.add(componentClassName);
506        return changed;
507    }
508
509    boolean disableComponentLPw(String componentClassName, int userId) {
510        PackageUserState state = modifyUserStateComponents(userId, true, false);
511        boolean changed = state.enabledComponents != null
512                ? state.enabledComponents.remove(componentClassName) : false;
513        changed |= state.disabledComponents.add(componentClassName);
514        return changed;
515    }
516
517    boolean restoreComponentLPw(String componentClassName, int userId) {
518        PackageUserState state = modifyUserStateComponents(userId, true, true);
519        boolean changed = state.disabledComponents != null
520                ? state.disabledComponents.remove(componentClassName) : false;
521        changed |= state.enabledComponents != null
522                ? state.enabledComponents.remove(componentClassName) : false;
523        return changed;
524    }
525
526    int getCurrentEnabledStateLPr(String componentName, int userId) {
527        PackageUserState state = readUserState(userId);
528        if (state.enabledComponents != null && state.enabledComponents.contains(componentName)) {
529            return COMPONENT_ENABLED_STATE_ENABLED;
530        } else if (state.disabledComponents != null
531                && state.disabledComponents.contains(componentName)) {
532            return COMPONENT_ENABLED_STATE_DISABLED;
533        } else {
534            return COMPONENT_ENABLED_STATE_DEFAULT;
535        }
536    }
537
538    void removeUser(int userId) {
539        userState.delete(userId);
540    }
541
542    public int[] getNotInstalledUserIds() {
543        int count = 0;
544        int userStateCount = userState.size();
545        for (int i = 0; i < userStateCount; i++) {
546            if (userState.valueAt(i).installed == false) {
547                count++;
548            }
549        }
550        if (count == 0) return EMPTY_INT_ARRAY;
551        int[] excludedUserIds = new int[count];
552        int idx = 0;
553        for (int i = 0; i < userStateCount; i++) {
554            if (userState.valueAt(i).installed == false) {
555                excludedUserIds[idx++] = userState.keyAt(i);
556            }
557        }
558        return excludedUserIds;
559    }
560
561    IntentFilterVerificationInfo getIntentFilterVerificationInfo() {
562        return verificationInfo;
563    }
564
565    void setIntentFilterVerificationInfo(IntentFilterVerificationInfo info) {
566        verificationInfo = info;
567    }
568
569    // Returns a packed value as a long:
570    //
571    // high 'int'-sized word: link status: undefined/ask/never/always.
572    // low 'int'-sized word: relative priority among 'always' results.
573    long getDomainVerificationStatusForUser(int userId) {
574        PackageUserState state = readUserState(userId);
575        long result = (long) state.appLinkGeneration;
576        result |= ((long) state.domainVerificationStatus) << 32;
577        return result;
578    }
579
580    void setDomainVerificationStatusForUser(final int status, int generation, int userId) {
581        PackageUserState state = modifyUserState(userId);
582        state.domainVerificationStatus = status;
583        if (status == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
584            state.appLinkGeneration = generation;
585        }
586    }
587
588    void clearDomainVerificationStatusForUser(int userId) {
589        modifyUserState(userId).domainVerificationStatus =
590                PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
591    }
592
593    protected void writeUsersInfoToProto(ProtoOutputStream proto, long fieldId) {
594        int count = userState.size();
595        for (int i = 0; i < count; i++) {
596            final long userToken = proto.start(fieldId);
597            final int userId = userState.keyAt(i);
598            final PackageUserState state = userState.valueAt(i);
599            proto.write(PackageProto.UserInfoProto.ID, userId);
600            final int installType;
601            if (state.instantApp) {
602                installType = PackageProto.UserInfoProto.INSTANT_APP_INSTALL;
603            } else if (state.installed) {
604                installType = PackageProto.UserInfoProto.FULL_APP_INSTALL;
605            } else {
606                installType = PackageProto.UserInfoProto.NOT_INSTALLED_FOR_USER;
607            }
608            proto.write(PackageProto.UserInfoProto.INSTALL_TYPE, installType);
609            proto.write(PackageProto.UserInfoProto.IS_HIDDEN, state.hidden);
610            proto.write(PackageProto.UserInfoProto.IS_SUSPENDED, state.suspended);
611            if (state.suspended) {
612                proto.write(PackageProto.UserInfoProto.SUSPENDING_PACKAGE, state.suspendingPackage);
613            }
614            proto.write(PackageProto.UserInfoProto.IS_STOPPED, state.stopped);
615            proto.write(PackageProto.UserInfoProto.IS_LAUNCHED, !state.notLaunched);
616            proto.write(PackageProto.UserInfoProto.ENABLED_STATE, state.enabled);
617            proto.write(
618                    PackageProto.UserInfoProto.LAST_DISABLED_APP_CALLER,
619                    state.lastDisableAppCaller);
620            proto.end(userToken);
621        }
622    }
623
624    void setHarmfulAppWarning(int userId, String harmfulAppWarning) {
625        PackageUserState userState = modifyUserState(userId);
626        userState.harmfulAppWarning = harmfulAppWarning;
627    }
628
629    String getHarmfulAppWarning(int userId) {
630        PackageUserState userState = readUserState(userId);
631        return userState.harmfulAppWarning;
632    }
633}
634