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