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