Settings.java revision 1f09b8c0c2a08fa5169a36031efcb3f34ec5f163
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_DISABLED_UNTIL_USED;
22import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
23import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
24import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
25import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
26import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
27import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
28import static android.os.Process.SYSTEM_UID;
29import static android.os.Process.PACKAGE_INFO_GID;
30
31import android.content.IntentFilter;
32import android.content.pm.ActivityInfo;
33import android.content.pm.IntentFilterVerificationInfo;
34import android.content.pm.ResolveInfo;
35import android.net.Uri;
36import android.os.Binder;
37import android.os.Build;
38import android.os.Environment;
39import android.os.FileUtils;
40import android.os.Handler;
41import android.os.Message;
42import android.os.PatternMatcher;
43import android.os.Process;
44import android.os.SystemClock;
45import android.os.UserHandle;
46import android.os.UserManager;
47import android.os.storage.VolumeInfo;
48import android.util.AtomicFile;
49import android.text.TextUtils;
50import android.util.LogPrinter;
51import android.util.SparseBooleanArray;
52import android.util.SparseLongArray;
53
54import com.android.internal.annotations.GuardedBy;
55import com.android.internal.os.BackgroundThread;
56import com.android.internal.util.ArrayUtils;
57import com.android.internal.util.FastXmlSerializer;
58import com.android.internal.util.JournaledFile;
59import com.android.internal.util.Preconditions;
60import com.android.internal.util.XmlUtils;
61import com.android.server.backup.PreferredActivityBackupHelper;
62import com.android.server.pm.PackageManagerService.DumpState;
63
64import java.io.FileNotFoundException;
65import java.util.Collection;
66
67import org.xmlpull.v1.XmlPullParser;
68import org.xmlpull.v1.XmlPullParserException;
69import org.xmlpull.v1.XmlSerializer;
70
71import android.content.ComponentName;
72import android.content.Intent;
73import android.content.pm.ApplicationInfo;
74import android.content.pm.ComponentInfo;
75import android.content.pm.PackageCleanItem;
76import android.content.pm.PackageManager;
77import android.content.pm.PackageParser;
78import android.content.pm.PermissionInfo;
79import android.content.pm.Signature;
80import android.content.pm.UserInfo;
81import android.content.pm.PackageUserState;
82import android.content.pm.VerifierDeviceIdentity;
83import android.util.ArrayMap;
84import android.util.ArraySet;
85import android.util.Log;
86import android.util.Slog;
87import android.util.SparseArray;
88import android.util.Xml;
89
90import java.io.BufferedOutputStream;
91import java.io.File;
92import java.io.FileInputStream;
93import java.io.FileOutputStream;
94import java.io.IOException;
95import java.io.PrintWriter;
96import java.text.SimpleDateFormat;
97import java.util.ArrayList;
98import java.util.Arrays;
99import java.util.Collections;
100import java.util.Date;
101import java.util.Iterator;
102import java.util.List;
103import java.util.Map;
104import java.util.Objects;
105import java.util.Set;
106import java.util.Map.Entry;
107
108import libcore.io.IoUtils;
109
110/**
111 * Holds information about dynamic settings.
112 */
113final class Settings {
114    private static final String TAG = "PackageSettings";
115
116    /**
117     * Current version of the package database. Set it to the latest version in
118     * the {@link DatabaseVersion} class below to ensure the database upgrade
119     * doesn't happen repeatedly.
120     * <p>
121     * Note that care should be taken to make sure all database upgrades are
122     * idempotent.
123     */
124    private static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_MALFORMED_RECOVER;
125
126    /**
127     * This class contains constants that can be referred to from upgrade code.
128     * Insert constant values here that describe the upgrade reason. The version
129     * code must be monotonically increasing.
130     */
131    public static class DatabaseVersion {
132        /**
133         * The initial version of the database.
134         */
135        public static final int FIRST_VERSION = 1;
136
137        /**
138         * Migrating the Signature array from the entire certificate chain to
139         * just the signing certificate.
140         */
141        public static final int SIGNATURE_END_ENTITY = 2;
142
143        /**
144         * There was a window of time in
145         * {@link android.os.Build.VERSION_CODES#LOLLIPOP} where we persisted
146         * certificates after potentially mutating them. To switch back to the
147         * original untouched certificates, we need to force a collection pass.
148         */
149        public static final int SIGNATURE_MALFORMED_RECOVER = 3;
150    }
151
152    private static final boolean DEBUG_STOPPED = false;
153    private static final boolean DEBUG_MU = false;
154
155    private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml";
156
157    private static final String TAG_READ_EXTERNAL_STORAGE = "read-external-storage";
158    private static final String ATTR_ENFORCEMENT = "enforcement";
159
160    private static final String TAG_ITEM = "item";
161    private static final String TAG_DISABLED_COMPONENTS = "disabled-components";
162    private static final String TAG_ENABLED_COMPONENTS = "enabled-components";
163    private static final String TAG_PACKAGE_RESTRICTIONS = "package-restrictions";
164    private static final String TAG_PACKAGE = "pkg";
165    private static final String TAG_SHARED_USER = "shared-user";
166    private static final String TAG_RUNTIME_PERMISSIONS = "runtime-permissions";
167    private static final String TAG_PERMISSIONS = "perms";
168    private static final String TAG_PERSISTENT_PREFERRED_ACTIVITIES =
169            "persistent-preferred-activities";
170    static final String TAG_CROSS_PROFILE_INTENT_FILTERS =
171            "crossProfile-intent-filters";
172    public static final String TAG_DOMAIN_VERIFICATION = "domain-verification";
173    public static final String TAG_DEFAULT_APPS= "default-apps";
174    public static final String TAG_DEFAULT_BROWSER= "default-browser";
175
176    private static final String ATTR_NAME = "name";
177    private static final String ATTR_USER = "user";
178    private static final String ATTR_CODE = "code";
179    private static final String ATTR_NOT_LAUNCHED = "nl";
180    private static final String ATTR_ENABLED = "enabled";
181    private static final String ATTR_ENABLED_CALLER = "enabledCaller";
182    private static final String ATTR_STOPPED = "stopped";
183    // Legacy, here for reading older versions of the package-restrictions.
184    private static final String ATTR_BLOCKED = "blocked";
185    // New name for the above attribute.
186    private static final String ATTR_HIDDEN = "hidden";
187    private static final String ATTR_INSTALLED = "inst";
188    private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
189    private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
190    private static final String ATTR_PACKAGE_NAME= "packageName";
191
192    private final Object mLock;
193
194    private final RuntimePermissionPersistence mRuntimePermissionsPersistence;
195
196    private final File mSettingsFilename;
197    private final File mBackupSettingsFilename;
198    private final File mPackageListFilename;
199    private final File mStoppedPackagesFilename;
200    private final File mBackupStoppedPackagesFilename;
201
202    final ArrayMap<String, PackageSetting> mPackages =
203            new ArrayMap<String, PackageSetting>();
204    // List of replaced system applications
205    private final ArrayMap<String, PackageSetting> mDisabledSysPackages =
206        new ArrayMap<String, PackageSetting>();
207
208    private static int mFirstAvailableUid = 0;
209
210    // TODO: store SDK versions and fingerprint for each volume UUID
211
212    // These are the last platform API version we were using for
213    // the apps installed on internal and external storage.  It is
214    // used to grant newer permissions one time during a system upgrade.
215    int mInternalSdkPlatform;
216    int mExternalSdkPlatform;
217
218    /**
219     * The current database version for apps on internal storage. This is
220     * used to upgrade the format of the packages.xml database not necessarily
221     * tied to an SDK version.
222     */
223    int mInternalDatabaseVersion;
224    int mExternalDatabaseVersion;
225
226    /**
227     * Last known value of {@link Build#FINGERPRINT}. Used to determine when an
228     * system update has occurred, meaning we need to clear code caches.
229     */
230    String mFingerprint;
231
232    Boolean mReadExternalStorageEnforced;
233
234    /** Device identity for the purpose of package verification. */
235    private VerifierDeviceIdentity mVerifierDeviceIdentity;
236
237    // The user's preferred activities associated with particular intent
238    // filters.
239    final SparseArray<PreferredIntentResolver> mPreferredActivities =
240            new SparseArray<PreferredIntentResolver>();
241
242    // The persistent preferred activities of the user's profile/device owner
243    // associated with particular intent filters.
244    final SparseArray<PersistentPreferredIntentResolver> mPersistentPreferredActivities =
245            new SparseArray<PersistentPreferredIntentResolver>();
246
247    // For every user, it is used to find to which other users the intent can be forwarded.
248    final SparseArray<CrossProfileIntentResolver> mCrossProfileIntentResolvers =
249            new SparseArray<CrossProfileIntentResolver>();
250
251    final ArrayMap<String, SharedUserSetting> mSharedUsers =
252            new ArrayMap<String, SharedUserSetting>();
253    private final ArrayList<Object> mUserIds = new ArrayList<Object>();
254    private final SparseArray<Object> mOtherUserIds =
255            new SparseArray<Object>();
256
257    // For reading/writing settings file.
258    private final ArrayList<Signature> mPastSignatures =
259            new ArrayList<Signature>();
260    private final ArrayMap<Long, Integer> mKeySetRefs =
261            new ArrayMap<Long, Integer>();
262
263    // Mapping from permission names to info about them.
264    final ArrayMap<String, BasePermission> mPermissions =
265            new ArrayMap<String, BasePermission>();
266
267    // Mapping from permission tree names to info about them.
268    final ArrayMap<String, BasePermission> mPermissionTrees =
269            new ArrayMap<String, BasePermission>();
270
271    // Packages that have been uninstalled and still need their external
272    // storage data deleted.
273    final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>();
274
275    // Packages that have been renamed since they were first installed.
276    // Keys are the new names of the packages, values are the original
277    // names.  The packages appear everwhere else under their original
278    // names.
279    final ArrayMap<String, String> mRenamedPackages = new ArrayMap<String, String>();
280
281    // For every user, it is used to find the package name of the default Browser App.
282    final SparseArray<String> mDefaultBrowserApp = new SparseArray<String>();
283
284    final StringBuilder mReadMessages = new StringBuilder();
285
286    /**
287     * Used to track packages that have a shared user ID that hasn't been read
288     * in yet.
289     * <p>
290     * TODO: make this just a local variable that is passed in during package
291     * scanning to make it less confusing.
292     */
293    private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
294
295    private final File mSystemDir;
296
297    public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
298
299    Settings(Object lock) {
300        this(Environment.getDataDirectory(), lock);
301    }
302
303    Settings(File dataDir, Object lock) {
304        mLock = lock;
305
306        mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
307
308        mSystemDir = new File(dataDir, "system");
309        mSystemDir.mkdirs();
310        FileUtils.setPermissions(mSystemDir.toString(),
311                FileUtils.S_IRWXU|FileUtils.S_IRWXG
312                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
313                -1, -1);
314        mSettingsFilename = new File(mSystemDir, "packages.xml");
315        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
316        mPackageListFilename = new File(mSystemDir, "packages.list");
317        FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
318
319        // Deprecated: Needed for migration
320        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
321        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
322    }
323
324    PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
325            String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
326            String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,
327            int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add) {
328        final String name = pkg.packageName;
329        PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
330                resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,
331                pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /* allowInstall */);
332        return p;
333    }
334
335    PackageSetting peekPackageLPr(String name) {
336        return mPackages.get(name);
337    }
338
339    void setInstallStatus(String pkgName, int status) {
340        PackageSetting p = mPackages.get(pkgName);
341        if(p != null) {
342            if(p.getInstallStatus() != status) {
343                p.setInstallStatus(status);
344            }
345        }
346    }
347
348    void setInstallerPackageName(String pkgName, String installerPkgName) {
349        PackageSetting p = mPackages.get(pkgName);
350        if (p != null) {
351            p.setInstallerPackageName(installerPkgName);
352        }
353    }
354
355    SharedUserSetting getSharedUserLPw(String name,
356            int pkgFlags, int pkgPrivateFlags, boolean create) {
357        SharedUserSetting s = mSharedUsers.get(name);
358        if (s == null) {
359            if (!create) {
360                return null;
361            }
362            s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
363            s.userId = newUserIdLPw(s);
364            Log.i(PackageManagerService.TAG, "New shared user " + name + ": id=" + s.userId);
365            // < 0 means we couldn't assign a userid; fall out and return
366            // s, which is currently null
367            if (s.userId >= 0) {
368                mSharedUsers.put(name, s);
369            }
370        }
371
372        return s;
373    }
374
375    Collection<SharedUserSetting> getAllSharedUsersLPw() {
376        return mSharedUsers.values();
377    }
378
379
380    boolean disableSystemPackageLPw(String name) {
381        final PackageSetting p = mPackages.get(name);
382        if(p == null) {
383            Log.w(PackageManagerService.TAG, "Package:"+name+" is not an installed package");
384            return false;
385        }
386        final PackageSetting dp = mDisabledSysPackages.get(name);
387        // always make sure the system package code and resource paths dont change
388        if (dp == null) {
389            if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
390                p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
391            }
392            mDisabledSysPackages.put(name, p);
393
394            // a little trick...  when we install the new package, we don't
395            // want to modify the existing PackageSetting for the built-in
396            // version.  so at this point we need a new PackageSetting that
397            // is okay to muck with.
398            PackageSetting newp = new PackageSetting(p);
399            replacePackageLPw(name, newp);
400            return true;
401        }
402        return false;
403    }
404
405    PackageSetting enableSystemPackageLPw(String name) {
406        PackageSetting p = mDisabledSysPackages.get(name);
407        if(p == null) {
408            Log.w(PackageManagerService.TAG, "Package:"+name+" is not disabled");
409            return null;
410        }
411        // Reset flag in ApplicationInfo object
412        if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
413            p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
414        }
415        PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
416                p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
417                p.secondaryCpuAbiString, p.secondaryCpuAbiString,
418                p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags);
419        mDisabledSysPackages.remove(name);
420        return ret;
421    }
422
423    boolean isDisabledSystemPackageLPr(String name) {
424        return mDisabledSysPackages.containsKey(name);
425    }
426
427    void removeDisabledSystemPackageLPw(String name) {
428        mDisabledSysPackages.remove(name);
429    }
430
431    PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
432            String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString,
433            String cpuAbiOverrideString, int uid, int vc, int pkgFlags, int pkgPrivateFlags) {
434        PackageSetting p = mPackages.get(name);
435        if (p != null) {
436            if (p.appId == uid) {
437                return p;
438            }
439            PackageManagerService.reportSettingsProblem(Log.ERROR,
440                    "Adding duplicate package, keeping first: " + name);
441            return null;
442        }
443        p = new PackageSetting(name, realName, codePath, resourcePath,
444                legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
445                cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags);
446        p.appId = uid;
447        if (addUserIdLPw(uid, p, name)) {
448            mPackages.put(name, p);
449            return p;
450        }
451        return null;
452    }
453
454    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
455        SharedUserSetting s = mSharedUsers.get(name);
456        if (s != null) {
457            if (s.userId == uid) {
458                return s;
459            }
460            PackageManagerService.reportSettingsProblem(Log.ERROR,
461                    "Adding duplicate shared user, keeping first: " + name);
462            return null;
463        }
464        s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
465        s.userId = uid;
466        if (addUserIdLPw(uid, s, name)) {
467            mSharedUsers.put(name, s);
468            return s;
469        }
470        return null;
471    }
472
473    void pruneSharedUsersLPw() {
474        ArrayList<String> removeStage = new ArrayList<String>();
475        for (Map.Entry<String,SharedUserSetting> entry : mSharedUsers.entrySet()) {
476            final SharedUserSetting sus = entry.getValue();
477            if (sus == null || sus.packages.size() == 0) {
478                removeStage.add(entry.getKey());
479            }
480        }
481        for (int i = 0; i < removeStage.size(); i++) {
482            mSharedUsers.remove(removeStage.get(i));
483        }
484    }
485
486    // Transfer ownership of permissions from one package to another.
487    void transferPermissionsLPw(String origPkg, String newPkg) {
488        // Transfer ownership of permissions to the new package.
489        for (int i=0; i<2; i++) {
490            ArrayMap<String, BasePermission> permissions =
491                    i == 0 ? mPermissionTrees : mPermissions;
492            for (BasePermission bp : permissions.values()) {
493                if (origPkg.equals(bp.sourcePackage)) {
494                    if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG,
495                            "Moving permission " + bp.name
496                            + " from pkg " + bp.sourcePackage
497                            + " to " + newPkg);
498                    bp.sourcePackage = newPkg;
499                    bp.packageSetting = null;
500                    bp.perm = null;
501                    if (bp.pendingInfo != null) {
502                        bp.pendingInfo.packageName = newPkg;
503                    }
504                    bp.uid = 0;
505                    bp.setGids(null, false);
506                }
507            }
508        }
509    }
510
511    private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
512            String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
513            String legacyNativeLibraryPathString, String primaryCpuAbiString,
514            String secondaryCpuAbiString, int vc, int pkgFlags, int pkgPrivateFlags,
515            UserHandle installUser, boolean add, boolean allowInstall) {
516        PackageSetting p = mPackages.get(name);
517        UserManagerService userManager = UserManagerService.getInstance();
518        if (p != null) {
519            p.primaryCpuAbiString = primaryCpuAbiString;
520            p.secondaryCpuAbiString = secondaryCpuAbiString;
521
522            if (!p.codePath.equals(codePath)) {
523                // Check to see if its a disabled system app
524                if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
525                    // This is an updated system app with versions in both system
526                    // and data partition. Just let the most recent version
527                    // take precedence.
528                    Slog.w(PackageManagerService.TAG, "Trying to update system app code path from "
529                            + p.codePathString + " to " + codePath.toString());
530                } else {
531                    // Just a change in the code path is not an issue, but
532                    // let's log a message about it.
533                    Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from "
534                            + p.codePath + " to " + codePath + "; Retaining data and using new");
535                    /*
536                     * Since we've changed paths, we need to prefer the new
537                     * native library path over the one stored in the
538                     * package settings since we might have moved from
539                     * internal to external storage or vice versa.
540                     */
541                    p.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
542                }
543            }
544            if (p.sharedUser != sharedUser) {
545                PackageManagerService.reportSettingsProblem(Log.WARN,
546                        "Package " + name + " shared user changed from "
547                        + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
548                        + " to "
549                        + (sharedUser != null ? sharedUser.name : "<nothing>")
550                        + "; replacing with new");
551                p = null;
552            } else {
553                // If what we are scanning is a system (and possibly privileged) package,
554                // then make it so, regardless of whether it was previously installed only
555                // in the data partition.
556                p.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
557                p.pkgPrivateFlags |= pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
558            }
559        }
560        if (p == null) {
561            if (origPackage != null) {
562                // We are consuming the data from an existing package.
563                p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
564                        legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
565                        null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags);
566                if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
567                        + name + " is adopting original package " + origPackage.name);
568                // Note that we will retain the new package's signature so
569                // that we can keep its data.
570                PackageSignatures s = p.signatures;
571                p.copyFrom(origPackage);
572                p.signatures = s;
573                p.sharedUser = origPackage.sharedUser;
574                p.appId = origPackage.appId;
575                p.origPackage = origPackage;
576                mRenamedPackages.put(name, origPackage.name);
577                name = origPackage.name;
578                // Update new package state.
579                p.setTimeStamp(codePath.lastModified());
580            } else {
581                p = new PackageSetting(name, realName, codePath, resourcePath,
582                        legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
583                        null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags);
584                p.setTimeStamp(codePath.lastModified());
585                p.sharedUser = sharedUser;
586                // If this is not a system app, it starts out stopped.
587                if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
588                    if (DEBUG_STOPPED) {
589                        RuntimeException e = new RuntimeException("here");
590                        e.fillInStackTrace();
591                        Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
592                    }
593                    List<UserInfo> users = getAllUsers();
594                    final int installUserId = installUser != null ? installUser.getIdentifier() : 0;
595                    if (users != null && allowInstall) {
596                        for (UserInfo user : users) {
597                            // By default we consider this app to be installed
598                            // for the user if no user has been specified (which
599                            // means to leave it at its original value, and the
600                            // original default value is true), or we are being
601                            // asked to install for all users, or this is the
602                            // user we are installing for.
603                            final boolean installed = installUser == null
604                                    || (installUserId == UserHandle.USER_ALL
605                                        && !isAdbInstallDisallowed(userManager, user.id))
606                                    || installUserId == user.id;
607                            p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
608                                    installed,
609                                    true, // stopped,
610                                    true, // notLaunched
611                                    false, // hidden
612                                    null, null, null,
613                                    false, // blockUninstall
614                                    INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
615                            writePackageRestrictionsLPr(user.id);
616                        }
617                    }
618                }
619                if (sharedUser != null) {
620                    p.appId = sharedUser.userId;
621                } else {
622                    // Clone the setting here for disabled system packages
623                    PackageSetting dis = mDisabledSysPackages.get(name);
624                    if (dis != null) {
625                        // For disabled packages a new setting is created
626                        // from the existing user id. This still has to be
627                        // added to list of user id's
628                        // Copy signatures from previous setting
629                        if (dis.signatures.mSignatures != null) {
630                            p.signatures.mSignatures = dis.signatures.mSignatures.clone();
631                        }
632                        p.appId = dis.appId;
633                        // Clone permissions
634                        p.getPermissionsState().copyFrom(dis.getPermissionsState());
635                        // Clone component info
636                        List<UserInfo> users = getAllUsers();
637                        if (users != null) {
638                            for (UserInfo user : users) {
639                                int userId = user.id;
640                                p.setDisabledComponentsCopy(
641                                        dis.getDisabledComponents(userId), userId);
642                                p.setEnabledComponentsCopy(
643                                        dis.getEnabledComponents(userId), userId);
644                            }
645                        }
646                        // Add new setting to list of user ids
647                        addUserIdLPw(p.appId, p, name);
648                    } else {
649                        // Assign new user id
650                        p.appId = newUserIdLPw(p);
651                    }
652                }
653            }
654            if (p.appId < 0) {
655                PackageManagerService.reportSettingsProblem(Log.WARN,
656                        "Package " + name + " could not be assigned a valid uid");
657                return null;
658            }
659            if (add) {
660                // Finish adding new package by adding it and updating shared
661                // user preferences
662                addPackageSettingLPw(p, name, sharedUser);
663            }
664        } else {
665            if (installUser != null && allowInstall) {
666                // The caller has explicitly specified the user they want this
667                // package installed for, and the package already exists.
668                // Make sure it conforms to the new request.
669                List<UserInfo> users = getAllUsers();
670                if (users != null) {
671                    for (UserInfo user : users) {
672                        if ((installUser.getIdentifier() == UserHandle.USER_ALL
673                                    && !isAdbInstallDisallowed(userManager, user.id))
674                                || installUser.getIdentifier() == user.id) {
675                            boolean installed = p.getInstalled(user.id);
676                            if (!installed) {
677                                p.setInstalled(true, user.id);
678                                writePackageRestrictionsLPr(user.id);
679                            }
680                        }
681                    }
682                }
683            }
684        }
685        return p;
686    }
687
688    boolean isAdbInstallDisallowed(UserManagerService userManager, int userId) {
689        return userManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
690                userId);
691    }
692
693    void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
694        p.pkg = pkg;
695        // pkg.mSetEnabled = p.getEnabled(userId);
696        // pkg.mSetStopped = p.getStopped(userId);
697        final String volumeUuid = pkg.applicationInfo.volumeUuid;
698        final String codePath = pkg.applicationInfo.getCodePath();
699        final String resourcePath = pkg.applicationInfo.getResourcePath();
700        final String legacyNativeLibraryPath = pkg.applicationInfo.nativeLibraryRootDir;
701        // Update volume if needed
702        if (!Objects.equals(volumeUuid, p.volumeUuid)) {
703            Slog.w(PackageManagerService.TAG, "Volume for " + p.pkg.packageName +
704                    " changing from " + p.volumeUuid + " to " + volumeUuid);
705            p.volumeUuid = volumeUuid;
706        }
707        // Update code path if needed
708        if (!Objects.equals(codePath, p.codePathString)) {
709            Slog.w(PackageManagerService.TAG, "Code path for " + p.pkg.packageName +
710                    " changing from " + p.codePathString + " to " + codePath);
711            p.codePath = new File(codePath);
712            p.codePathString = codePath;
713        }
714        //Update resource path if needed
715        if (!Objects.equals(resourcePath, p.resourcePathString)) {
716            Slog.w(PackageManagerService.TAG, "Resource path for " + p.pkg.packageName +
717                    " changing from " + p.resourcePathString + " to " + resourcePath);
718            p.resourcePath = new File(resourcePath);
719            p.resourcePathString = resourcePath;
720        }
721        // Update the native library paths if needed
722        if (!Objects.equals(legacyNativeLibraryPath, p.legacyNativeLibraryPathString)) {
723            p.legacyNativeLibraryPathString = legacyNativeLibraryPath;
724        }
725
726        // Update the required Cpu Abi
727        p.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
728        p.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
729        p.cpuAbiOverrideString = pkg.cpuAbiOverride;
730        // Update version code if needed
731        if (pkg.mVersionCode != p.versionCode) {
732            p.versionCode = pkg.mVersionCode;
733        }
734        // Update signatures if needed.
735        if (p.signatures.mSignatures == null) {
736            p.signatures.assignSignatures(pkg.mSignatures);
737        }
738        // Update flags if needed.
739        if (pkg.applicationInfo.flags != p.pkgFlags) {
740            p.pkgFlags = pkg.applicationInfo.flags;
741        }
742        // If this app defines a shared user id initialize
743        // the shared user signatures as well.
744        if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
745            p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
746        }
747        addPackageSettingLPw(p, pkg.packageName, p.sharedUser);
748    }
749
750    // Utility method that adds a PackageSetting to mPackages and
751    // completes updating the shared user attributes
752    private void addPackageSettingLPw(PackageSetting p, String name,
753            SharedUserSetting sharedUser) {
754        mPackages.put(name, p);
755        if (sharedUser != null) {
756            if (p.sharedUser != null && p.sharedUser != sharedUser) {
757                PackageManagerService.reportSettingsProblem(Log.ERROR,
758                        "Package " + p.name + " was user "
759                        + p.sharedUser + " but is now " + sharedUser
760                        + "; I am not changing its files so it will probably fail!");
761                p.sharedUser.removePackage(p);
762            } else if (p.appId != sharedUser.userId) {
763                PackageManagerService.reportSettingsProblem(Log.ERROR,
764                    "Package " + p.name + " was user id " + p.appId
765                    + " but is now user " + sharedUser
766                    + " with id " + sharedUser.userId
767                    + "; I am not changing its files so it will probably fail!");
768            }
769
770            sharedUser.addPackage(p);
771            p.sharedUser = sharedUser;
772            p.appId = sharedUser.userId;
773        }
774    }
775
776    /*
777     * Update the shared user setting when a package using
778     * specifying the shared user id is removed. The gids
779     * associated with each permission of the deleted package
780     * are removed from the shared user's gid list only if its
781     * not in use by other permissions of packages in the
782     * shared user setting.
783     */
784    int updateSharedUserPermsLPw(PackageSetting deletedPs, int userId) {
785        if ((deletedPs == null) || (deletedPs.pkg == null)) {
786            Slog.i(PackageManagerService.TAG,
787                    "Trying to update info for null package. Just ignoring");
788            return UserHandle.USER_NULL;
789        }
790
791        // No sharedUserId
792        if (deletedPs.sharedUser == null) {
793            return UserHandle.USER_NULL;
794        }
795
796        SharedUserSetting sus = deletedPs.sharedUser;
797
798        // Update permissions
799        for (String eachPerm : deletedPs.pkg.requestedPermissions) {
800            BasePermission bp = mPermissions.get(eachPerm);
801            if (bp == null) {
802                continue;
803            }
804
805            // If no user has the permission, nothing to remove.
806            if (!sus.getPermissionsState().hasPermission(bp.name, userId)) {
807                 continue;
808            }
809
810            boolean used = false;
811
812            // Check if another package in the shared user needs the permission.
813            for (PackageSetting pkg : sus.packages) {
814                if (pkg.pkg != null
815                        && !pkg.pkg.packageName.equals(deletedPs.pkg.packageName)
816                        && pkg.pkg.requestedPermissions.contains(eachPerm)) {
817                    used = true;
818                    break;
819                }
820            }
821
822            if (!used) {
823                // Try to revoke as an install permission which is for all users.
824                if (sus.getPermissionsState().revokeInstallPermission(bp) ==
825                        PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
826                    return UserHandle.USER_ALL;
827                }
828
829                // Try to revoke as an install permission which is per user.
830                if (sus.getPermissionsState().revokeRuntimePermission(bp, userId) ==
831                        PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
832                    return userId;
833                }
834            }
835        }
836
837        return UserHandle.USER_NULL;
838    }
839
840    int removePackageLPw(String name) {
841        final PackageSetting p = mPackages.get(name);
842        if (p != null) {
843            mPackages.remove(name);
844            if (p.sharedUser != null) {
845                p.sharedUser.removePackage(p);
846                if (p.sharedUser.packages.size() == 0) {
847                    mSharedUsers.remove(p.sharedUser.name);
848                    removeUserIdLPw(p.sharedUser.userId);
849                    return p.sharedUser.userId;
850                }
851            } else {
852                removeUserIdLPw(p.appId);
853                return p.appId;
854            }
855        }
856        return -1;
857    }
858
859    private void replacePackageLPw(String name, PackageSetting newp) {
860        final PackageSetting p = mPackages.get(name);
861        if (p != null) {
862            if (p.sharedUser != null) {
863                p.sharedUser.removePackage(p);
864                p.sharedUser.addPackage(newp);
865            } else {
866                replaceUserIdLPw(p.appId, newp);
867            }
868        }
869        mPackages.put(name, newp);
870    }
871
872    private boolean addUserIdLPw(int uid, Object obj, Object name) {
873        if (uid > Process.LAST_APPLICATION_UID) {
874            return false;
875        }
876
877        if (uid >= Process.FIRST_APPLICATION_UID) {
878            int N = mUserIds.size();
879            final int index = uid - Process.FIRST_APPLICATION_UID;
880            while (index >= N) {
881                mUserIds.add(null);
882                N++;
883            }
884            if (mUserIds.get(index) != null) {
885                PackageManagerService.reportSettingsProblem(Log.ERROR,
886                        "Adding duplicate user id: " + uid
887                        + " name=" + name);
888                return false;
889            }
890            mUserIds.set(index, obj);
891        } else {
892            if (mOtherUserIds.get(uid) != null) {
893                PackageManagerService.reportSettingsProblem(Log.ERROR,
894                        "Adding duplicate shared id: " + uid
895                                + " name=" + name);
896                return false;
897            }
898            mOtherUserIds.put(uid, obj);
899        }
900        return true;
901    }
902
903    public Object getUserIdLPr(int uid) {
904        if (uid >= Process.FIRST_APPLICATION_UID) {
905            final int N = mUserIds.size();
906            final int index = uid - Process.FIRST_APPLICATION_UID;
907            return index < N ? mUserIds.get(index) : null;
908        } else {
909            return mOtherUserIds.get(uid);
910        }
911    }
912
913    private void removeUserIdLPw(int uid) {
914        if (uid >= Process.FIRST_APPLICATION_UID) {
915            final int N = mUserIds.size();
916            final int index = uid - Process.FIRST_APPLICATION_UID;
917            if (index < N) mUserIds.set(index, null);
918        } else {
919            mOtherUserIds.remove(uid);
920        }
921        setFirstAvailableUid(uid+1);
922    }
923
924    private void replaceUserIdLPw(int uid, Object obj) {
925        if (uid >= Process.FIRST_APPLICATION_UID) {
926            final int N = mUserIds.size();
927            final int index = uid - Process.FIRST_APPLICATION_UID;
928            if (index < N) mUserIds.set(index, obj);
929        } else {
930            mOtherUserIds.put(uid, obj);
931        }
932    }
933
934    PreferredIntentResolver editPreferredActivitiesLPw(int userId) {
935        PreferredIntentResolver pir = mPreferredActivities.get(userId);
936        if (pir == null) {
937            pir = new PreferredIntentResolver();
938            mPreferredActivities.put(userId, pir);
939        }
940        return pir;
941    }
942
943    PersistentPreferredIntentResolver editPersistentPreferredActivitiesLPw(int userId) {
944        PersistentPreferredIntentResolver ppir = mPersistentPreferredActivities.get(userId);
945        if (ppir == null) {
946            ppir = new PersistentPreferredIntentResolver();
947            mPersistentPreferredActivities.put(userId, ppir);
948        }
949        return ppir;
950    }
951
952    CrossProfileIntentResolver editCrossProfileIntentResolverLPw(int userId) {
953        CrossProfileIntentResolver cpir = mCrossProfileIntentResolvers.get(userId);
954        if (cpir == null) {
955            cpir = new CrossProfileIntentResolver();
956            mCrossProfileIntentResolvers.put(userId, cpir);
957        }
958        return cpir;
959    }
960
961    /**
962     * The following functions suppose that you have a lock for managing access to the
963     * mIntentFiltersVerifications map.
964     */
965
966    /* package protected */
967    IntentFilterVerificationInfo getIntentFilterVerificationLPr(String packageName) {
968        PackageSetting ps = mPackages.get(packageName);
969        if (ps == null) {
970            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
971            return null;
972        }
973        return ps.getIntentFilterVerificationInfo();
974    }
975
976    /* package protected */
977    IntentFilterVerificationInfo createIntentFilterVerificationIfNeededLPw(String packageName,
978            ArrayList<String> domains) {
979        PackageSetting ps = mPackages.get(packageName);
980        if (ps == null) {
981            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
982            return null;
983        }
984        IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
985        if (ivi == null) {
986            ivi = new IntentFilterVerificationInfo(packageName, domains);
987            ps.setIntentFilterVerificationInfo(ivi);
988            Slog.d(PackageManagerService.TAG,
989                    "Creating new IntentFilterVerificationInfo for packageName: " + packageName);
990        } else {
991            ivi.setDomains(domains);
992            Slog.d(PackageManagerService.TAG,
993                    "Setting domains to existing IntentFilterVerificationInfo for packageName: " +
994                            packageName + " and with domains: " + ivi.getDomainsString());
995        }
996        return ivi;
997    }
998
999    int getIntentFilterVerificationStatusLPr(String packageName, int userId) {
1000        PackageSetting ps = mPackages.get(packageName);
1001        if (ps == null) {
1002            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
1003            return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
1004        }
1005        int status = ps.getDomainVerificationStatusForUser(userId);
1006        if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
1007            if (ps.getIntentFilterVerificationInfo() != null) {
1008                status = ps.getIntentFilterVerificationInfo().getStatus();
1009            }
1010        }
1011        return status;
1012    }
1013
1014    boolean updateIntentFilterVerificationStatusLPw(String packageName, int status, int userId) {
1015        // Update the status for the current package
1016        PackageSetting current = mPackages.get(packageName);
1017        if (current == null) {
1018            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
1019            return false;
1020        }
1021        current.setDomainVerificationStatusForUser(status, userId);
1022
1023        if (current.getIntentFilterVerificationInfo() == null) {
1024            Slog.w(PackageManagerService.TAG,
1025                    "No IntentFilterVerificationInfo known for name: " + packageName);
1026            return false;
1027        }
1028
1029        // Then, if we set a ALWAYS status, then put NEVER status for Apps whose IntentFilter
1030        // domains overlap the domains of the current package
1031        ArraySet<String> currentDomains = current.getIntentFilterVerificationInfo().getDomains();
1032        if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
1033            for (PackageSetting ps : mPackages.values()) {
1034                if (ps == null || ps.pkg.packageName.equals(packageName)) continue;
1035                IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
1036                if (ivi == null) {
1037                    continue;
1038                }
1039                ArraySet<String> set = ivi.getDomains();
1040                set.retainAll(currentDomains);
1041                if (set.size() > 0) {
1042                    ps.setDomainVerificationStatusForUser(
1043                            INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER, userId);
1044                }
1045            }
1046        }
1047        return true;
1048    }
1049
1050    /**
1051     * Used for Settings App and PackageManagerService dump. Should be read only.
1052     */
1053    List<IntentFilterVerificationInfo> getIntentFilterVerificationsLPr(
1054            String packageName) {
1055        if (packageName == null) {
1056            return Collections.<IntentFilterVerificationInfo>emptyList();
1057        }
1058        ArrayList<IntentFilterVerificationInfo> result = new ArrayList<>();
1059        for (PackageSetting ps : mPackages.values()) {
1060            IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
1061            if (ivi == null || TextUtils.isEmpty(ivi.getPackageName()) ||
1062                    !ivi.getPackageName().equalsIgnoreCase(packageName)) {
1063                continue;
1064            }
1065            result.add(ivi);
1066        }
1067        return result;
1068    }
1069
1070    boolean removeIntentFilterVerificationLPw(String packageName, int userId) {
1071        PackageSetting ps = mPackages.get(packageName);
1072        if (ps == null) {
1073            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
1074            return false;
1075        }
1076        ps.clearDomainVerificationStatusForUser(userId);
1077        return true;
1078    }
1079
1080    boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) {
1081        boolean result = false;
1082        for (int userId : userIds) {
1083            result |= removeIntentFilterVerificationLPw(packageName, userId);
1084        }
1085        return result;
1086    }
1087
1088    boolean setDefaultBrowserPackageNameLPr(String packageName, int userId) {
1089        if (userId == UserHandle.USER_ALL) {
1090            return false;
1091        }
1092        mDefaultBrowserApp.put(userId, packageName);
1093        writePackageRestrictionsLPr(userId);
1094        return true;
1095    }
1096
1097    String getDefaultBrowserPackageNameLPw(int userId) {
1098        return (userId == UserHandle.USER_ALL) ? null : mDefaultBrowserApp.get(userId);
1099    }
1100
1101    private File getUserPackagesStateFile(int userId) {
1102        // TODO: Implement a cleaner solution when adding tests.
1103        // This instead of Environment.getUserSystemDirectory(userId) to support testing.
1104        File userDir = new File(new File(mSystemDir, "users"), Integer.toString(userId));
1105        return new File(userDir, "package-restrictions.xml");
1106    }
1107
1108    private File getUserRuntimePermissionsFile(int userId) {
1109        // TODO: Implement a cleaner solution when adding tests.
1110        // This instead of Environment.getUserSystemDirectory(userId) to support testing.
1111        File userDir = new File(new File(mSystemDir, "users"), Integer.toString(userId));
1112        return new File(userDir, RUNTIME_PERMISSIONS_FILE_NAME);
1113    }
1114
1115    boolean isFirstRuntimePermissionsBoot() {
1116        return !getUserRuntimePermissionsFile(UserHandle.USER_OWNER).exists();
1117    }
1118
1119    void deleteRuntimePermissionsFiles() {
1120        for (int userId : UserManagerService.getInstance().getUserIds()) {
1121            File file = getUserRuntimePermissionsFile(userId);
1122            file.delete();
1123        }
1124    }
1125
1126    private File getUserPackagesStateBackupFile(int userId) {
1127        return new File(Environment.getUserSystemDirectory(userId),
1128                "package-restrictions-backup.xml");
1129    }
1130
1131    void writeAllUsersPackageRestrictionsLPr() {
1132        List<UserInfo> users = getAllUsers();
1133        if (users == null) return;
1134
1135        for (UserInfo user : users) {
1136            writePackageRestrictionsLPr(user.id);
1137        }
1138    }
1139
1140    void writeAllRuntimePermissionsLPr() {
1141        for (int userId : UserManagerService.getInstance().getUserIds()) {
1142            mRuntimePermissionsPersistence.writePermissionsForUserAsyncLPr(userId);
1143        }
1144    }
1145
1146    /**
1147     * Returns whether the current database has is older than {@code version}
1148     * for apps on internal storage.
1149     */
1150    public boolean isInternalDatabaseVersionOlderThan(int version) {
1151        return mInternalDatabaseVersion < version;
1152    }
1153
1154    /**
1155     * Returns whether the current database has is older than {@code version}
1156     * for apps on external storage.
1157     */
1158    public boolean isExternalDatabaseVersionOlderThan(int version) {
1159        return mExternalDatabaseVersion < version;
1160    }
1161
1162    /**
1163     * Updates the database version for apps on internal storage. Called after
1164     * call the updates to the database format are done for apps on internal
1165     * storage after the initial start-up scan.
1166     */
1167    public void updateInternalDatabaseVersion() {
1168        mInternalDatabaseVersion = CURRENT_DATABASE_VERSION;
1169    }
1170
1171    /**
1172     * Updates the database version for apps on internal storage. Called after
1173     * call the updates to the database format are done for apps on internal
1174     * storage after the initial start-up scan.
1175     */
1176    public void updateExternalDatabaseVersion() {
1177        mExternalDatabaseVersion = CURRENT_DATABASE_VERSION;
1178    }
1179
1180    /**
1181     * Applies the preferred activity state described by the given XML.  This code
1182     * also supports the restore-from-backup code path.
1183     *
1184     * @see PreferredActivityBackupHelper
1185     */
1186    void readPreferredActivitiesLPw(XmlPullParser parser, int userId)
1187            throws XmlPullParserException, IOException {
1188        int outerDepth = parser.getDepth();
1189        int type;
1190        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1191                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1192            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1193                continue;
1194            }
1195
1196            String tagName = parser.getName();
1197            if (tagName.equals(TAG_ITEM)) {
1198                PreferredActivity pa = new PreferredActivity(parser);
1199                if (pa.mPref.getParseError() == null) {
1200                    editPreferredActivitiesLPw(userId).addFilter(pa);
1201                } else {
1202                    PackageManagerService.reportSettingsProblem(Log.WARN,
1203                            "Error in package manager settings: <preferred-activity> "
1204                                    + pa.mPref.getParseError() + " at "
1205                                    + parser.getPositionDescription());
1206                }
1207            } else {
1208                PackageManagerService.reportSettingsProblem(Log.WARN,
1209                        "Unknown element under <preferred-activities>: " + parser.getName());
1210                XmlUtils.skipCurrentTag(parser);
1211            }
1212        }
1213    }
1214
1215    private void readPersistentPreferredActivitiesLPw(XmlPullParser parser, int userId)
1216            throws XmlPullParserException, IOException {
1217        int outerDepth = parser.getDepth();
1218        int type;
1219        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1220                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1221            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1222                continue;
1223            }
1224            String tagName = parser.getName();
1225            if (tagName.equals(TAG_ITEM)) {
1226                PersistentPreferredActivity ppa = new PersistentPreferredActivity(parser);
1227                editPersistentPreferredActivitiesLPw(userId).addFilter(ppa);
1228            } else {
1229                PackageManagerService.reportSettingsProblem(Log.WARN,
1230                        "Unknown element under <" + TAG_PERSISTENT_PREFERRED_ACTIVITIES + ">: "
1231                        + parser.getName());
1232                XmlUtils.skipCurrentTag(parser);
1233            }
1234        }
1235    }
1236
1237    private void readCrossProfileIntentFiltersLPw(XmlPullParser parser, int userId)
1238            throws XmlPullParserException, IOException {
1239        int outerDepth = parser.getDepth();
1240        int type;
1241        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1242                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1243            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1244                continue;
1245            }
1246            String tagName = parser.getName();
1247            if (tagName.equals(TAG_ITEM)) {
1248                CrossProfileIntentFilter cpif = new CrossProfileIntentFilter(parser);
1249                editCrossProfileIntentResolverLPw(userId).addFilter(cpif);
1250            } else {
1251                String msg = "Unknown element under " +  TAG_CROSS_PROFILE_INTENT_FILTERS + ": " +
1252                        parser.getName();
1253                PackageManagerService.reportSettingsProblem(Log.WARN, msg);
1254                XmlUtils.skipCurrentTag(parser);
1255            }
1256        }
1257    }
1258
1259    private void readDomainVerificationLPw(XmlPullParser parser, PackageSettingBase packageSetting)
1260            throws XmlPullParserException, IOException {
1261        IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(parser);
1262        packageSetting.setIntentFilterVerificationInfo(ivi);
1263        Log.d(TAG, "Read domain verification for package:" + ivi.getPackageName());
1264    }
1265
1266    private void readDefaultAppsLPw(XmlPullParser parser, int userId)
1267            throws XmlPullParserException, IOException {
1268        int outerDepth = parser.getDepth();
1269        int type;
1270        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1271                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1272            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1273                continue;
1274            }
1275            String tagName = parser.getName();
1276            if (tagName.equals(TAG_DEFAULT_BROWSER)) {
1277                String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
1278                mDefaultBrowserApp.put(userId, packageName);
1279            } else {
1280                String msg = "Unknown element under " +  TAG_DEFAULT_APPS + ": " +
1281                        parser.getName();
1282                PackageManagerService.reportSettingsProblem(Log.WARN, msg);
1283                XmlUtils.skipCurrentTag(parser);
1284            }
1285        }
1286    }
1287
1288    void readPackageRestrictionsLPr(int userId) {
1289        if (DEBUG_MU) {
1290            Log.i(TAG, "Reading package restrictions for user=" + userId);
1291        }
1292        FileInputStream str = null;
1293        File userPackagesStateFile = getUserPackagesStateFile(userId);
1294        File backupFile = getUserPackagesStateBackupFile(userId);
1295        if (backupFile.exists()) {
1296            try {
1297                str = new FileInputStream(backupFile);
1298                mReadMessages.append("Reading from backup stopped packages file\n");
1299                PackageManagerService.reportSettingsProblem(Log.INFO,
1300                        "Need to read from backup stopped packages file");
1301                if (userPackagesStateFile.exists()) {
1302                    // If both the backup and normal file exist, we
1303                    // ignore the normal one since it might have been
1304                    // corrupted.
1305                    Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
1306                            + userPackagesStateFile);
1307                    userPackagesStateFile.delete();
1308                }
1309            } catch (java.io.IOException e) {
1310                // We'll try for the normal settings file.
1311            }
1312        }
1313
1314        try {
1315            if (str == null) {
1316                if (!userPackagesStateFile.exists()) {
1317                    mReadMessages.append("No stopped packages file found\n");
1318                    PackageManagerService.reportSettingsProblem(Log.INFO,
1319                            "No stopped packages file; "
1320                            + "assuming all started");
1321                    // At first boot, make sure no packages are stopped.
1322                    // We usually want to have third party apps initialize
1323                    // in the stopped state, but not at first boot.  Also
1324                    // consider all applications to be installed.
1325                    for (PackageSetting pkg : mPackages.values()) {
1326                        pkg.setUserState(userId, COMPONENT_ENABLED_STATE_DEFAULT,
1327                                true,   // installed
1328                                false,  // stopped
1329                                false,  // notLaunched
1330                                false,  // hidden
1331                                null, null, null,
1332                                false, // blockUninstall
1333                                INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
1334                    }
1335                    return;
1336                }
1337                str = new FileInputStream(userPackagesStateFile);
1338            }
1339            final XmlPullParser parser = Xml.newPullParser();
1340            parser.setInput(str, null);
1341
1342            int type;
1343            while ((type=parser.next()) != XmlPullParser.START_TAG
1344                       && type != XmlPullParser.END_DOCUMENT) {
1345                ;
1346            }
1347
1348            if (type != XmlPullParser.START_TAG) {
1349                mReadMessages.append("No start tag found in package restrictions file\n");
1350                PackageManagerService.reportSettingsProblem(Log.WARN,
1351                        "No start tag found in package manager stopped packages");
1352                return;
1353            }
1354
1355            int outerDepth = parser.getDepth();
1356            PackageSetting ps = null;
1357            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1358                   && (type != XmlPullParser.END_TAG
1359                           || parser.getDepth() > outerDepth)) {
1360                if (type == XmlPullParser.END_TAG
1361                        || type == XmlPullParser.TEXT) {
1362                    continue;
1363                }
1364
1365                String tagName = parser.getName();
1366                if (tagName.equals(TAG_PACKAGE)) {
1367                    String name = parser.getAttributeValue(null, ATTR_NAME);
1368                    ps = mPackages.get(name);
1369                    if (ps == null) {
1370                        Slog.w(PackageManagerService.TAG, "No package known for stopped package: "
1371                                + name);
1372                        XmlUtils.skipCurrentTag(parser);
1373                        continue;
1374                    }
1375                    final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
1376                    final int enabled = enabledStr == null
1377                            ? COMPONENT_ENABLED_STATE_DEFAULT : Integer.parseInt(enabledStr);
1378                    final String enabledCaller = parser.getAttributeValue(null,
1379                            ATTR_ENABLED_CALLER);
1380                    final String installedStr = parser.getAttributeValue(null, ATTR_INSTALLED);
1381                    final boolean installed = installedStr == null
1382                            ? true : Boolean.parseBoolean(installedStr);
1383                    final String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
1384                    final boolean stopped = stoppedStr == null
1385                            ? false : Boolean.parseBoolean(stoppedStr);
1386                    // For backwards compatibility with the previous name of "blocked", which
1387                    // now means hidden, read the old attribute as well.
1388                    final String blockedStr = parser.getAttributeValue(null, ATTR_BLOCKED);
1389                    boolean hidden = blockedStr == null
1390                            ? false : Boolean.parseBoolean(blockedStr);
1391                    final String hiddenStr = parser.getAttributeValue(null, ATTR_HIDDEN);
1392                    hidden = hiddenStr == null
1393                            ? hidden : Boolean.parseBoolean(hiddenStr);
1394                    final String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
1395                    final boolean notLaunched = stoppedStr == null
1396                            ? false : Boolean.parseBoolean(notLaunchedStr);
1397                    final String blockUninstallStr = parser.getAttributeValue(null,
1398                            ATTR_BLOCK_UNINSTALL);
1399                    final boolean blockUninstall = blockUninstallStr == null
1400                            ? false : Boolean.parseBoolean(blockUninstallStr);
1401
1402                    final String verifStateStr =
1403                            parser.getAttributeValue(null, ATTR_DOMAIN_VERIFICATON_STATE);
1404                    final int verifState = (verifStateStr == null) ?
1405                            PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED :
1406                            Integer.parseInt(verifStateStr);
1407
1408                    ArraySet<String> enabledComponents = null;
1409                    ArraySet<String> disabledComponents = null;
1410
1411                    int packageDepth = parser.getDepth();
1412                    while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1413                            && (type != XmlPullParser.END_TAG
1414                            || parser.getDepth() > packageDepth)) {
1415                        if (type == XmlPullParser.END_TAG
1416                                || type == XmlPullParser.TEXT) {
1417                            continue;
1418                        }
1419                        tagName = parser.getName();
1420                        if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
1421                            enabledComponents = readComponentsLPr(parser);
1422                        } else if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
1423                            disabledComponents = readComponentsLPr(parser);
1424                        }
1425                    }
1426
1427                    ps.setUserState(userId, enabled, installed, stopped, notLaunched, hidden,
1428                            enabledCaller, enabledComponents, disabledComponents, blockUninstall,
1429                            verifState);
1430                } else if (tagName.equals("preferred-activities")) {
1431                    readPreferredActivitiesLPw(parser, userId);
1432                } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
1433                    readPersistentPreferredActivitiesLPw(parser, userId);
1434                } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
1435                    readCrossProfileIntentFiltersLPw(parser, userId);
1436                } else if (tagName.equals(TAG_DEFAULT_APPS)) {
1437                    readDefaultAppsLPw(parser, userId);
1438                } else {
1439                    Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
1440                          + parser.getName());
1441                    XmlUtils.skipCurrentTag(parser);
1442                }
1443            }
1444
1445            str.close();
1446
1447        } catch (XmlPullParserException e) {
1448            mReadMessages.append("Error reading: " + e.toString());
1449            PackageManagerService.reportSettingsProblem(Log.ERROR,
1450                    "Error reading stopped packages: " + e);
1451            Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
1452                    e);
1453
1454        } catch (java.io.IOException e) {
1455            mReadMessages.append("Error reading: " + e.toString());
1456            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
1457            Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
1458                    e);
1459        }
1460    }
1461
1462    private ArraySet<String> readComponentsLPr(XmlPullParser parser)
1463            throws IOException, XmlPullParserException {
1464        ArraySet<String> components = null;
1465        int type;
1466        int outerDepth = parser.getDepth();
1467        String tagName;
1468        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1469                && (type != XmlPullParser.END_TAG
1470                || parser.getDepth() > outerDepth)) {
1471            if (type == XmlPullParser.END_TAG
1472                    || type == XmlPullParser.TEXT) {
1473                continue;
1474            }
1475            tagName = parser.getName();
1476            if (tagName.equals(TAG_ITEM)) {
1477                String componentName = parser.getAttributeValue(null, ATTR_NAME);
1478                if (componentName != null) {
1479                    if (components == null) {
1480                        components = new ArraySet<String>();
1481                    }
1482                    components.add(componentName);
1483                }
1484            }
1485        }
1486        return components;
1487    }
1488
1489    /**
1490     * Record the state of preferred activity configuration into XML.  This is used both
1491     * for recording packages.xml internally and for supporting backup/restore of the
1492     * preferred activity configuration.
1493     */
1494    void writePreferredActivitiesLPr(XmlSerializer serializer, int userId, boolean full)
1495            throws IllegalArgumentException, IllegalStateException, IOException {
1496        serializer.startTag(null, "preferred-activities");
1497        PreferredIntentResolver pir = mPreferredActivities.get(userId);
1498        if (pir != null) {
1499            for (final PreferredActivity pa : pir.filterSet()) {
1500                serializer.startTag(null, TAG_ITEM);
1501                pa.writeToXml(serializer, full);
1502                serializer.endTag(null, TAG_ITEM);
1503            }
1504        }
1505        serializer.endTag(null, "preferred-activities");
1506    }
1507
1508    void writePersistentPreferredActivitiesLPr(XmlSerializer serializer, int userId)
1509            throws IllegalArgumentException, IllegalStateException, IOException {
1510        serializer.startTag(null, TAG_PERSISTENT_PREFERRED_ACTIVITIES);
1511        PersistentPreferredIntentResolver ppir = mPersistentPreferredActivities.get(userId);
1512        if (ppir != null) {
1513            for (final PersistentPreferredActivity ppa : ppir.filterSet()) {
1514                serializer.startTag(null, TAG_ITEM);
1515                ppa.writeToXml(serializer);
1516                serializer.endTag(null, TAG_ITEM);
1517            }
1518        }
1519        serializer.endTag(null, TAG_PERSISTENT_PREFERRED_ACTIVITIES);
1520    }
1521
1522    void writeCrossProfileIntentFiltersLPr(XmlSerializer serializer, int userId)
1523            throws IllegalArgumentException, IllegalStateException, IOException {
1524        serializer.startTag(null, TAG_CROSS_PROFILE_INTENT_FILTERS);
1525        CrossProfileIntentResolver cpir = mCrossProfileIntentResolvers.get(userId);
1526        if (cpir != null) {
1527            for (final CrossProfileIntentFilter cpif : cpir.filterSet()) {
1528                serializer.startTag(null, TAG_ITEM);
1529                cpif.writeToXml(serializer);
1530                serializer.endTag(null, TAG_ITEM);
1531            }
1532        }
1533        serializer.endTag(null, TAG_CROSS_PROFILE_INTENT_FILTERS);
1534    }
1535
1536    void writeDomainVerificationsLPr(XmlSerializer serializer,
1537                                     IntentFilterVerificationInfo verificationInfo)
1538            throws IllegalArgumentException, IllegalStateException, IOException {
1539        if (verificationInfo != null && verificationInfo.getPackageName() != null) {
1540            serializer.startTag(null, TAG_DOMAIN_VERIFICATION);
1541            verificationInfo.writeToXml(serializer);
1542            Log.d(TAG, "Wrote domain verification for package: "
1543                    + verificationInfo.getPackageName());
1544            serializer.endTag(null, TAG_DOMAIN_VERIFICATION);
1545        }
1546    }
1547
1548    void writeDefaultAppsLPr(XmlSerializer serializer, int userId)
1549            throws IllegalArgumentException, IllegalStateException, IOException {
1550        serializer.startTag(null, TAG_DEFAULT_APPS);
1551        String packageName = mDefaultBrowserApp.get(userId);
1552        if (!TextUtils.isEmpty(packageName)) {
1553            serializer.startTag(null, TAG_DEFAULT_BROWSER);
1554            serializer.attribute(null, ATTR_PACKAGE_NAME, packageName);
1555            serializer.endTag(null, TAG_DEFAULT_BROWSER);
1556        }
1557        serializer.endTag(null, TAG_DEFAULT_APPS);
1558    }
1559
1560    void writePackageRestrictionsLPr(int userId) {
1561        if (DEBUG_MU) {
1562            Log.i(TAG, "Writing package restrictions for user=" + userId);
1563        }
1564        // Keep the old stopped packages around until we know the new ones have
1565        // been successfully written.
1566        File userPackagesStateFile = getUserPackagesStateFile(userId);
1567        File backupFile = getUserPackagesStateBackupFile(userId);
1568        new File(userPackagesStateFile.getParent()).mkdirs();
1569        if (userPackagesStateFile.exists()) {
1570            // Presence of backup settings file indicates that we failed
1571            // to persist packages earlier. So preserve the older
1572            // backup for future reference since the current packages
1573            // might have been corrupted.
1574            if (!backupFile.exists()) {
1575                if (!userPackagesStateFile.renameTo(backupFile)) {
1576                    Slog.wtf(PackageManagerService.TAG,
1577                            "Unable to backup user packages state file, "
1578                            + "current changes will be lost at reboot");
1579                    return;
1580                }
1581            } else {
1582                userPackagesStateFile.delete();
1583                Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
1584            }
1585        }
1586
1587        try {
1588            final FileOutputStream fstr = new FileOutputStream(userPackagesStateFile);
1589            final BufferedOutputStream str = new BufferedOutputStream(fstr);
1590
1591            final XmlSerializer serializer = new FastXmlSerializer();
1592            serializer.setOutput(str, "utf-8");
1593            serializer.startDocument(null, true);
1594            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1595
1596            serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
1597
1598            for (final PackageSetting pkg : mPackages.values()) {
1599                PackageUserState ustate = pkg.readUserState(userId);
1600                if (ustate.stopped || ustate.notLaunched || !ustate.installed
1601                        || ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT
1602                        || ustate.hidden
1603                        || (ustate.enabledComponents != null
1604                                && ustate.enabledComponents.size() > 0)
1605                        || (ustate.disabledComponents != null
1606                                && ustate.disabledComponents.size() > 0)
1607                        || ustate.blockUninstall
1608                        || (ustate.domainVerificationStatus !=
1609                            PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED)) {
1610                    serializer.startTag(null, TAG_PACKAGE);
1611                    serializer.attribute(null, ATTR_NAME, pkg.name);
1612                    if (DEBUG_MU) Log.i(TAG, "  pkg=" + pkg.name + ", state=" + ustate.enabled);
1613
1614                    if (!ustate.installed) {
1615                        serializer.attribute(null, ATTR_INSTALLED, "false");
1616                    }
1617                    if (ustate.stopped) {
1618                        serializer.attribute(null, ATTR_STOPPED, "true");
1619                    }
1620                    if (ustate.notLaunched) {
1621                        serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
1622                    }
1623                    if (ustate.hidden) {
1624                        serializer.attribute(null, ATTR_HIDDEN, "true");
1625                    }
1626                    if (ustate.blockUninstall) {
1627                        serializer.attribute(null, ATTR_BLOCK_UNINSTALL, "true");
1628                    }
1629                    if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
1630                        serializer.attribute(null, ATTR_ENABLED,
1631                                Integer.toString(ustate.enabled));
1632                        if (ustate.lastDisableAppCaller != null) {
1633                            serializer.attribute(null, ATTR_ENABLED_CALLER,
1634                                    ustate.lastDisableAppCaller);
1635                        }
1636                    }
1637                    if (ustate.domainVerificationStatus !=
1638                            PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
1639                        serializer.attribute(null, ATTR_DOMAIN_VERIFICATON_STATE,
1640                                Integer.toString(ustate.domainVerificationStatus));
1641                    }
1642                    if (ustate.enabledComponents != null
1643                            && ustate.enabledComponents.size() > 0) {
1644                        serializer.startTag(null, TAG_ENABLED_COMPONENTS);
1645                        for (final String name : ustate.enabledComponents) {
1646                            serializer.startTag(null, TAG_ITEM);
1647                            serializer.attribute(null, ATTR_NAME, name);
1648                            serializer.endTag(null, TAG_ITEM);
1649                        }
1650                        serializer.endTag(null, TAG_ENABLED_COMPONENTS);
1651                    }
1652                    if (ustate.disabledComponents != null
1653                            && ustate.disabledComponents.size() > 0) {
1654                        serializer.startTag(null, TAG_DISABLED_COMPONENTS);
1655                        for (final String name : ustate.disabledComponents) {
1656                            serializer.startTag(null, TAG_ITEM);
1657                            serializer.attribute(null, ATTR_NAME, name);
1658                            serializer.endTag(null, TAG_ITEM);
1659                        }
1660                        serializer.endTag(null, TAG_DISABLED_COMPONENTS);
1661                    }
1662
1663                    serializer.endTag(null, TAG_PACKAGE);
1664                }
1665            }
1666
1667            writePreferredActivitiesLPr(serializer, userId, true);
1668            writePersistentPreferredActivitiesLPr(serializer, userId);
1669            writeCrossProfileIntentFiltersLPr(serializer, userId);
1670            writeDefaultAppsLPr(serializer, userId);
1671
1672            serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
1673
1674            serializer.endDocument();
1675
1676            str.flush();
1677            FileUtils.sync(fstr);
1678            str.close();
1679
1680            // New settings successfully written, old ones are no longer
1681            // needed.
1682            backupFile.delete();
1683            FileUtils.setPermissions(userPackagesStateFile.toString(),
1684                    FileUtils.S_IRUSR|FileUtils.S_IWUSR
1685                    |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
1686                    -1, -1);
1687
1688            // Done, all is good!
1689            return;
1690        } catch(java.io.IOException e) {
1691            Slog.wtf(PackageManagerService.TAG,
1692                    "Unable to write package manager user packages state, "
1693                    + " current changes will be lost at reboot", e);
1694        }
1695
1696        // Clean up partially written files
1697        if (userPackagesStateFile.exists()) {
1698            if (!userPackagesStateFile.delete()) {
1699                Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "
1700                        + mStoppedPackagesFilename);
1701            }
1702        }
1703    }
1704
1705    void readInstallPermissionsLPr(XmlPullParser parser,
1706            PermissionsState permissionsState) throws IOException, XmlPullParserException {
1707        int outerDepth = parser.getDepth();
1708        int type;
1709        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1710                && (type != XmlPullParser.END_TAG
1711                || parser.getDepth() > outerDepth)) {
1712            if (type == XmlPullParser.END_TAG
1713                    || type == XmlPullParser.TEXT) {
1714                continue;
1715            }
1716            String tagName = parser.getName();
1717            if (tagName.equals(TAG_ITEM)) {
1718                String name = parser.getAttributeValue(null, ATTR_NAME);
1719
1720                BasePermission bp = mPermissions.get(name);
1721                if (bp == null) {
1722                    Slog.w(PackageManagerService.TAG, "Unknown permission: " + name);
1723                    XmlUtils.skipCurrentTag(parser);
1724                    continue;
1725                }
1726
1727                if (permissionsState.grantInstallPermission(bp) ==
1728                        PermissionsState.PERMISSION_OPERATION_FAILURE) {
1729                    Slog.w(PackageManagerService.TAG, "Permission already added: " + name);
1730                    XmlUtils.skipCurrentTag(parser);
1731                }
1732            } else {
1733                Slog.w(PackageManagerService.TAG, "Unknown element under <permissions>: "
1734                        + parser.getName());
1735                XmlUtils.skipCurrentTag(parser);
1736            }
1737        }
1738    }
1739
1740    void writePermissionsLPr(XmlSerializer serializer, Set<String> permissions)
1741            throws IOException {
1742        if (permissions.isEmpty()) {
1743            return;
1744        }
1745
1746        serializer.startTag(null, TAG_PERMISSIONS);
1747
1748        for (String permission : permissions) {
1749            serializer.startTag(null, TAG_ITEM);
1750            serializer.attribute(null, ATTR_NAME, permission);
1751            serializer.endTag(null, TAG_ITEM);
1752        }
1753
1754        serializer.endTag(null, TAG_PERMISSIONS);
1755    }
1756
1757    // Note: assumed "stopped" field is already cleared in all packages.
1758    // Legacy reader, used to read in the old file format after an upgrade. Not used after that.
1759    void readStoppedLPw() {
1760        FileInputStream str = null;
1761        if (mBackupStoppedPackagesFilename.exists()) {
1762            try {
1763                str = new FileInputStream(mBackupStoppedPackagesFilename);
1764                mReadMessages.append("Reading from backup stopped packages file\n");
1765                PackageManagerService.reportSettingsProblem(Log.INFO,
1766                        "Need to read from backup stopped packages file");
1767                if (mSettingsFilename.exists()) {
1768                    // If both the backup and normal file exist, we
1769                    // ignore the normal one since it might have been
1770                    // corrupted.
1771                    Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
1772                            + mStoppedPackagesFilename);
1773                    mStoppedPackagesFilename.delete();
1774                }
1775            } catch (java.io.IOException e) {
1776                // We'll try for the normal settings file.
1777            }
1778        }
1779
1780        try {
1781            if (str == null) {
1782                if (!mStoppedPackagesFilename.exists()) {
1783                    mReadMessages.append("No stopped packages file found\n");
1784                    PackageManagerService.reportSettingsProblem(Log.INFO,
1785                            "No stopped packages file file; assuming all started");
1786                    // At first boot, make sure no packages are stopped.
1787                    // We usually want to have third party apps initialize
1788                    // in the stopped state, but not at first boot.
1789                    for (PackageSetting pkg : mPackages.values()) {
1790                        pkg.setStopped(false, 0);
1791                        pkg.setNotLaunched(false, 0);
1792                    }
1793                    return;
1794                }
1795                str = new FileInputStream(mStoppedPackagesFilename);
1796            }
1797            final XmlPullParser parser = Xml.newPullParser();
1798            parser.setInput(str, null);
1799
1800            int type;
1801            while ((type=parser.next()) != XmlPullParser.START_TAG
1802                       && type != XmlPullParser.END_DOCUMENT) {
1803                ;
1804            }
1805
1806            if (type != XmlPullParser.START_TAG) {
1807                mReadMessages.append("No start tag found in stopped packages file\n");
1808                PackageManagerService.reportSettingsProblem(Log.WARN,
1809                        "No start tag found in package manager stopped packages");
1810                return;
1811            }
1812
1813            int outerDepth = parser.getDepth();
1814            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1815                   && (type != XmlPullParser.END_TAG
1816                           || parser.getDepth() > outerDepth)) {
1817                if (type == XmlPullParser.END_TAG
1818                        || type == XmlPullParser.TEXT) {
1819                    continue;
1820                }
1821
1822                String tagName = parser.getName();
1823                if (tagName.equals(TAG_PACKAGE)) {
1824                    String name = parser.getAttributeValue(null, ATTR_NAME);
1825                    PackageSetting ps = mPackages.get(name);
1826                    if (ps != null) {
1827                        ps.setStopped(true, 0);
1828                        if ("1".equals(parser.getAttributeValue(null, ATTR_NOT_LAUNCHED))) {
1829                            ps.setNotLaunched(true, 0);
1830                        }
1831                    } else {
1832                        Slog.w(PackageManagerService.TAG,
1833                                "No package known for stopped package: " + name);
1834                    }
1835                    XmlUtils.skipCurrentTag(parser);
1836                } else {
1837                    Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
1838                          + parser.getName());
1839                    XmlUtils.skipCurrentTag(parser);
1840                }
1841            }
1842
1843            str.close();
1844
1845        } catch (XmlPullParserException e) {
1846            mReadMessages.append("Error reading: " + e.toString());
1847            PackageManagerService.reportSettingsProblem(Log.ERROR,
1848                    "Error reading stopped packages: " + e);
1849            Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
1850                    e);
1851
1852        } catch (java.io.IOException e) {
1853            mReadMessages.append("Error reading: " + e.toString());
1854            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
1855            Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
1856                    e);
1857
1858        }
1859    }
1860
1861    void writeLPr() {
1862        //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
1863
1864        // Keep the old settings around until we know the new ones have
1865        // been successfully written.
1866        if (mSettingsFilename.exists()) {
1867            // Presence of backup settings file indicates that we failed
1868            // to persist settings earlier. So preserve the older
1869            // backup for future reference since the current settings
1870            // might have been corrupted.
1871            if (!mBackupSettingsFilename.exists()) {
1872                if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
1873                    Slog.wtf(PackageManagerService.TAG,
1874                            "Unable to backup package manager settings, "
1875                            + " current changes will be lost at reboot");
1876                    return;
1877                }
1878            } else {
1879                mSettingsFilename.delete();
1880                Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
1881            }
1882        }
1883
1884        mPastSignatures.clear();
1885
1886        try {
1887            FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
1888            BufferedOutputStream str = new BufferedOutputStream(fstr);
1889
1890            //XmlSerializer serializer = XmlUtils.serializerInstance();
1891            XmlSerializer serializer = new FastXmlSerializer();
1892            serializer.setOutput(str, "utf-8");
1893            serializer.startDocument(null, true);
1894            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1895
1896            serializer.startTag(null, "packages");
1897
1898            serializer.startTag(null, "last-platform-version");
1899            serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
1900            serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
1901            serializer.attribute(null, "fingerprint", mFingerprint);
1902            serializer.endTag(null, "last-platform-version");
1903
1904            serializer.startTag(null, "database-version");
1905            serializer.attribute(null, "internal", Integer.toString(mInternalDatabaseVersion));
1906            serializer.attribute(null, "external", Integer.toString(mExternalDatabaseVersion));
1907            serializer.endTag(null, "database-version");
1908
1909            if (mVerifierDeviceIdentity != null) {
1910                serializer.startTag(null, "verifier");
1911                serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
1912                serializer.endTag(null, "verifier");
1913            }
1914
1915            if (mReadExternalStorageEnforced != null) {
1916                serializer.startTag(null, TAG_READ_EXTERNAL_STORAGE);
1917                serializer.attribute(
1918                        null, ATTR_ENFORCEMENT, mReadExternalStorageEnforced ? "1" : "0");
1919                serializer.endTag(null, TAG_READ_EXTERNAL_STORAGE);
1920            }
1921
1922            serializer.startTag(null, "permission-trees");
1923            for (BasePermission bp : mPermissionTrees.values()) {
1924                writePermissionLPr(serializer, bp);
1925            }
1926            serializer.endTag(null, "permission-trees");
1927
1928            serializer.startTag(null, "permissions");
1929            for (BasePermission bp : mPermissions.values()) {
1930                writePermissionLPr(serializer, bp);
1931            }
1932            serializer.endTag(null, "permissions");
1933
1934            for (final PackageSetting pkg : mPackages.values()) {
1935                writePackageLPr(serializer, pkg);
1936            }
1937
1938            for (final PackageSetting pkg : mDisabledSysPackages.values()) {
1939                writeDisabledSysPackageLPr(serializer, pkg);
1940            }
1941
1942            for (final SharedUserSetting usr : mSharedUsers.values()) {
1943                serializer.startTag(null, "shared-user");
1944                serializer.attribute(null, ATTR_NAME, usr.name);
1945                serializer.attribute(null, "userId",
1946                        Integer.toString(usr.userId));
1947                usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
1948                writePermissionsLPr(serializer, usr.getPermissionsState().getInstallPermissions());
1949                serializer.endTag(null, "shared-user");
1950            }
1951
1952            if (mPackagesToBeCleaned.size() > 0) {
1953                for (PackageCleanItem item : mPackagesToBeCleaned) {
1954                    final String userStr = Integer.toString(item.userId);
1955                    serializer.startTag(null, "cleaning-package");
1956                    serializer.attribute(null, ATTR_NAME, item.packageName);
1957                    serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
1958                    serializer.attribute(null, ATTR_USER, userStr);
1959                    serializer.endTag(null, "cleaning-package");
1960                }
1961            }
1962
1963            if (mRenamedPackages.size() > 0) {
1964                for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
1965                    serializer.startTag(null, "renamed-package");
1966                    serializer.attribute(null, "new", e.getKey());
1967                    serializer.attribute(null, "old", e.getValue());
1968                    serializer.endTag(null, "renamed-package");
1969                }
1970            }
1971
1972            mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
1973
1974            serializer.endTag(null, "packages");
1975
1976            serializer.endDocument();
1977
1978            str.flush();
1979            FileUtils.sync(fstr);
1980            str.close();
1981
1982            // New settings successfully written, old ones are no longer
1983            // needed.
1984            mBackupSettingsFilename.delete();
1985            FileUtils.setPermissions(mSettingsFilename.toString(),
1986                    FileUtils.S_IRUSR|FileUtils.S_IWUSR
1987                    |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
1988                    -1, -1);
1989
1990            // Write package list file now, use a JournaledFile.
1991            File tempFile = new File(mPackageListFilename.getAbsolutePath() + ".tmp");
1992            JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
1993
1994            final File writeTarget = journal.chooseForWrite();
1995            fstr = new FileOutputStream(writeTarget);
1996            str = new BufferedOutputStream(fstr);
1997            try {
1998                FileUtils.setPermissions(fstr.getFD(), 0640, SYSTEM_UID, PACKAGE_INFO_GID);
1999
2000                StringBuilder sb = new StringBuilder();
2001                for (final PackageSetting pkg : mPackages.values()) {
2002                    if (pkg.pkg == null || pkg.pkg.applicationInfo == null) {
2003                        Slog.w(TAG, "Skipping " + pkg + " due to missing metadata");
2004                        continue;
2005                    }
2006
2007                    final ApplicationInfo ai = pkg.pkg.applicationInfo;
2008                    final String dataPath = ai.dataDir;
2009                    final boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
2010                    final int[] gids = pkg.getPermissionsState().computeGids();
2011
2012                    // Avoid any application that has a space in its path.
2013                    if (dataPath.indexOf(" ") >= 0)
2014                        continue;
2015
2016                    // we store on each line the following information for now:
2017                    //
2018                    // pkgName    - package name
2019                    // userId     - application-specific user id
2020                    // debugFlag  - 0 or 1 if the package is debuggable.
2021                    // dataPath   - path to package's data path
2022                    // seinfo     - seinfo label for the app (assigned at install time)
2023                    // gids       - supplementary gids this app launches with
2024                    //
2025                    // NOTE: We prefer not to expose all ApplicationInfo flags for now.
2026                    //
2027                    // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
2028                    // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
2029                    //   system/core/logd/LogStatistics.cpp
2030                    //   system/core/run-as/run-as.c
2031                    //   system/core/sdcard/sdcard.c
2032                    //   external/libselinux/src/android.c:package_info_init()
2033                    //
2034                    sb.setLength(0);
2035                    sb.append(ai.packageName);
2036                    sb.append(" ");
2037                    sb.append((int)ai.uid);
2038                    sb.append(isDebug ? " 1 " : " 0 ");
2039                    sb.append(dataPath);
2040                    sb.append(" ");
2041                    sb.append(ai.seinfo);
2042                    sb.append(" ");
2043                    if (gids != null && gids.length > 0) {
2044                        sb.append(gids[0]);
2045                        for (int i = 1; i < gids.length; i++) {
2046                            sb.append(",");
2047                            sb.append(gids[i]);
2048                        }
2049                    } else {
2050                        sb.append("none");
2051                    }
2052                    sb.append("\n");
2053                    str.write(sb.toString().getBytes());
2054                }
2055                str.flush();
2056                FileUtils.sync(fstr);
2057                str.close();
2058                journal.commit();
2059            } catch (Exception e) {
2060                Slog.wtf(TAG, "Failed to write packages.list", e);
2061                IoUtils.closeQuietly(str);
2062                journal.rollback();
2063            }
2064
2065            writeAllUsersPackageRestrictionsLPr();
2066
2067            writeAllRuntimePermissionsLPr();
2068            return;
2069
2070        } catch(XmlPullParserException e) {
2071            Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
2072                    + "current changes will be lost at reboot", e);
2073        } catch(java.io.IOException e) {
2074            Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
2075                    + "current changes will be lost at reboot", e);
2076        }
2077        // Clean up partially written files
2078        if (mSettingsFilename.exists()) {
2079            if (!mSettingsFilename.delete()) {
2080                Slog.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
2081                        + mSettingsFilename);
2082            }
2083        }
2084        //Debug.stopMethodTracing();
2085    }
2086
2087    void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
2088            throws java.io.IOException {
2089        serializer.startTag(null, "updated-package");
2090        serializer.attribute(null, ATTR_NAME, pkg.name);
2091        if (pkg.realName != null) {
2092            serializer.attribute(null, "realName", pkg.realName);
2093        }
2094        serializer.attribute(null, "codePath", pkg.codePathString);
2095        serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
2096        serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
2097        serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
2098        serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
2099        if (!pkg.resourcePathString.equals(pkg.codePathString)) {
2100            serializer.attribute(null, "resourcePath", pkg.resourcePathString);
2101        }
2102        if (pkg.legacyNativeLibraryPathString != null) {
2103            serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString);
2104        }
2105        if (pkg.primaryCpuAbiString != null) {
2106           serializer.attribute(null, "primaryCpuAbi", pkg.primaryCpuAbiString);
2107        }
2108        if (pkg.secondaryCpuAbiString != null) {
2109            serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString);
2110        }
2111        if (pkg.cpuAbiOverrideString != null) {
2112            serializer.attribute(null, "cpuAbiOverride", pkg.cpuAbiOverrideString);
2113        }
2114
2115        if (pkg.sharedUser == null) {
2116            serializer.attribute(null, "userId", Integer.toString(pkg.appId));
2117        } else {
2118            serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId));
2119        }
2120
2121        // If this is a shared user, the permissions will be written there.
2122        if (pkg.sharedUser == null) {
2123            writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissions());
2124        }
2125
2126        serializer.endTag(null, "updated-package");
2127    }
2128
2129    void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg)
2130            throws java.io.IOException {
2131        serializer.startTag(null, "package");
2132        serializer.attribute(null, ATTR_NAME, pkg.name);
2133        if (pkg.realName != null) {
2134            serializer.attribute(null, "realName", pkg.realName);
2135        }
2136        serializer.attribute(null, "codePath", pkg.codePathString);
2137        if (!pkg.resourcePathString.equals(pkg.codePathString)) {
2138            serializer.attribute(null, "resourcePath", pkg.resourcePathString);
2139        }
2140
2141        if (pkg.legacyNativeLibraryPathString != null) {
2142            serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString);
2143        }
2144        if (pkg.primaryCpuAbiString != null) {
2145            serializer.attribute(null, "primaryCpuAbi", pkg.primaryCpuAbiString);
2146        }
2147        if (pkg.secondaryCpuAbiString != null) {
2148            serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString);
2149        }
2150        if (pkg.cpuAbiOverrideString != null) {
2151            serializer.attribute(null, "cpuAbiOverride", pkg.cpuAbiOverrideString);
2152        }
2153
2154        serializer.attribute(null, "publicFlags", Integer.toString(pkg.pkgFlags));
2155        serializer.attribute(null, "privateFlags", Integer.toString(pkg.pkgPrivateFlags));
2156        serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
2157        serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
2158        serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
2159        serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
2160        if (pkg.sharedUser == null) {
2161            serializer.attribute(null, "userId", Integer.toString(pkg.appId));
2162        } else {
2163            serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId));
2164        }
2165        if (pkg.uidError) {
2166            serializer.attribute(null, "uidError", "true");
2167        }
2168        if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
2169            serializer.attribute(null, "installStatus", "false");
2170        }
2171        if (pkg.installerPackageName != null) {
2172            serializer.attribute(null, "installer", pkg.installerPackageName);
2173        }
2174        if (pkg.volumeUuid != null) {
2175            serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
2176        }
2177        pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
2178        if ((pkg.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
2179            writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissions());
2180        }
2181
2182        writeSigningKeySetLPr(serializer, pkg.keySetData);
2183        writeUpgradeKeySetsLPr(serializer, pkg.keySetData);
2184        writeKeySetAliasesLPr(serializer, pkg.keySetData);
2185        writeDomainVerificationsLPr(serializer, pkg.verificationInfo);
2186
2187        serializer.endTag(null, "package");
2188    }
2189
2190    void writeSigningKeySetLPr(XmlSerializer serializer,
2191            PackageKeySetData data) throws IOException {
2192        serializer.startTag(null, "proper-signing-keyset");
2193        serializer.attribute(null, "identifier",
2194                Long.toString(data.getProperSigningKeySet()));
2195        serializer.endTag(null, "proper-signing-keyset");
2196    }
2197
2198    void writeUpgradeKeySetsLPr(XmlSerializer serializer,
2199            PackageKeySetData data) throws IOException {
2200        long properSigning = data.getProperSigningKeySet();
2201        if (data.isUsingUpgradeKeySets()) {
2202            for (long id : data.getUpgradeKeySets()) {
2203                serializer.startTag(null, "upgrade-keyset");
2204                serializer.attribute(null, "identifier", Long.toString(id));
2205                serializer.endTag(null, "upgrade-keyset");
2206            }
2207        }
2208    }
2209
2210    void writeKeySetAliasesLPr(XmlSerializer serializer,
2211            PackageKeySetData data) throws IOException {
2212        for (Map.Entry<String, Long> e: data.getAliases().entrySet()) {
2213            serializer.startTag(null, "defined-keyset");
2214            serializer.attribute(null, "alias", e.getKey());
2215            serializer.attribute(null, "identifier", Long.toString(e.getValue()));
2216            serializer.endTag(null, "defined-keyset");
2217        }
2218    }
2219
2220    void writePermissionLPr(XmlSerializer serializer, BasePermission bp)
2221            throws XmlPullParserException, java.io.IOException {
2222        if (bp.type != BasePermission.TYPE_BUILTIN && bp.sourcePackage != null) {
2223            serializer.startTag(null, TAG_ITEM);
2224            serializer.attribute(null, ATTR_NAME, bp.name);
2225            serializer.attribute(null, "package", bp.sourcePackage);
2226            if (bp.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
2227                serializer.attribute(null, "protection", Integer.toString(bp.protectionLevel));
2228            }
2229            if (PackageManagerService.DEBUG_SETTINGS)
2230                Log.v(PackageManagerService.TAG, "Writing perm: name=" + bp.name + " type="
2231                        + bp.type);
2232            if (bp.type == BasePermission.TYPE_DYNAMIC) {
2233                final PermissionInfo pi = bp.perm != null ? bp.perm.info : bp.pendingInfo;
2234                if (pi != null) {
2235                    serializer.attribute(null, "type", "dynamic");
2236                    if (pi.icon != 0) {
2237                        serializer.attribute(null, "icon", Integer.toString(pi.icon));
2238                    }
2239                    if (pi.nonLocalizedLabel != null) {
2240                        serializer.attribute(null, "label", pi.nonLocalizedLabel.toString());
2241                    }
2242                }
2243            }
2244            serializer.endTag(null, TAG_ITEM);
2245        }
2246    }
2247
2248    ArrayList<PackageSetting> getListOfIncompleteInstallPackagesLPr() {
2249        final ArraySet<String> kList = new ArraySet<String>(mPackages.keySet());
2250        final Iterator<String> its = kList.iterator();
2251        final ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
2252        while (its.hasNext()) {
2253            final String key = its.next();
2254            final PackageSetting ps = mPackages.get(key);
2255            if (ps.getInstallStatus() == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
2256                ret.add(ps);
2257            }
2258        }
2259        return ret;
2260    }
2261
2262    void addPackageToCleanLPw(PackageCleanItem pkg) {
2263        if (!mPackagesToBeCleaned.contains(pkg)) {
2264            mPackagesToBeCleaned.add(pkg);
2265        }
2266    }
2267
2268    boolean readLPw(PackageManagerService service, List<UserInfo> users, int sdkVersion,
2269            boolean onlyCore) {
2270        FileInputStream str = null;
2271        if (mBackupSettingsFilename.exists()) {
2272            try {
2273                str = new FileInputStream(mBackupSettingsFilename);
2274                mReadMessages.append("Reading from backup settings file\n");
2275                PackageManagerService.reportSettingsProblem(Log.INFO,
2276                        "Need to read from backup settings file");
2277                if (mSettingsFilename.exists()) {
2278                    // If both the backup and settings file exist, we
2279                    // ignore the settings since it might have been
2280                    // corrupted.
2281                    Slog.w(PackageManagerService.TAG, "Cleaning up settings file "
2282                            + mSettingsFilename);
2283                    mSettingsFilename.delete();
2284                }
2285            } catch (java.io.IOException e) {
2286                // We'll try for the normal settings file.
2287            }
2288        }
2289
2290        mPendingPackages.clear();
2291        mPastSignatures.clear();
2292        mKeySetRefs.clear();
2293
2294        try {
2295            if (str == null) {
2296                if (!mSettingsFilename.exists()) {
2297                    mReadMessages.append("No settings file found\n");
2298                    PackageManagerService.reportSettingsProblem(Log.INFO,
2299                            "No settings file; creating initial state");
2300                    mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion;
2301                    mFingerprint = Build.FINGERPRINT;
2302                    return false;
2303                }
2304                str = new FileInputStream(mSettingsFilename);
2305            }
2306            XmlPullParser parser = Xml.newPullParser();
2307            parser.setInput(str, null);
2308
2309            int type;
2310            while ((type = parser.next()) != XmlPullParser.START_TAG
2311                    && type != XmlPullParser.END_DOCUMENT) {
2312                ;
2313            }
2314
2315            if (type != XmlPullParser.START_TAG) {
2316                mReadMessages.append("No start tag found in settings file\n");
2317                PackageManagerService.reportSettingsProblem(Log.WARN,
2318                        "No start tag found in package manager settings");
2319                Slog.wtf(PackageManagerService.TAG,
2320                        "No start tag found in package manager settings");
2321                return false;
2322            }
2323
2324            int outerDepth = parser.getDepth();
2325            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2326                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2327                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2328                    continue;
2329                }
2330
2331                String tagName = parser.getName();
2332                if (tagName.equals("package")) {
2333                    readPackageLPw(parser);
2334                } else if (tagName.equals("permissions")) {
2335                    readPermissionsLPw(mPermissions, parser);
2336                } else if (tagName.equals("permission-trees")) {
2337                    readPermissionsLPw(mPermissionTrees, parser);
2338                } else if (tagName.equals("shared-user")) {
2339                    readSharedUserLPw(parser);
2340                } else if (tagName.equals("preferred-packages")) {
2341                    // no longer used.
2342                } else if (tagName.equals("preferred-activities")) {
2343                    // Upgrading from old single-user implementation;
2344                    // these are the preferred activities for user 0.
2345                    readPreferredActivitiesLPw(parser, 0);
2346                } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
2347                    // TODO: check whether this is okay! as it is very
2348                    // similar to how preferred-activities are treated
2349                    readPersistentPreferredActivitiesLPw(parser, 0);
2350                } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
2351                    // TODO: check whether this is okay! as it is very
2352                    // similar to how preferred-activities are treated
2353                    readCrossProfileIntentFiltersLPw(parser, 0);
2354                } else if (tagName.equals(TAG_DEFAULT_BROWSER)) {
2355                    readDefaultAppsLPw(parser, 0);
2356                } else if (tagName.equals("updated-package")) {
2357                    readDisabledSysPackageLPw(parser);
2358                } else if (tagName.equals("cleaning-package")) {
2359                    String name = parser.getAttributeValue(null, ATTR_NAME);
2360                    String userStr = parser.getAttributeValue(null, ATTR_USER);
2361                    String codeStr = parser.getAttributeValue(null, ATTR_CODE);
2362                    if (name != null) {
2363                        int userId = 0;
2364                        boolean andCode = true;
2365                        try {
2366                            if (userStr != null) {
2367                                userId = Integer.parseInt(userStr);
2368                            }
2369                        } catch (NumberFormatException e) {
2370                        }
2371                        if (codeStr != null) {
2372                            andCode = Boolean.parseBoolean(codeStr);
2373                        }
2374                        addPackageToCleanLPw(new PackageCleanItem(userId, name, andCode));
2375                    }
2376                } else if (tagName.equals("renamed-package")) {
2377                    String nname = parser.getAttributeValue(null, "new");
2378                    String oname = parser.getAttributeValue(null, "old");
2379                    if (nname != null && oname != null) {
2380                        mRenamedPackages.put(nname, oname);
2381                    }
2382                } else if (tagName.equals("last-platform-version")) {
2383                    mInternalSdkPlatform = mExternalSdkPlatform = 0;
2384                    try {
2385                        String internal = parser.getAttributeValue(null, "internal");
2386                        if (internal != null) {
2387                            mInternalSdkPlatform = Integer.parseInt(internal);
2388                        }
2389                        String external = parser.getAttributeValue(null, "external");
2390                        if (external != null) {
2391                            mExternalSdkPlatform = Integer.parseInt(external);
2392                        }
2393                    } catch (NumberFormatException e) {
2394                    }
2395                    mFingerprint = parser.getAttributeValue(null, "fingerprint");
2396                } else if (tagName.equals("database-version")) {
2397                    mInternalDatabaseVersion = mExternalDatabaseVersion = 0;
2398                    try {
2399                        String internalDbVersionString = parser.getAttributeValue(null, "internal");
2400                        if (internalDbVersionString != null) {
2401                            mInternalDatabaseVersion = Integer.parseInt(internalDbVersionString);
2402                        }
2403                        String externalDbVersionString = parser.getAttributeValue(null, "external");
2404                        if (externalDbVersionString != null) {
2405                            mExternalDatabaseVersion = Integer.parseInt(externalDbVersionString);
2406                        }
2407                    } catch (NumberFormatException ignored) {
2408                    }
2409                } else if (tagName.equals("verifier")) {
2410                    final String deviceIdentity = parser.getAttributeValue(null, "device");
2411                    try {
2412                        mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
2413                    } catch (IllegalArgumentException e) {
2414                        Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
2415                                + e.getMessage());
2416                    }
2417                } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
2418                    final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
2419                    mReadExternalStorageEnforced = "1".equals(enforcement);
2420                } else if (tagName.equals("keyset-settings")) {
2421                    mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs);
2422                } else {
2423                    Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
2424                            + parser.getName());
2425                    XmlUtils.skipCurrentTag(parser);
2426                }
2427            }
2428
2429            str.close();
2430
2431        } catch (XmlPullParserException e) {
2432            mReadMessages.append("Error reading: " + e.toString());
2433            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
2434            Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
2435
2436        } catch (java.io.IOException e) {
2437            mReadMessages.append("Error reading: " + e.toString());
2438            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
2439            Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
2440        }
2441
2442        final int N = mPendingPackages.size();
2443
2444        for (int i = 0; i < N; i++) {
2445            final PendingPackage pp = mPendingPackages.get(i);
2446            Object idObj = getUserIdLPr(pp.sharedId);
2447            if (idObj != null && idObj instanceof SharedUserSetting) {
2448                PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
2449                        (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
2450                        pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString,
2451                        pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags, pp.pkgPrivateFlags,
2452                        null, true /* add */, false /* allowInstall */);
2453                if (p == null) {
2454                    PackageManagerService.reportSettingsProblem(Log.WARN,
2455                            "Unable to create application package for " + pp.name);
2456                    continue;
2457                }
2458                p.copyFrom(pp);
2459            } else if (idObj != null) {
2460                String msg = "Bad package setting: package " + pp.name + " has shared uid "
2461                        + pp.sharedId + " that is not a shared uid\n";
2462                mReadMessages.append(msg);
2463                PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
2464            } else {
2465                String msg = "Bad package setting: package " + pp.name + " has shared uid "
2466                        + pp.sharedId + " that is not defined\n";
2467                mReadMessages.append(msg);
2468                PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
2469            }
2470        }
2471        mPendingPackages.clear();
2472
2473        if (mBackupStoppedPackagesFilename.exists()
2474                || mStoppedPackagesFilename.exists()) {
2475            // Read old file
2476            readStoppedLPw();
2477            mBackupStoppedPackagesFilename.delete();
2478            mStoppedPackagesFilename.delete();
2479            // Migrate to new file format
2480            writePackageRestrictionsLPr(0);
2481        } else {
2482            if (users == null) {
2483                readPackageRestrictionsLPr(0);
2484                mRuntimePermissionsPersistence.readStateForUserSyncLPr(UserHandle.USER_OWNER);
2485            } else {
2486                for (UserInfo user : users) {
2487                    readPackageRestrictionsLPr(user.id);
2488                    mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id);
2489                }
2490            }
2491        }
2492
2493        /*
2494         * Make sure all the updated system packages have their shared users
2495         * associated with them.
2496         */
2497        final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
2498        while (disabledIt.hasNext()) {
2499            final PackageSetting disabledPs = disabledIt.next();
2500            final Object id = getUserIdLPr(disabledPs.appId);
2501            if (id != null && id instanceof SharedUserSetting) {
2502                disabledPs.sharedUser = (SharedUserSetting) id;
2503            }
2504        }
2505
2506        mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
2507                + mSharedUsers.size() + " shared uids\n");
2508
2509        return true;
2510    }
2511
2512    void readDefaultPreferredAppsLPw(PackageManagerService service, int userId) {
2513        // First pull data from any pre-installed apps.
2514        for (PackageSetting ps : mPackages.values()) {
2515            if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null
2516                    && ps.pkg.preferredActivityFilters != null) {
2517                ArrayList<PackageParser.ActivityIntentInfo> intents
2518                        = ps.pkg.preferredActivityFilters;
2519                for (int i=0; i<intents.size(); i++) {
2520                    PackageParser.ActivityIntentInfo aii = intents.get(i);
2521                    applyDefaultPreferredActivityLPw(service, aii, new ComponentName(
2522                            ps.name, aii.activity.className), userId);
2523                }
2524            }
2525        }
2526
2527        // Read preferred apps from .../etc/preferred-apps directory.
2528        File preferredDir = new File(Environment.getRootDirectory(), "etc/preferred-apps");
2529        if (!preferredDir.exists() || !preferredDir.isDirectory()) {
2530            return;
2531        }
2532        if (!preferredDir.canRead()) {
2533            Slog.w(TAG, "Directory " + preferredDir + " cannot be read");
2534            return;
2535        }
2536
2537        // Iterate over the files in the directory and scan .xml files
2538        for (File f : preferredDir.listFiles()) {
2539            if (!f.getPath().endsWith(".xml")) {
2540                Slog.i(TAG, "Non-xml file " + f + " in " + preferredDir + " directory, ignoring");
2541                continue;
2542            }
2543            if (!f.canRead()) {
2544                Slog.w(TAG, "Preferred apps file " + f + " cannot be read");
2545                continue;
2546            }
2547
2548            if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Reading default preferred " + f);
2549            FileInputStream str = null;
2550            try {
2551                str = new FileInputStream(f);
2552                XmlPullParser parser = Xml.newPullParser();
2553                parser.setInput(str, null);
2554
2555                int type;
2556                while ((type = parser.next()) != XmlPullParser.START_TAG
2557                        && type != XmlPullParser.END_DOCUMENT) {
2558                    ;
2559                }
2560
2561                if (type != XmlPullParser.START_TAG) {
2562                    Slog.w(TAG, "Preferred apps file " + f + " does not have start tag");
2563                    continue;
2564                }
2565                if (!"preferred-activities".equals(parser.getName())) {
2566                    Slog.w(TAG, "Preferred apps file " + f
2567                            + " does not start with 'preferred-activities'");
2568                    continue;
2569                }
2570                readDefaultPreferredActivitiesLPw(service, parser, userId);
2571            } catch (XmlPullParserException e) {
2572                Slog.w(TAG, "Error reading apps file " + f, e);
2573            } catch (IOException e) {
2574                Slog.w(TAG, "Error reading apps file " + f, e);
2575            } finally {
2576                if (str != null) {
2577                    try {
2578                        str.close();
2579                    } catch (IOException e) {
2580                    }
2581                }
2582            }
2583        }
2584    }
2585
2586    private void applyDefaultPreferredActivityLPw(PackageManagerService service,
2587            IntentFilter tmpPa, ComponentName cn, int userId) {
2588        // The initial preferences only specify the target activity
2589        // component and intent-filter, not the set of matches.  So we
2590        // now need to query for the matches to build the correct
2591        // preferred activity entry.
2592        if (PackageManagerService.DEBUG_PREFERRED) {
2593            Log.d(TAG, "Processing preferred:");
2594            tmpPa.dump(new LogPrinter(Log.DEBUG, TAG), "  ");
2595        }
2596        Intent intent = new Intent();
2597        int flags = 0;
2598        intent.setAction(tmpPa.getAction(0));
2599        for (int i=0; i<tmpPa.countCategories(); i++) {
2600            String cat = tmpPa.getCategory(i);
2601            if (cat.equals(Intent.CATEGORY_DEFAULT)) {
2602                flags |= PackageManager.MATCH_DEFAULT_ONLY;
2603            } else {
2604                intent.addCategory(cat);
2605            }
2606        }
2607
2608        boolean doNonData = true;
2609        boolean hasSchemes = false;
2610
2611        for (int ischeme=0; ischeme<tmpPa.countDataSchemes(); ischeme++) {
2612            boolean doScheme = true;
2613            String scheme = tmpPa.getDataScheme(ischeme);
2614            if (scheme != null && !scheme.isEmpty()) {
2615                hasSchemes = true;
2616            }
2617            for (int issp=0; issp<tmpPa.countDataSchemeSpecificParts(); issp++) {
2618                Uri.Builder builder = new Uri.Builder();
2619                builder.scheme(scheme);
2620                PatternMatcher ssp = tmpPa.getDataSchemeSpecificPart(issp);
2621                builder.opaquePart(ssp.getPath());
2622                Intent finalIntent = new Intent(intent);
2623                finalIntent.setData(builder.build());
2624                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
2625                        scheme, ssp, null, null, userId);
2626                doScheme = false;
2627            }
2628            for (int iauth=0; iauth<tmpPa.countDataAuthorities(); iauth++) {
2629                boolean doAuth = true;
2630                IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(iauth);
2631                for (int ipath=0; ipath<tmpPa.countDataPaths(); ipath++) {
2632                    Uri.Builder builder = new Uri.Builder();
2633                    builder.scheme(scheme);
2634                    if (auth.getHost() != null) {
2635                        builder.authority(auth.getHost());
2636                    }
2637                    PatternMatcher path = tmpPa.getDataPath(ipath);
2638                    builder.path(path.getPath());
2639                    Intent finalIntent = new Intent(intent);
2640                    finalIntent.setData(builder.build());
2641                    applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
2642                            scheme, null, auth, path, userId);
2643                    doAuth = doScheme = false;
2644                }
2645                if (doAuth) {
2646                    Uri.Builder builder = new Uri.Builder();
2647                    builder.scheme(scheme);
2648                    if (auth.getHost() != null) {
2649                        builder.authority(auth.getHost());
2650                    }
2651                    Intent finalIntent = new Intent(intent);
2652                    finalIntent.setData(builder.build());
2653                    applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
2654                            scheme, null, auth, null, userId);
2655                    doScheme = false;
2656                }
2657            }
2658            if (doScheme) {
2659                Uri.Builder builder = new Uri.Builder();
2660                builder.scheme(scheme);
2661                Intent finalIntent = new Intent(intent);
2662                finalIntent.setData(builder.build());
2663                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
2664                        scheme, null, null, null, userId);
2665            }
2666            doNonData = false;
2667        }
2668
2669        for (int idata=0; idata<tmpPa.countDataTypes(); idata++) {
2670            String mimeType = tmpPa.getDataType(idata);
2671            if (hasSchemes) {
2672                Uri.Builder builder = new Uri.Builder();
2673                for (int ischeme=0; ischeme<tmpPa.countDataSchemes(); ischeme++) {
2674                    String scheme = tmpPa.getDataScheme(ischeme);
2675                    if (scheme != null && !scheme.isEmpty()) {
2676                        Intent finalIntent = new Intent(intent);
2677                        builder.scheme(scheme);
2678                        finalIntent.setDataAndType(builder.build(), mimeType);
2679                        applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
2680                                scheme, null, null, null, userId);
2681                    }
2682                }
2683            } else {
2684                Intent finalIntent = new Intent(intent);
2685                finalIntent.setType(mimeType);
2686                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
2687                        null, null, null, null, userId);
2688            }
2689            doNonData = false;
2690        }
2691
2692        if (doNonData) {
2693            applyDefaultPreferredActivityLPw(service, intent, flags, cn,
2694                    null, null, null, null, userId);
2695        }
2696    }
2697
2698    private void applyDefaultPreferredActivityLPw(PackageManagerService service,
2699            Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
2700            IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
2701        List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
2702                intent.getType(), flags, 0);
2703        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
2704                + " results: " + ri);
2705        int systemMatch = 0;
2706        int thirdPartyMatch = 0;
2707        if (ri != null && ri.size() > 1) {
2708            boolean haveAct = false;
2709            ComponentName haveNonSys = null;
2710            ComponentName[] set = new ComponentName[ri.size()];
2711            for (int i=0; i<ri.size(); i++) {
2712                ActivityInfo ai = ri.get(i).activityInfo;
2713                set[i] = new ComponentName(ai.packageName, ai.name);
2714                if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2715                    if (ri.get(i).match >= thirdPartyMatch) {
2716                        // Keep track of the best match we find of all third
2717                        // party apps, for use later to determine if we actually
2718                        // want to set a preferred app for this intent.
2719                        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
2720                                + ai.packageName + "/" + ai.name + ": non-system!");
2721                        haveNonSys = set[i];
2722                        break;
2723                    }
2724                } else if (cn.getPackageName().equals(ai.packageName)
2725                        && cn.getClassName().equals(ai.name)) {
2726                    if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
2727                            + ai.packageName + "/" + ai.name + ": default!");
2728                    haveAct = true;
2729                    systemMatch = ri.get(i).match;
2730                } else {
2731                    if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
2732                            + ai.packageName + "/" + ai.name + ": skipped");
2733                }
2734            }
2735            if (haveNonSys != null && thirdPartyMatch < systemMatch) {
2736                // If we have a matching third party app, but its match is not as
2737                // good as the built-in system app, then we don't want to actually
2738                // consider it a match because presumably the built-in app is still
2739                // the thing we want users to see by default.
2740                haveNonSys = null;
2741            }
2742            if (haveAct && haveNonSys == null) {
2743                IntentFilter filter = new IntentFilter();
2744                if (intent.getAction() != null) {
2745                    filter.addAction(intent.getAction());
2746                }
2747                if (intent.getCategories() != null) {
2748                    for (String cat : intent.getCategories()) {
2749                        filter.addCategory(cat);
2750                    }
2751                }
2752                if ((flags&PackageManager.MATCH_DEFAULT_ONLY) != 0) {
2753                    filter.addCategory(Intent.CATEGORY_DEFAULT);
2754                }
2755                if (scheme != null) {
2756                    filter.addDataScheme(scheme);
2757                }
2758                if (ssp != null) {
2759                    filter.addDataSchemeSpecificPart(ssp.getPath(), ssp.getType());
2760                }
2761                if (auth != null) {
2762                    filter.addDataAuthority(auth);
2763                }
2764                if (path != null) {
2765                    filter.addDataPath(path);
2766                }
2767                if (intent.getType() != null) {
2768                    try {
2769                        filter.addDataType(intent.getType());
2770                    } catch (IntentFilter.MalformedMimeTypeException ex) {
2771                        Slog.w(TAG, "Malformed mimetype " + intent.getType() + " for " + cn);
2772                    }
2773                }
2774                PreferredActivity pa = new PreferredActivity(filter, systemMatch, set, cn, true);
2775                editPreferredActivitiesLPw(userId).addFilter(pa);
2776            } else if (haveNonSys == null) {
2777                StringBuilder sb = new StringBuilder();
2778                sb.append("No component ");
2779                sb.append(cn.flattenToShortString());
2780                sb.append(" found setting preferred ");
2781                sb.append(intent);
2782                sb.append("; possible matches are ");
2783                for (int i=0; i<set.length; i++) {
2784                    if (i > 0) sb.append(", ");
2785                    sb.append(set[i].flattenToShortString());
2786                }
2787                Slog.w(TAG, sb.toString());
2788            } else {
2789                Slog.i(TAG, "Not setting preferred " + intent + "; found third party match "
2790                        + haveNonSys.flattenToShortString());
2791            }
2792        } else {
2793            Slog.w(TAG, "No potential matches found for " + intent + " while setting preferred "
2794                    + cn.flattenToShortString());
2795        }
2796    }
2797
2798    private void readDefaultPreferredActivitiesLPw(PackageManagerService service,
2799            XmlPullParser parser, int userId)
2800            throws XmlPullParserException, IOException {
2801        int outerDepth = parser.getDepth();
2802        int type;
2803        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2804                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2805            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2806                continue;
2807            }
2808
2809            String tagName = parser.getName();
2810            if (tagName.equals(TAG_ITEM)) {
2811                PreferredActivity tmpPa = new PreferredActivity(parser);
2812                if (tmpPa.mPref.getParseError() == null) {
2813                    applyDefaultPreferredActivityLPw(service, tmpPa, tmpPa.mPref.mComponent,
2814                            userId);
2815                } else {
2816                    PackageManagerService.reportSettingsProblem(Log.WARN,
2817                            "Error in package manager settings: <preferred-activity> "
2818                                    + tmpPa.mPref.getParseError() + " at "
2819                                    + parser.getPositionDescription());
2820                }
2821            } else {
2822                PackageManagerService.reportSettingsProblem(Log.WARN,
2823                        "Unknown element under <preferred-activities>: " + parser.getName());
2824                XmlUtils.skipCurrentTag(parser);
2825            }
2826        }
2827    }
2828
2829    private int readInt(XmlPullParser parser, String ns, String name, int defValue) {
2830        String v = parser.getAttributeValue(ns, name);
2831        try {
2832            if (v == null) {
2833                return defValue;
2834            }
2835            return Integer.parseInt(v);
2836        } catch (NumberFormatException e) {
2837            PackageManagerService.reportSettingsProblem(Log.WARN,
2838                    "Error in package manager settings: attribute " + name
2839                            + " has bad integer value " + v + " at "
2840                            + parser.getPositionDescription());
2841        }
2842        return defValue;
2843    }
2844
2845    private void readPermissionsLPw(ArrayMap<String, BasePermission> out, XmlPullParser parser)
2846            throws IOException, XmlPullParserException {
2847        int outerDepth = parser.getDepth();
2848        int type;
2849        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2850                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2851            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2852                continue;
2853            }
2854
2855            final String tagName = parser.getName();
2856            if (tagName.equals(TAG_ITEM)) {
2857                final String name = parser.getAttributeValue(null, ATTR_NAME);
2858                final String sourcePackage = parser.getAttributeValue(null, "package");
2859                final String ptype = parser.getAttributeValue(null, "type");
2860                if (name != null && sourcePackage != null) {
2861                    final boolean dynamic = "dynamic".equals(ptype);
2862                    final BasePermission bp = new BasePermission(name.intern(), sourcePackage,
2863                            dynamic ? BasePermission.TYPE_DYNAMIC : BasePermission.TYPE_NORMAL);
2864                    bp.protectionLevel = readInt(parser, null, "protection",
2865                            PermissionInfo.PROTECTION_NORMAL);
2866                    bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel);
2867                    if (dynamic) {
2868                        PermissionInfo pi = new PermissionInfo();
2869                        pi.packageName = sourcePackage.intern();
2870                        pi.name = name.intern();
2871                        pi.icon = readInt(parser, null, "icon", 0);
2872                        pi.nonLocalizedLabel = parser.getAttributeValue(null, "label");
2873                        pi.protectionLevel = bp.protectionLevel;
2874                        bp.pendingInfo = pi;
2875                    }
2876                    out.put(bp.name, bp);
2877                } else {
2878                    PackageManagerService.reportSettingsProblem(Log.WARN,
2879                            "Error in package manager settings: permissions has" + " no name at "
2880                                    + parser.getPositionDescription());
2881                }
2882            } else {
2883                PackageManagerService.reportSettingsProblem(Log.WARN,
2884                        "Unknown element reading permissions: " + parser.getName() + " at "
2885                                + parser.getPositionDescription());
2886            }
2887            XmlUtils.skipCurrentTag(parser);
2888        }
2889    }
2890
2891    private void readDisabledSysPackageLPw(XmlPullParser parser) throws XmlPullParserException,
2892            IOException {
2893        String name = parser.getAttributeValue(null, ATTR_NAME);
2894        String realName = parser.getAttributeValue(null, "realName");
2895        String codePathStr = parser.getAttributeValue(null, "codePath");
2896        String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
2897
2898        String legacyCpuAbiStr = parser.getAttributeValue(null, "requiredCpuAbi");
2899        String legacyNativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
2900
2901        String primaryCpuAbiStr = parser.getAttributeValue(null, "primaryCpuAbi");
2902        String secondaryCpuAbiStr = parser.getAttributeValue(null, "secondaryCpuAbi");
2903        String cpuAbiOverrideStr = parser.getAttributeValue(null, "cpuAbiOverride");
2904
2905        if (primaryCpuAbiStr == null && legacyCpuAbiStr != null) {
2906            primaryCpuAbiStr = legacyCpuAbiStr;
2907        }
2908
2909        if (resourcePathStr == null) {
2910            resourcePathStr = codePathStr;
2911        }
2912        String version = parser.getAttributeValue(null, "version");
2913        int versionCode = 0;
2914        if (version != null) {
2915            try {
2916                versionCode = Integer.parseInt(version);
2917            } catch (NumberFormatException e) {
2918            }
2919        }
2920
2921        int pkgFlags = 0;
2922        int pkgPrivateFlags = 0;
2923        pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
2924        final File codePathFile = new File(codePathStr);
2925        if (PackageManagerService.locationIsPrivileged(codePathFile)) {
2926            pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
2927        }
2928        PackageSetting ps = new PackageSetting(name, realName, codePathFile,
2929                new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
2930                secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags);
2931        String timeStampStr = parser.getAttributeValue(null, "ft");
2932        if (timeStampStr != null) {
2933            try {
2934                long timeStamp = Long.parseLong(timeStampStr, 16);
2935                ps.setTimeStamp(timeStamp);
2936            } catch (NumberFormatException e) {
2937            }
2938        } else {
2939            timeStampStr = parser.getAttributeValue(null, "ts");
2940            if (timeStampStr != null) {
2941                try {
2942                    long timeStamp = Long.parseLong(timeStampStr);
2943                    ps.setTimeStamp(timeStamp);
2944                } catch (NumberFormatException e) {
2945                }
2946            }
2947        }
2948        timeStampStr = parser.getAttributeValue(null, "it");
2949        if (timeStampStr != null) {
2950            try {
2951                ps.firstInstallTime = Long.parseLong(timeStampStr, 16);
2952            } catch (NumberFormatException e) {
2953            }
2954        }
2955        timeStampStr = parser.getAttributeValue(null, "ut");
2956        if (timeStampStr != null) {
2957            try {
2958                ps.lastUpdateTime = Long.parseLong(timeStampStr, 16);
2959            } catch (NumberFormatException e) {
2960            }
2961        }
2962        String idStr = parser.getAttributeValue(null, "userId");
2963        ps.appId = idStr != null ? Integer.parseInt(idStr) : 0;
2964        if (ps.appId <= 0) {
2965            String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
2966            ps.appId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
2967        }
2968
2969        int outerDepth = parser.getDepth();
2970        int type;
2971        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2972                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2973            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2974                continue;
2975            }
2976
2977            if (parser.getName().equals(TAG_PERMISSIONS)) {
2978                readInstallPermissionsLPr(parser, ps.getPermissionsState());
2979            } else {
2980                PackageManagerService.reportSettingsProblem(Log.WARN,
2981                        "Unknown element under <updated-package>: " + parser.getName());
2982                XmlUtils.skipCurrentTag(parser);
2983            }
2984        }
2985
2986        // We keep track for which users we granted permissions to be able
2987        // to grant runtime permissions to system apps for newly appeared
2988        // users or newly appeared system apps. If we supported runtime
2989        // permissions during the previous boot, then we already granted
2990        // permissions for all device users. In such a case we set the users
2991        // for which we granted permissions to avoid clobbering of runtime
2992        // permissions we granted to system apps but the user revoked later.
2993        if (!isFirstRuntimePermissionsBoot()) {
2994            final int[] userIds = UserManagerService.getInstance().getUserIds();
2995            ps.setPermissionsUpdatedForUserIds(userIds);
2996        }
2997
2998        mDisabledSysPackages.put(name, ps);
2999    }
3000
3001    private static int PRE_M_APP_INFO_FLAG_HIDDEN = 1<<27;
3002    private static int PRE_M_APP_INFO_FLAG_CANT_SAVE_STATE = 1<<28;
3003    private static int PRE_M_APP_INFO_FLAG_FORWARD_LOCK = 1<<29;
3004    private static int PRE_M_APP_INFO_FLAG_PRIVILEGED = 1<<30;
3005
3006    private void readPackageLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
3007        String name = null;
3008        String realName = null;
3009        String idStr = null;
3010        String sharedIdStr = null;
3011        String codePathStr = null;
3012        String resourcePathStr = null;
3013        String legacyCpuAbiString = null;
3014        String legacyNativeLibraryPathStr = null;
3015        String primaryCpuAbiString = null;
3016        String secondaryCpuAbiString = null;
3017        String cpuAbiOverrideString = null;
3018        String systemStr = null;
3019        String installerPackageName = null;
3020        String volumeUuid = null;
3021        String uidError = null;
3022        int pkgFlags = 0;
3023        int pkgPrivateFlags = 0;
3024        long timeStamp = 0;
3025        long firstInstallTime = 0;
3026        long lastUpdateTime = 0;
3027        PackageSettingBase packageSetting = null;
3028        String version = null;
3029        int versionCode = 0;
3030        try {
3031            name = parser.getAttributeValue(null, ATTR_NAME);
3032            realName = parser.getAttributeValue(null, "realName");
3033            idStr = parser.getAttributeValue(null, "userId");
3034            uidError = parser.getAttributeValue(null, "uidError");
3035            sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
3036            codePathStr = parser.getAttributeValue(null, "codePath");
3037            resourcePathStr = parser.getAttributeValue(null, "resourcePath");
3038
3039            legacyCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
3040
3041            legacyNativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
3042            primaryCpuAbiString = parser.getAttributeValue(null, "primaryCpuAbi");
3043            secondaryCpuAbiString = parser.getAttributeValue(null, "secondaryCpuAbi");
3044            cpuAbiOverrideString = parser.getAttributeValue(null, "cpuAbiOverride");
3045
3046            if (primaryCpuAbiString == null && legacyCpuAbiString != null) {
3047                primaryCpuAbiString = legacyCpuAbiString;
3048            }
3049
3050            version = parser.getAttributeValue(null, "version");
3051            if (version != null) {
3052                try {
3053                    versionCode = Integer.parseInt(version);
3054                } catch (NumberFormatException e) {
3055                }
3056            }
3057            installerPackageName = parser.getAttributeValue(null, "installer");
3058            volumeUuid = parser.getAttributeValue(null, "volumeUuid");
3059
3060            systemStr = parser.getAttributeValue(null, "publicFlags");
3061            if (systemStr != null) {
3062                try {
3063                    pkgFlags = Integer.parseInt(systemStr);
3064                } catch (NumberFormatException e) {
3065                }
3066                systemStr = parser.getAttributeValue(null, "privateFlags");
3067                if (systemStr != null) {
3068                    try {
3069                        pkgPrivateFlags = Integer.parseInt(systemStr);
3070                    } catch (NumberFormatException e) {
3071                    }
3072                }
3073            } else {
3074                // Pre-M -- both public and private flags were stored in one "flags" field.
3075                systemStr = parser.getAttributeValue(null, "flags");
3076                if (systemStr != null) {
3077                    try {
3078                        pkgFlags = Integer.parseInt(systemStr);
3079                    } catch (NumberFormatException e) {
3080                    }
3081                    if ((pkgFlags & PRE_M_APP_INFO_FLAG_HIDDEN) != 0) {
3082                        pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
3083                    }
3084                    if ((pkgFlags & PRE_M_APP_INFO_FLAG_CANT_SAVE_STATE) != 0) {
3085                        pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
3086                    }
3087                    if ((pkgFlags & PRE_M_APP_INFO_FLAG_FORWARD_LOCK) != 0) {
3088                        pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
3089                    }
3090                    if ((pkgFlags & PRE_M_APP_INFO_FLAG_PRIVILEGED) != 0) {
3091                        pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
3092                    }
3093                    pkgFlags &= ~(PRE_M_APP_INFO_FLAG_HIDDEN
3094                            | PRE_M_APP_INFO_FLAG_CANT_SAVE_STATE
3095                            | PRE_M_APP_INFO_FLAG_FORWARD_LOCK
3096                            | PRE_M_APP_INFO_FLAG_PRIVILEGED);
3097                } else {
3098                    // For backward compatibility
3099                    systemStr = parser.getAttributeValue(null, "system");
3100                    if (systemStr != null) {
3101                        pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM
3102                                : 0;
3103                    } else {
3104                        // Old settings that don't specify system... just treat
3105                        // them as system, good enough.
3106                        pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
3107                    }
3108                }
3109            }
3110            String timeStampStr = parser.getAttributeValue(null, "ft");
3111            if (timeStampStr != null) {
3112                try {
3113                    timeStamp = Long.parseLong(timeStampStr, 16);
3114                } catch (NumberFormatException e) {
3115                }
3116            } else {
3117                timeStampStr = parser.getAttributeValue(null, "ts");
3118                if (timeStampStr != null) {
3119                    try {
3120                        timeStamp = Long.parseLong(timeStampStr);
3121                    } catch (NumberFormatException e) {
3122                    }
3123                }
3124            }
3125            timeStampStr = parser.getAttributeValue(null, "it");
3126            if (timeStampStr != null) {
3127                try {
3128                    firstInstallTime = Long.parseLong(timeStampStr, 16);
3129                } catch (NumberFormatException e) {
3130                }
3131            }
3132            timeStampStr = parser.getAttributeValue(null, "ut");
3133            if (timeStampStr != null) {
3134                try {
3135                    lastUpdateTime = Long.parseLong(timeStampStr, 16);
3136                } catch (NumberFormatException e) {
3137                }
3138            }
3139            if (PackageManagerService.DEBUG_SETTINGS)
3140                Log.v(PackageManagerService.TAG, "Reading package: " + name + " userId=" + idStr
3141                        + " sharedUserId=" + sharedIdStr);
3142            int userId = idStr != null ? Integer.parseInt(idStr) : 0;
3143            if (resourcePathStr == null) {
3144                resourcePathStr = codePathStr;
3145            }
3146            if (realName != null) {
3147                realName = realName.intern();
3148            }
3149            if (name == null) {
3150                PackageManagerService.reportSettingsProblem(Log.WARN,
3151                        "Error in package manager settings: <package> has no name at "
3152                                + parser.getPositionDescription());
3153            } else if (codePathStr == null) {
3154                PackageManagerService.reportSettingsProblem(Log.WARN,
3155                        "Error in package manager settings: <package> has no codePath at "
3156                                + parser.getPositionDescription());
3157            } else if (userId > 0) {
3158                packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
3159                        new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
3160                        secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags,
3161                        pkgPrivateFlags);
3162                if (PackageManagerService.DEBUG_SETTINGS)
3163                    Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
3164                            + userId + " pkg=" + packageSetting);
3165                if (packageSetting == null) {
3166                    PackageManagerService.reportSettingsProblem(Log.ERROR, "Failure adding uid "
3167                            + userId + " while parsing settings at "
3168                            + parser.getPositionDescription());
3169                } else {
3170                    packageSetting.setTimeStamp(timeStamp);
3171                    packageSetting.firstInstallTime = firstInstallTime;
3172                    packageSetting.lastUpdateTime = lastUpdateTime;
3173                }
3174            } else if (sharedIdStr != null) {
3175                userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
3176                if (userId > 0) {
3177                    packageSetting = new PendingPackage(name.intern(), realName, new File(
3178                            codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
3179                            primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
3180                            userId, versionCode, pkgFlags, pkgPrivateFlags);
3181                    packageSetting.setTimeStamp(timeStamp);
3182                    packageSetting.firstInstallTime = firstInstallTime;
3183                    packageSetting.lastUpdateTime = lastUpdateTime;
3184                    mPendingPackages.add((PendingPackage) packageSetting);
3185                    if (PackageManagerService.DEBUG_SETTINGS)
3186                        Log.i(PackageManagerService.TAG, "Reading package " + name
3187                                + ": sharedUserId=" + userId + " pkg=" + packageSetting);
3188                } else {
3189                    PackageManagerService.reportSettingsProblem(Log.WARN,
3190                            "Error in package manager settings: package " + name
3191                                    + " has bad sharedId " + sharedIdStr + " at "
3192                                    + parser.getPositionDescription());
3193                }
3194            } else {
3195                PackageManagerService.reportSettingsProblem(Log.WARN,
3196                        "Error in package manager settings: package " + name + " has bad userId "
3197                                + idStr + " at " + parser.getPositionDescription());
3198            }
3199        } catch (NumberFormatException e) {
3200            PackageManagerService.reportSettingsProblem(Log.WARN,
3201                    "Error in package manager settings: package " + name + " has bad userId "
3202                            + idStr + " at " + parser.getPositionDescription());
3203        }
3204        if (packageSetting != null) {
3205            packageSetting.uidError = "true".equals(uidError);
3206            packageSetting.installerPackageName = installerPackageName;
3207            packageSetting.volumeUuid = volumeUuid;
3208            packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr;
3209            packageSetting.primaryCpuAbiString = primaryCpuAbiString;
3210            packageSetting.secondaryCpuAbiString = secondaryCpuAbiString;
3211            // Handle legacy string here for single-user mode
3212            final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
3213            if (enabledStr != null) {
3214                try {
3215                    packageSetting.setEnabled(Integer.parseInt(enabledStr), 0 /* userId */, null);
3216                } catch (NumberFormatException e) {
3217                    if (enabledStr.equalsIgnoreCase("true")) {
3218                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 0, null);
3219                    } else if (enabledStr.equalsIgnoreCase("false")) {
3220                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null);
3221                    } else if (enabledStr.equalsIgnoreCase("default")) {
3222                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0, null);
3223                    } else {
3224                        PackageManagerService.reportSettingsProblem(Log.WARN,
3225                                "Error in package manager settings: package " + name
3226                                        + " has bad enabled value: " + idStr + " at "
3227                                        + parser.getPositionDescription());
3228                    }
3229                }
3230            } else {
3231                packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0, null);
3232            }
3233
3234            final String installStatusStr = parser.getAttributeValue(null, "installStatus");
3235            if (installStatusStr != null) {
3236                if (installStatusStr.equalsIgnoreCase("false")) {
3237                    packageSetting.installStatus = PackageSettingBase.PKG_INSTALL_INCOMPLETE;
3238                } else {
3239                    packageSetting.installStatus = PackageSettingBase.PKG_INSTALL_COMPLETE;
3240                }
3241            }
3242            int outerDepth = parser.getDepth();
3243            int type;
3244            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3245                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3246                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3247                    continue;
3248                }
3249
3250                String tagName = parser.getName();
3251                // Legacy
3252                if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
3253                    readDisabledComponentsLPw(packageSetting, parser, 0);
3254                } else if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
3255                    readEnabledComponentsLPw(packageSetting, parser, 0);
3256                } else if (tagName.equals("sigs")) {
3257                    packageSetting.signatures.readXml(parser, mPastSignatures);
3258                } else if (tagName.equals(TAG_PERMISSIONS)) {
3259                    readInstallPermissionsLPr(parser,
3260                            packageSetting.getPermissionsState());
3261                    packageSetting.installPermissionsFixed = true;
3262                } else if (tagName.equals("proper-signing-keyset")) {
3263                    long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
3264                    Integer refCt = mKeySetRefs.get(id);
3265                    if (refCt != null) {
3266                        mKeySetRefs.put(id, refCt + 1);
3267                    } else {
3268                        mKeySetRefs.put(id, 1);
3269                    }
3270                    packageSetting.keySetData.setProperSigningKeySet(id);
3271                } else if (tagName.equals("signing-keyset")) {
3272                    // from v1 of keysetmanagerservice - no longer used
3273                } else if (tagName.equals("upgrade-keyset")) {
3274                    long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
3275                    packageSetting.keySetData.addUpgradeKeySetById(id);
3276                } else if (tagName.equals("defined-keyset")) {
3277                    long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
3278                    String alias = parser.getAttributeValue(null, "alias");
3279                    Integer refCt = mKeySetRefs.get(id);
3280                    if (refCt != null) {
3281                        mKeySetRefs.put(id, refCt + 1);
3282                    } else {
3283                        mKeySetRefs.put(id, 1);
3284                    }
3285                    packageSetting.keySetData.addDefinedKeySet(id, alias);
3286                } else if (tagName.equals(TAG_DOMAIN_VERIFICATION)) {
3287                    readDomainVerificationLPw(parser, packageSetting);
3288                } else {
3289                    PackageManagerService.reportSettingsProblem(Log.WARN,
3290                            "Unknown element under <package>: " + parser.getName());
3291                    XmlUtils.skipCurrentTag(parser);
3292                }
3293            }
3294
3295            // We keep track for which users we granted permissions to be able
3296            // to grant runtime permissions to system apps for newly appeared
3297            // users or newly appeared system apps. If we supported runtime
3298            // permissions during the previous boot, then we already granted
3299            // permissions for all device users. In such a case we set the users
3300            // for which we granted permissions to avoid clobbering of runtime
3301            // permissions we granted to system apps but the user revoked later.
3302            if (!isFirstRuntimePermissionsBoot()) {
3303                final int[] userIds = UserManagerService.getInstance().getUserIds();
3304                packageSetting.setPermissionsUpdatedForUserIds(userIds);
3305            }
3306        } else {
3307            XmlUtils.skipCurrentTag(parser);
3308        }
3309    }
3310
3311    private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
3312            int userId) throws IOException, XmlPullParserException {
3313        int outerDepth = parser.getDepth();
3314        int type;
3315        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3316                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3317            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3318                continue;
3319            }
3320
3321            String tagName = parser.getName();
3322            if (tagName.equals(TAG_ITEM)) {
3323                String name = parser.getAttributeValue(null, ATTR_NAME);
3324                if (name != null) {
3325                    packageSetting.addDisabledComponent(name.intern(), userId);
3326                } else {
3327                    PackageManagerService.reportSettingsProblem(Log.WARN,
3328                            "Error in package manager settings: <disabled-components> has"
3329                                    + " no name at " + parser.getPositionDescription());
3330                }
3331            } else {
3332                PackageManagerService.reportSettingsProblem(Log.WARN,
3333                        "Unknown element under <disabled-components>: " + parser.getName());
3334            }
3335            XmlUtils.skipCurrentTag(parser);
3336        }
3337    }
3338
3339    private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
3340            int userId) throws IOException, XmlPullParserException {
3341        int outerDepth = parser.getDepth();
3342        int type;
3343        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3344                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3345            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3346                continue;
3347            }
3348
3349            String tagName = parser.getName();
3350            if (tagName.equals(TAG_ITEM)) {
3351                String name = parser.getAttributeValue(null, ATTR_NAME);
3352                if (name != null) {
3353                    packageSetting.addEnabledComponent(name.intern(), userId);
3354                } else {
3355                    PackageManagerService.reportSettingsProblem(Log.WARN,
3356                            "Error in package manager settings: <enabled-components> has"
3357                                    + " no name at " + parser.getPositionDescription());
3358                }
3359            } else {
3360                PackageManagerService.reportSettingsProblem(Log.WARN,
3361                        "Unknown element under <enabled-components>: " + parser.getName());
3362            }
3363            XmlUtils.skipCurrentTag(parser);
3364        }
3365    }
3366
3367    private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException,IOException {
3368        String name = null;
3369        String idStr = null;
3370        int pkgFlags = 0;
3371        int pkgPrivateFlags = 0;
3372        SharedUserSetting su = null;
3373        try {
3374            name = parser.getAttributeValue(null, ATTR_NAME);
3375            idStr = parser.getAttributeValue(null, "userId");
3376            int userId = idStr != null ? Integer.parseInt(idStr) : 0;
3377            if ("true".equals(parser.getAttributeValue(null, "system"))) {
3378                pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
3379            }
3380            if (name == null) {
3381                PackageManagerService.reportSettingsProblem(Log.WARN,
3382                        "Error in package manager settings: <shared-user> has no name at "
3383                                + parser.getPositionDescription());
3384            } else if (userId == 0) {
3385                PackageManagerService.reportSettingsProblem(Log.WARN,
3386                        "Error in package manager settings: shared-user " + name
3387                                + " has bad userId " + idStr + " at "
3388                                + parser.getPositionDescription());
3389            } else {
3390                if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags, pkgPrivateFlags))
3391                        == null) {
3392                    PackageManagerService
3393                            .reportSettingsProblem(Log.ERROR, "Occurred while parsing settings at "
3394                                    + parser.getPositionDescription());
3395                }
3396            }
3397        } catch (NumberFormatException e) {
3398            PackageManagerService.reportSettingsProblem(Log.WARN,
3399                    "Error in package manager settings: package " + name + " has bad userId "
3400                            + idStr + " at " + parser.getPositionDescription());
3401        }
3402
3403        if (su != null) {
3404            int outerDepth = parser.getDepth();
3405            int type;
3406            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3407                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3408                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3409                    continue;
3410                }
3411
3412                String tagName = parser.getName();
3413                if (tagName.equals("sigs")) {
3414                    su.signatures.readXml(parser, mPastSignatures);
3415                } else if (tagName.equals("perms")) {
3416                    readInstallPermissionsLPr(parser, su.getPermissionsState());
3417                } else {
3418                    PackageManagerService.reportSettingsProblem(Log.WARN,
3419                            "Unknown element under <shared-user>: " + parser.getName());
3420                    XmlUtils.skipCurrentTag(parser);
3421                }
3422            }
3423
3424            // We keep track for which users we granted permissions to be able
3425            // to grant runtime permissions to system apps for newly appeared
3426            // users or newly appeared system apps. If we supported runtime
3427            // permissions during the previous boot, then we already granted
3428            // permissions for all device users. In such a case we set the users
3429            // for which we granted permissions to avoid clobbering of runtime
3430            // permissions we granted to system apps but the user revoked later.
3431            if (!isFirstRuntimePermissionsBoot()) {
3432                final int[] userIds = UserManagerService.getInstance().getUserIds();
3433                su.setPermissionsUpdatedForUserIds(userIds);
3434            }
3435        } else {
3436            XmlUtils.skipCurrentTag(parser);
3437        }
3438    }
3439
3440    void createNewUserLILPw(PackageManagerService service, Installer installer,
3441            int userHandle, File path) {
3442        path.mkdir();
3443        FileUtils.setPermissions(path.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
3444                | FileUtils.S_IXOTH, -1, -1);
3445        for (PackageSetting ps : mPackages.values()) {
3446            if (ps.pkg == null || ps.pkg.applicationInfo == null) {
3447                continue;
3448            }
3449            // Only system apps are initially installed.
3450            ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
3451            // Need to create a data directory for all apps under this user.
3452            installer.createUserData(ps.volumeUuid, ps.name,
3453                    UserHandle.getUid(userHandle, ps.appId), userHandle,
3454                    ps.pkg.applicationInfo.seinfo);
3455        }
3456        readDefaultPreferredAppsLPw(service, userHandle);
3457        writePackageRestrictionsLPr(userHandle);
3458    }
3459
3460    void removeUserLPw(int userId) {
3461        Set<Entry<String, PackageSetting>> entries = mPackages.entrySet();
3462        for (Entry<String, PackageSetting> entry : entries) {
3463            entry.getValue().removeUser(userId);
3464        }
3465        mPreferredActivities.remove(userId);
3466        File file = getUserPackagesStateFile(userId);
3467        file.delete();
3468        file = getUserPackagesStateBackupFile(userId);
3469        file.delete();
3470        removeCrossProfileIntentFiltersLPw(userId);
3471
3472        mRuntimePermissionsPersistence.onUserRemoved(userId);
3473    }
3474
3475    void removeCrossProfileIntentFiltersLPw(int userId) {
3476        synchronized (mCrossProfileIntentResolvers) {
3477            // userId is the source user
3478            if (mCrossProfileIntentResolvers.get(userId) != null) {
3479                mCrossProfileIntentResolvers.remove(userId);
3480                writePackageRestrictionsLPr(userId);
3481            }
3482            // userId is the target user
3483            int count = mCrossProfileIntentResolvers.size();
3484            for (int i = 0; i < count; i++) {
3485                int sourceUserId = mCrossProfileIntentResolvers.keyAt(i);
3486                CrossProfileIntentResolver cpir = mCrossProfileIntentResolvers.get(sourceUserId);
3487                boolean needsWriting = false;
3488                ArraySet<CrossProfileIntentFilter> cpifs =
3489                        new ArraySet<CrossProfileIntentFilter>(cpir.filterSet());
3490                for (CrossProfileIntentFilter cpif : cpifs) {
3491                    if (cpif.getTargetUserId() == userId) {
3492                        needsWriting = true;
3493                        cpir.removeFilter(cpif);
3494                    }
3495                }
3496                if (needsWriting) {
3497                    writePackageRestrictionsLPr(sourceUserId);
3498                }
3499            }
3500        }
3501    }
3502
3503    // This should be called (at least) whenever an application is removed
3504    private void setFirstAvailableUid(int uid) {
3505        if (uid > mFirstAvailableUid) {
3506            mFirstAvailableUid = uid;
3507        }
3508    }
3509
3510    // Returns -1 if we could not find an available UserId to assign
3511    private int newUserIdLPw(Object obj) {
3512        // Let's be stupidly inefficient for now...
3513        final int N = mUserIds.size();
3514        for (int i = mFirstAvailableUid; i < N; i++) {
3515            if (mUserIds.get(i) == null) {
3516                mUserIds.set(i, obj);
3517                return Process.FIRST_APPLICATION_UID + i;
3518            }
3519        }
3520
3521        // None left?
3522        if (N > (Process.LAST_APPLICATION_UID-Process.FIRST_APPLICATION_UID)) {
3523            return -1;
3524        }
3525
3526        mUserIds.add(obj);
3527        return Process.FIRST_APPLICATION_UID + N;
3528    }
3529
3530    public VerifierDeviceIdentity getVerifierDeviceIdentityLPw() {
3531        if (mVerifierDeviceIdentity == null) {
3532            mVerifierDeviceIdentity = VerifierDeviceIdentity.generate();
3533
3534            writeLPr();
3535        }
3536
3537        return mVerifierDeviceIdentity;
3538    }
3539
3540    public PackageSetting getDisabledSystemPkgLPr(String name) {
3541        PackageSetting ps = mDisabledSysPackages.get(name);
3542        return ps;
3543    }
3544
3545    private String compToString(ArraySet<String> cmp) {
3546        return cmp != null ? Arrays.toString(cmp.toArray()) : "[]";
3547    }
3548
3549    boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
3550        if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
3551            return true;
3552        }
3553        final String pkgName = componentInfo.packageName;
3554        final PackageSetting packageSettings = mPackages.get(pkgName);
3555        if (PackageManagerService.DEBUG_SETTINGS) {
3556            Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
3557                    + componentInfo.packageName + " componentName = " + componentInfo.name);
3558            Log.v(PackageManagerService.TAG, "enabledComponents: "
3559                    + compToString(packageSettings.getEnabledComponents(userId)));
3560            Log.v(PackageManagerService.TAG, "disabledComponents: "
3561                    + compToString(packageSettings.getDisabledComponents(userId)));
3562        }
3563        if (packageSettings == null) {
3564            return false;
3565        }
3566        PackageUserState ustate = packageSettings.readUserState(userId);
3567        if ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0) {
3568            if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
3569                return true;
3570            }
3571        }
3572        if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED
3573                || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
3574                || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
3575                || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
3576                    && ustate.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
3577            return false;
3578        }
3579        if (ustate.enabledComponents != null
3580                && ustate.enabledComponents.contains(componentInfo.name)) {
3581            return true;
3582        }
3583        if (ustate.disabledComponents != null
3584                && ustate.disabledComponents.contains(componentInfo.name)) {
3585            return false;
3586        }
3587        return componentInfo.enabled;
3588    }
3589
3590    String getInstallerPackageNameLPr(String packageName) {
3591        final PackageSetting pkg = mPackages.get(packageName);
3592        if (pkg == null) {
3593            throw new IllegalArgumentException("Unknown package: " + packageName);
3594        }
3595        return pkg.installerPackageName;
3596    }
3597
3598    int getApplicationEnabledSettingLPr(String packageName, int userId) {
3599        final PackageSetting pkg = mPackages.get(packageName);
3600        if (pkg == null) {
3601            throw new IllegalArgumentException("Unknown package: " + packageName);
3602        }
3603        return pkg.getEnabled(userId);
3604    }
3605
3606    int getComponentEnabledSettingLPr(ComponentName componentName, int userId) {
3607        final String packageName = componentName.getPackageName();
3608        final PackageSetting pkg = mPackages.get(packageName);
3609        if (pkg == null) {
3610            throw new IllegalArgumentException("Unknown component: " + componentName);
3611        }
3612        final String classNameStr = componentName.getClassName();
3613        return pkg.getCurrentEnabledStateLPr(classNameStr, userId);
3614    }
3615
3616    boolean setPackageStoppedStateLPw(String packageName, boolean stopped,
3617            boolean allowedByPermission, int uid, int userId) {
3618        int appId = UserHandle.getAppId(uid);
3619        final PackageSetting pkgSetting = mPackages.get(packageName);
3620        if (pkgSetting == null) {
3621            throw new IllegalArgumentException("Unknown package: " + packageName);
3622        }
3623        if (!allowedByPermission && (appId != pkgSetting.appId)) {
3624            throw new SecurityException(
3625                    "Permission Denial: attempt to change stopped state from pid="
3626                    + Binder.getCallingPid()
3627                    + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
3628        }
3629        if (DEBUG_STOPPED) {
3630            if (stopped) {
3631                RuntimeException e = new RuntimeException("here");
3632                e.fillInStackTrace();
3633                Slog.i(TAG, "Stopping package " + packageName, e);
3634            }
3635        }
3636        if (pkgSetting.getStopped(userId) != stopped) {
3637            pkgSetting.setStopped(stopped, userId);
3638            // pkgSetting.pkg.mSetStopped = stopped;
3639            if (pkgSetting.getNotLaunched(userId)) {
3640                if (pkgSetting.installerPackageName != null) {
3641                    PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
3642                            pkgSetting.name, null,
3643                            pkgSetting.installerPackageName, null, new int[] {userId});
3644                }
3645                pkgSetting.setNotLaunched(false, userId);
3646            }
3647            return true;
3648        }
3649        return false;
3650    }
3651
3652    List<UserInfo> getAllUsers() {
3653        long id = Binder.clearCallingIdentity();
3654        try {
3655            return UserManagerService.getInstance().getUsers(false);
3656        } catch (NullPointerException npe) {
3657            // packagemanager not yet initialized
3658        } finally {
3659            Binder.restoreCallingIdentity(id);
3660        }
3661        return null;
3662    }
3663
3664    /**
3665     * Return all {@link PackageSetting} that are actively installed on the
3666     * given {@link VolumeInfo#fsUuid}.
3667     */
3668    List<PackageSetting> getVolumePackagesLPr(String volumeUuid) {
3669        Preconditions.checkNotNull(volumeUuid);
3670        ArrayList<PackageSetting> res = new ArrayList<>();
3671        for (int i = 0; i < mPackages.size(); i++) {
3672            final PackageSetting setting = mPackages.valueAt(i);
3673            if (Objects.equals(volumeUuid, setting.volumeUuid)) {
3674                res.add(setting);
3675            }
3676        }
3677        return res;
3678    }
3679
3680    static void printFlags(PrintWriter pw, int val, Object[] spec) {
3681        pw.print("[ ");
3682        for (int i=0; i<spec.length; i+=2) {
3683            int mask = (Integer)spec[i];
3684            if ((val & mask) != 0) {
3685                pw.print(spec[i+1]);
3686                pw.print(" ");
3687            }
3688        }
3689        pw.print("]");
3690    }
3691
3692    static final Object[] FLAG_DUMP_SPEC = new Object[] {
3693        ApplicationInfo.FLAG_SYSTEM, "SYSTEM",
3694        ApplicationInfo.FLAG_DEBUGGABLE, "DEBUGGABLE",
3695        ApplicationInfo.FLAG_HAS_CODE, "HAS_CODE",
3696        ApplicationInfo.FLAG_PERSISTENT, "PERSISTENT",
3697        ApplicationInfo.FLAG_FACTORY_TEST, "FACTORY_TEST",
3698        ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING, "ALLOW_TASK_REPARENTING",
3699        ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA, "ALLOW_CLEAR_USER_DATA",
3700        ApplicationInfo.FLAG_UPDATED_SYSTEM_APP, "UPDATED_SYSTEM_APP",
3701        ApplicationInfo.FLAG_TEST_ONLY, "TEST_ONLY",
3702        ApplicationInfo.FLAG_VM_SAFE_MODE, "VM_SAFE_MODE",
3703        ApplicationInfo.FLAG_ALLOW_BACKUP, "ALLOW_BACKUP",
3704        ApplicationInfo.FLAG_KILL_AFTER_RESTORE, "KILL_AFTER_RESTORE",
3705        ApplicationInfo.FLAG_RESTORE_ANY_VERSION, "RESTORE_ANY_VERSION",
3706        ApplicationInfo.FLAG_EXTERNAL_STORAGE, "EXTERNAL_STORAGE",
3707        ApplicationInfo.FLAG_LARGE_HEAP, "LARGE_HEAP",
3708    };
3709
3710    static final Object[] PRIVATE_FLAG_DUMP_SPEC = new Object[] {
3711        ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
3712        ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
3713        ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
3714    };
3715
3716    void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, PackageSetting ps,
3717            SimpleDateFormat sdf, Date date, List<UserInfo> users) {
3718        if (checkinTag != null) {
3719            pw.print(checkinTag);
3720            pw.print(",");
3721            pw.print(ps.realName != null ? ps.realName : ps.name);
3722            pw.print(",");
3723            pw.print(ps.appId);
3724            pw.print(",");
3725            pw.print(ps.versionCode);
3726            pw.print(",");
3727            pw.print(ps.firstInstallTime);
3728            pw.print(",");
3729            pw.print(ps.lastUpdateTime);
3730            pw.print(",");
3731            pw.print(ps.installerPackageName != null ? ps.installerPackageName : "?");
3732            pw.println();
3733            if (ps.pkg != null) {
3734                pw.print(checkinTag); pw.print("-"); pw.print("splt,");
3735                pw.print("base,");
3736                pw.println(ps.pkg.baseRevisionCode);
3737                if (ps.pkg.splitNames != null) {
3738                    for (int i = 0; i < ps.pkg.splitNames.length; i++) {
3739                        pw.print(checkinTag); pw.print("-"); pw.print("splt,");
3740                        pw.print(ps.pkg.splitNames[i]); pw.print(",");
3741                        pw.println(ps.pkg.splitRevisionCodes[i]);
3742                    }
3743                }
3744            }
3745            for (UserInfo user : users) {
3746                pw.print(checkinTag);
3747                pw.print("-");
3748                pw.print("usr");
3749                pw.print(",");
3750                pw.print(user.id);
3751                pw.print(",");
3752                pw.print(ps.getInstalled(user.id) ? "I" : "i");
3753                pw.print(ps.getHidden(user.id) ? "B" : "b");
3754                pw.print(ps.getStopped(user.id) ? "S" : "s");
3755                pw.print(ps.getNotLaunched(user.id) ? "l" : "L");
3756                pw.print(",");
3757                pw.print(ps.getEnabled(user.id));
3758                String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
3759                pw.print(",");
3760                pw.print(lastDisabledAppCaller != null ? lastDisabledAppCaller : "?");
3761                pw.println();
3762            }
3763            return;
3764        }
3765
3766        pw.print(prefix); pw.print("Package [");
3767            pw.print(ps.realName != null ? ps.realName : ps.name);
3768            pw.print("] (");
3769            pw.print(Integer.toHexString(System.identityHashCode(ps)));
3770            pw.println("):");
3771
3772        if (ps.realName != null) {
3773            pw.print(prefix); pw.print("  compat name=");
3774            pw.println(ps.name);
3775        }
3776
3777        pw.print(prefix); pw.print("  userId="); pw.println(ps.appId);
3778
3779        if (ps.sharedUser != null) {
3780            pw.print(prefix); pw.print("  sharedUser="); pw.println(ps.sharedUser);
3781        }
3782        pw.print(prefix); pw.print("  pkg="); pw.println(ps.pkg);
3783        pw.print(prefix); pw.print("  codePath="); pw.println(ps.codePathString);
3784        pw.print(prefix); pw.print("  resourcePath="); pw.println(ps.resourcePathString);
3785        pw.print(prefix); pw.print("  legacyNativeLibraryDir="); pw.println(ps.legacyNativeLibraryPathString);
3786        pw.print(prefix); pw.print("  primaryCpuAbi="); pw.println(ps.primaryCpuAbiString);
3787        pw.print(prefix); pw.print("  secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString);
3788        pw.print(prefix); pw.print("  versionCode="); pw.print(ps.versionCode);
3789        if (ps.pkg != null) {
3790            pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion);
3791        }
3792        pw.println();
3793        if (ps.pkg != null) {
3794            pw.print(prefix); pw.print("  versionName="); pw.println(ps.pkg.mVersionName);
3795            pw.print(prefix); pw.print("  splits="); dumpSplitNames(pw, ps.pkg); pw.println();
3796            pw.print(prefix); pw.print("  applicationInfo=");
3797                pw.println(ps.pkg.applicationInfo.toString());
3798            pw.print(prefix); pw.print("  flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
3799                    FLAG_DUMP_SPEC); pw.println();
3800            pw.print(prefix); pw.print("  priavateFlags="); printFlags(pw,
3801                    ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println();
3802            pw.print(prefix); pw.print("  dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
3803            if (ps.pkg.mOperationPending) {
3804                pw.print(prefix); pw.println("  mOperationPending=true");
3805            }
3806            pw.print(prefix); pw.print("  supportsScreens=[");
3807            boolean first = true;
3808            if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
3809                if (!first)
3810                    pw.print(", ");
3811                first = false;
3812                pw.print("small");
3813            }
3814            if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
3815                if (!first)
3816                    pw.print(", ");
3817                first = false;
3818                pw.print("medium");
3819            }
3820            if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
3821                if (!first)
3822                    pw.print(", ");
3823                first = false;
3824                pw.print("large");
3825            }
3826            if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
3827                if (!first)
3828                    pw.print(", ");
3829                first = false;
3830                pw.print("xlarge");
3831            }
3832            if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
3833                if (!first)
3834                    pw.print(", ");
3835                first = false;
3836                pw.print("resizeable");
3837            }
3838            if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
3839                if (!first)
3840                    pw.print(", ");
3841                first = false;
3842                pw.print("anyDensity");
3843            }
3844            pw.println("]");
3845            if (ps.pkg.libraryNames != null && ps.pkg.libraryNames.size() > 0) {
3846                pw.print(prefix); pw.println("  libraries:");
3847                for (int i=0; i<ps.pkg.libraryNames.size(); i++) {
3848                    pw.print(prefix); pw.print("    "); pw.println(ps.pkg.libraryNames.get(i));
3849                }
3850            }
3851            if (ps.pkg.usesLibraries != null && ps.pkg.usesLibraries.size() > 0) {
3852                pw.print(prefix); pw.println("  usesLibraries:");
3853                for (int i=0; i<ps.pkg.usesLibraries.size(); i++) {
3854                    pw.print(prefix); pw.print("    "); pw.println(ps.pkg.usesLibraries.get(i));
3855                }
3856            }
3857            if (ps.pkg.usesOptionalLibraries != null
3858                    && ps.pkg.usesOptionalLibraries.size() > 0) {
3859                pw.print(prefix); pw.println("  usesOptionalLibraries:");
3860                for (int i=0; i<ps.pkg.usesOptionalLibraries.size(); i++) {
3861                    pw.print(prefix); pw.print("    ");
3862                        pw.println(ps.pkg.usesOptionalLibraries.get(i));
3863                }
3864            }
3865            if (ps.pkg.usesLibraryFiles != null
3866                    && ps.pkg.usesLibraryFiles.length > 0) {
3867                pw.print(prefix); pw.println("  usesLibraryFiles:");
3868                for (int i=0; i<ps.pkg.usesLibraryFiles.length; i++) {
3869                    pw.print(prefix); pw.print("    "); pw.println(ps.pkg.usesLibraryFiles[i]);
3870                }
3871            }
3872        }
3873        pw.print(prefix); pw.print("  timeStamp=");
3874            date.setTime(ps.timeStamp);
3875            pw.println(sdf.format(date));
3876        pw.print(prefix); pw.print("  firstInstallTime=");
3877            date.setTime(ps.firstInstallTime);
3878            pw.println(sdf.format(date));
3879        pw.print(prefix); pw.print("  lastUpdateTime=");
3880            date.setTime(ps.lastUpdateTime);
3881            pw.println(sdf.format(date));
3882        if (ps.installerPackageName != null) {
3883            pw.print(prefix); pw.print("  installerPackageName=");
3884                    pw.println(ps.installerPackageName);
3885        }
3886        if (ps.volumeUuid != null) {
3887            pw.print(prefix); pw.print("  volumeUuid=");
3888                    pw.println(ps.volumeUuid);
3889        }
3890        pw.print(prefix); pw.print("  signatures="); pw.println(ps.signatures);
3891        pw.print(prefix); pw.print("  installPermissionsFixed=");
3892                pw.print(ps.installPermissionsFixed);
3893                pw.print(" installStatus="); pw.println(ps.installStatus);
3894        pw.print(prefix); pw.print("  pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
3895                pw.println();
3896
3897        if (ps.sharedUser == null) {
3898            PermissionsState permissionsState = ps.getPermissionsState();
3899            dumpInstallPermissionsLPr(pw, prefix + "  ", permissionsState);
3900        }
3901
3902        for (UserInfo user : users) {
3903            pw.print(prefix); pw.print("  User "); pw.print(user.id); pw.print(": ");
3904            pw.print(" installed=");
3905            pw.print(ps.getInstalled(user.id));
3906            pw.print(" hidden=");
3907            pw.print(ps.getHidden(user.id));
3908            pw.print(" stopped=");
3909            pw.print(ps.getStopped(user.id));
3910            pw.print(" notLaunched=");
3911            pw.print(ps.getNotLaunched(user.id));
3912            pw.print(" enabled=");
3913            pw.println(ps.getEnabled(user.id));
3914            String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
3915            if (lastDisabledAppCaller != null) {
3916                pw.print(prefix); pw.print("    lastDisabledCaller: ");
3917                        pw.println(lastDisabledAppCaller);
3918            }
3919
3920            if (ps.sharedUser == null) {
3921                PermissionsState permissionsState = ps.getPermissionsState();
3922                dumpGidsLPr(pw, prefix + "    ", permissionsState.computeGids(user.id));
3923                dumpRuntimePermissionsLPr(pw, prefix + "    ", permissionsState
3924                        .getRuntimePermissions(user.id));
3925            }
3926
3927            ArraySet<String> cmp = ps.getDisabledComponents(user.id);
3928            if (cmp != null && cmp.size() > 0) {
3929                pw.print(prefix); pw.println("    disabledComponents:");
3930                for (String s : cmp) {
3931                    pw.print(prefix); pw.print("    "); pw.println(s);
3932                }
3933            }
3934            cmp = ps.getEnabledComponents(user.id);
3935            if (cmp != null && cmp.size() > 0) {
3936                pw.print(prefix); pw.println("    enabledComponents:");
3937                for (String s : cmp) {
3938                    pw.print(prefix); pw.print("    "); pw.println(s);
3939                }
3940            }
3941        }
3942    }
3943
3944    void dumpPackagesLPr(PrintWriter pw, String packageName, DumpState dumpState, boolean checkin) {
3945        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
3946        final Date date = new Date();
3947        boolean printedSomething = false;
3948        List<UserInfo> users = getAllUsers();
3949        for (final PackageSetting ps : mPackages.values()) {
3950            if (packageName != null && !packageName.equals(ps.realName)
3951                    && !packageName.equals(ps.name)) {
3952                continue;
3953            }
3954
3955            if (!checkin && packageName != null) {
3956                dumpState.setSharedUser(ps.sharedUser);
3957            }
3958
3959            if (!checkin && !printedSomething) {
3960                if (dumpState.onTitlePrinted())
3961                    pw.println();
3962                pw.println("Packages:");
3963                printedSomething = true;
3964            }
3965            dumpPackageLPr(pw, "  ", checkin ? "pkg" : null, ps, sdf, date, users);
3966        }
3967
3968        printedSomething = false;
3969        if (!checkin && mRenamedPackages.size() > 0) {
3970            for (final Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
3971                if (packageName != null && !packageName.equals(e.getKey())
3972                        && !packageName.equals(e.getValue())) {
3973                    continue;
3974                }
3975                if (!checkin) {
3976                    if (!printedSomething) {
3977                        if (dumpState.onTitlePrinted())
3978                            pw.println();
3979                        pw.println("Renamed packages:");
3980                        printedSomething = true;
3981                    }
3982                    pw.print("  ");
3983                } else {
3984                    pw.print("ren,");
3985                }
3986                pw.print(e.getKey());
3987                pw.print(checkin ? " -> " : ",");
3988                pw.println(e.getValue());
3989            }
3990        }
3991
3992        printedSomething = false;
3993        if (mDisabledSysPackages.size() > 0) {
3994            for (final PackageSetting ps : mDisabledSysPackages.values()) {
3995                if (packageName != null && !packageName.equals(ps.realName)
3996                        && !packageName.equals(ps.name)) {
3997                    continue;
3998                }
3999                if (!checkin && !printedSomething) {
4000                    if (dumpState.onTitlePrinted())
4001                        pw.println();
4002                    pw.println("Hidden system packages:");
4003                    printedSomething = true;
4004                }
4005                dumpPackageLPr(pw, "  ", checkin ? "dis" : null, ps, sdf, date, users);
4006            }
4007        }
4008    }
4009
4010    void dumpPermissionsLPr(PrintWriter pw, String packageName, DumpState dumpState) {
4011        boolean printedSomething = false;
4012        for (BasePermission p : mPermissions.values()) {
4013            if (packageName != null && !packageName.equals(p.sourcePackage)) {
4014                continue;
4015            }
4016            if (!printedSomething) {
4017                if (dumpState.onTitlePrinted())
4018                    pw.println();
4019                pw.println("Permissions:");
4020                printedSomething = true;
4021            }
4022            pw.print("  Permission ["); pw.print(p.name); pw.print("] (");
4023                    pw.print(Integer.toHexString(System.identityHashCode(p)));
4024                    pw.println("):");
4025            pw.print("    sourcePackage="); pw.println(p.sourcePackage);
4026            pw.print("    uid="); pw.print(p.uid);
4027                    pw.print(" gids="); pw.print(Arrays.toString(
4028                            p.computeGids(UserHandle.USER_OWNER)));
4029                    pw.print(" type="); pw.print(p.type);
4030                    pw.print(" prot=");
4031                    pw.println(PermissionInfo.protectionToString(p.protectionLevel));
4032            if (p.packageSetting != null) {
4033                pw.print("    packageSetting="); pw.println(p.packageSetting);
4034            }
4035            if (p.perm != null) {
4036                pw.print("    perm="); pw.println(p.perm);
4037            }
4038            if (READ_EXTERNAL_STORAGE.equals(p.name)) {
4039                pw.print("    enforced=");
4040                pw.println(mReadExternalStorageEnforced);
4041            }
4042        }
4043    }
4044
4045    void dumpSharedUsersLPr(PrintWriter pw, String packageName, DumpState dumpState,
4046            boolean checkin) {
4047        boolean printedSomething = false;
4048        for (SharedUserSetting su : mSharedUsers.values()) {
4049            if (packageName != null && su != dumpState.getSharedUser()) {
4050                continue;
4051            }
4052            if (!checkin) {
4053                if (!printedSomething) {
4054                    if (dumpState.onTitlePrinted())
4055                        pw.println();
4056                    pw.println("Shared users:");
4057                    printedSomething = true;
4058                }
4059                pw.print("  SharedUser [");
4060                pw.print(su.name);
4061                pw.print("] (");
4062                pw.print(Integer.toHexString(System.identityHashCode(su)));
4063                        pw.println("):");
4064
4065                String prefix = "    ";
4066                pw.print(prefix); pw.print("userId="); pw.println(su.userId);
4067
4068                PermissionsState permissionsState = su.getPermissionsState();
4069                dumpInstallPermissionsLPr(pw, prefix, permissionsState);
4070
4071                for (int userId : UserManagerService.getInstance().getUserIds()) {
4072                    final int[] gids = permissionsState.computeGids(userId);
4073                    Set<String> permissions = permissionsState.getRuntimePermissions(userId);
4074                    if (!ArrayUtils.isEmpty(gids) || !permissions.isEmpty()) {
4075                        pw.print(prefix); pw.print("User "); pw.print(userId); pw.println(": ");
4076                        dumpGidsLPr(pw, prefix + "  ", gids);
4077                        dumpRuntimePermissionsLPr(pw, prefix + "  ", permissions);
4078                    }
4079                }
4080            } else {
4081                pw.print("suid,"); pw.print(su.userId); pw.print(","); pw.println(su.name);
4082            }
4083        }
4084    }
4085
4086    void dumpReadMessagesLPr(PrintWriter pw, DumpState dumpState) {
4087        pw.println("Settings parse messages:");
4088        pw.print(mReadMessages.toString());
4089    }
4090
4091    private static void dumpSplitNames(PrintWriter pw, PackageParser.Package pkg) {
4092        if (pkg == null) {
4093            pw.print("unknown");
4094        } else {
4095            // [base:10, config.mdpi, config.xhdpi:12]
4096            pw.print("[");
4097            pw.print("base");
4098            if (pkg.baseRevisionCode != 0) {
4099                pw.print(":"); pw.print(pkg.baseRevisionCode);
4100            }
4101            if (pkg.splitNames != null) {
4102                for (int i = 0; i < pkg.splitNames.length; i++) {
4103                    pw.print(", ");
4104                    pw.print(pkg.splitNames[i]);
4105                    if (pkg.splitRevisionCodes[i] != 0) {
4106                        pw.print(":"); pw.print(pkg.splitRevisionCodes[i]);
4107                    }
4108                }
4109            }
4110            pw.print("]");
4111        }
4112    }
4113
4114    void dumpGidsLPr(PrintWriter pw, String prefix, int[] gids) {
4115        if (!ArrayUtils.isEmpty(gids)) {
4116            pw.print(prefix);
4117            pw.print("gids="); pw.println(
4118                    PackageManagerService.arrayToString(gids));
4119        }
4120    }
4121
4122    void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix, Set<String> permissions) {
4123        if (!permissions.isEmpty()) {
4124            pw.print(prefix); pw.println("runtime permissions:");
4125            for (String permission : permissions) {
4126                pw.print(prefix); pw.print("  "); pw.println(permission);
4127            }
4128        }
4129    }
4130
4131    void dumpInstallPermissionsLPr(PrintWriter pw, String prefix,
4132            PermissionsState permissionsState) {
4133        Set<String> permissions = permissionsState.getInstallPermissions();
4134        if (!permissions.isEmpty()) {
4135            pw.print(prefix); pw.println("install permissions:");
4136            for (String permission : permissions) {
4137                pw.print(prefix); pw.print("  "); pw.println(permission);
4138            }
4139        }
4140    }
4141
4142    public void writeRuntimePermissionsForUserLPr(int userId, boolean sync) {
4143        if (sync) {
4144            mRuntimePermissionsPersistence.writePermissionsForUserSyncLPr(userId);
4145        } else {
4146            mRuntimePermissionsPersistence.writePermissionsForUserAsyncLPr(userId);
4147        }
4148    }
4149
4150    private final class RuntimePermissionPersistence {
4151        private static final long WRITE_PERMISSIONS_DELAY_MILLIS = 200;
4152
4153        private static final long MAX_WRITE_PERMISSIONS_DELAY_MILLIS = 2000;
4154
4155        private final Handler mHandler = new MyHandler();
4156
4157        private final Object mLock;
4158
4159        @GuardedBy("mLock")
4160        private SparseBooleanArray mWriteScheduled = new SparseBooleanArray();
4161
4162        @GuardedBy("mLock")
4163        private SparseLongArray mLastNotWrittenMutationTimesMillis = new SparseLongArray();
4164
4165        public RuntimePermissionPersistence(Object lock) {
4166            mLock = lock;
4167        }
4168
4169        public void writePermissionsForUserSyncLPr(int userId) {
4170            if (!PackageManagerService.RUNTIME_PERMISSIONS_ENABLED) {
4171                return;
4172            }
4173
4174            mHandler.removeMessages(userId);
4175            writePermissionsSync(userId);
4176        }
4177
4178        public void writePermissionsForUserAsyncLPr(int userId) {
4179            if (!PackageManagerService.RUNTIME_PERMISSIONS_ENABLED) {
4180                return;
4181            }
4182
4183            final long currentTimeMillis = SystemClock.uptimeMillis();
4184
4185            if (mWriteScheduled.get(userId)) {
4186                mHandler.removeMessages(userId);
4187
4188                // If enough time passed, write without holding off anymore.
4189                final long lastNotWrittenMutationTimeMillis = mLastNotWrittenMutationTimesMillis
4190                        .get(userId);
4191                final long timeSinceLastNotWrittenMutationMillis = currentTimeMillis
4192                        - lastNotWrittenMutationTimeMillis;
4193                if (timeSinceLastNotWrittenMutationMillis >= MAX_WRITE_PERMISSIONS_DELAY_MILLIS) {
4194                    mHandler.obtainMessage(userId).sendToTarget();
4195                    return;
4196                }
4197
4198                // Hold off a bit more as settings are frequently changing.
4199                final long maxDelayMillis = Math.max(lastNotWrittenMutationTimeMillis
4200                        + MAX_WRITE_PERMISSIONS_DELAY_MILLIS - currentTimeMillis, 0);
4201                final long writeDelayMillis = Math.min(WRITE_PERMISSIONS_DELAY_MILLIS,
4202                        maxDelayMillis);
4203
4204                Message message = mHandler.obtainMessage(userId);
4205                mHandler.sendMessageDelayed(message, writeDelayMillis);
4206            } else {
4207                mLastNotWrittenMutationTimesMillis.put(userId, currentTimeMillis);
4208                Message message = mHandler.obtainMessage(userId);
4209                mHandler.sendMessageDelayed(message, WRITE_PERMISSIONS_DELAY_MILLIS);
4210                mWriteScheduled.put(userId, true);
4211            }
4212        }
4213
4214        private void writePermissionsSync(int userId) {
4215            AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId));
4216
4217            ArrayMap<String, Set<String>> permissionsForPackage = new ArrayMap<>();
4218            ArrayMap<String, Set<String>> permissionsForSharedUser = new ArrayMap<>();
4219
4220            synchronized (mLock) {
4221                mWriteScheduled.delete(userId);
4222
4223                final int packageCount = mPackages.size();
4224                for (int i = 0; i < packageCount; i++) {
4225                    String packageName = mPackages.keyAt(i);
4226                    PackageSetting packageSetting = mPackages.valueAt(i);
4227                    if (packageSetting.sharedUser == null) {
4228                        PermissionsState permissionsState = packageSetting.getPermissionsState();
4229                        Set<String> permissions = permissionsState.getRuntimePermissions(userId);
4230                        if (!permissions.isEmpty()) {
4231                            permissionsForPackage.put(packageName, permissions);
4232                        }
4233                    }
4234                }
4235
4236                final int sharedUserCount = mSharedUsers.size();
4237                for (int i = 0; i < sharedUserCount; i++) {
4238                    String sharedUserName = mSharedUsers.keyAt(i);
4239                    SharedUserSetting sharedUser = mSharedUsers.valueAt(i);
4240                    PermissionsState permissionsState = sharedUser.getPermissionsState();
4241                    Set<String> permissions = permissionsState.getRuntimePermissions(userId);
4242                    if (!permissions.isEmpty()) {
4243                        permissionsForSharedUser.put(sharedUserName, permissions);
4244                    }
4245                }
4246            }
4247
4248            FileOutputStream out = null;
4249            try {
4250                out = destination.startWrite();
4251
4252                XmlSerializer serializer = Xml.newSerializer();
4253                serializer.setOutput(out, "utf-8");
4254                serializer.setFeature(
4255                        "http://xmlpull.org/v1/doc/features.html#indent-output", true);
4256                serializer.startDocument(null, true);
4257                serializer.startTag(null, TAG_RUNTIME_PERMISSIONS);
4258
4259                final int packageCount = permissionsForPackage.size();
4260                for (int i = 0; i < packageCount; i++) {
4261                    String packageName = permissionsForPackage.keyAt(i);
4262                    Set<String> permissions = permissionsForPackage.valueAt(i);
4263                    serializer.startTag(null, TAG_PACKAGE);
4264                    serializer.attribute(null, ATTR_NAME, packageName);
4265                    writePermissions(serializer, permissions);
4266                    serializer.endTag(null, TAG_PACKAGE);
4267                }
4268
4269                final int sharedUserCount = permissionsForSharedUser.size();
4270                for (int i = 0; i < sharedUserCount; i++) {
4271                    String packageName = permissionsForSharedUser.keyAt(i);
4272                    Set<String> permissions = permissionsForSharedUser.valueAt(i);
4273                    serializer.startTag(null, TAG_SHARED_USER);
4274                    serializer.attribute(null, ATTR_NAME, packageName);
4275                    writePermissions(serializer, permissions);
4276                    serializer.endTag(null, TAG_SHARED_USER);
4277                }
4278
4279                serializer.endTag(null, TAG_RUNTIME_PERMISSIONS);
4280                serializer.endDocument();
4281                destination.finishWrite(out);
4282
4283                // Any error while writing is fatal.
4284            } catch (Throwable t) {
4285                Slog.wtf(PackageManagerService.TAG,
4286                        "Failed to write settings, restoring backup", t);
4287                destination.failWrite(out);
4288                throw new IllegalStateException("Failed to write runtime permissions,"
4289                        + " restoring backup", t);
4290            } finally {
4291                IoUtils.closeQuietly(out);
4292            }
4293        }
4294
4295        private void onUserRemoved(int userId) {
4296            // Make sure we do not
4297            mHandler.removeMessages(userId);
4298
4299            for (SettingBase sb : mPackages.values()) {
4300                revokeRuntimePermissions(sb, userId);
4301            }
4302
4303            for (SettingBase sb : mSharedUsers.values()) {
4304                revokeRuntimePermissions(sb, userId);
4305            }
4306        }
4307
4308        private void revokeRuntimePermissions(SettingBase sb, int userId) {
4309            PermissionsState permissionsState = sb.getPermissionsState();
4310            for (String permission : permissionsState.getRuntimePermissions(userId)) {
4311                BasePermission bp = mPermissions.get(permission);
4312                if (bp != null) {
4313                    permissionsState.revokeRuntimePermission(bp, userId);
4314                }
4315            }
4316        }
4317
4318        public void readStateForUserSyncLPr(int userId) {
4319            File permissionsFile = getUserRuntimePermissionsFile(userId);
4320            if (!permissionsFile.exists()) {
4321                return;
4322            }
4323
4324            FileInputStream in;
4325            try {
4326                in = new FileInputStream(permissionsFile);
4327            } catch (FileNotFoundException fnfe) {
4328                Slog.i(PackageManagerService.TAG, "No permissions state");
4329                return;
4330            }
4331
4332            try {
4333                XmlPullParser parser = Xml.newPullParser();
4334                parser.setInput(in, null);
4335                parseRuntimePermissionsLPr(parser, userId);
4336
4337            } catch (XmlPullParserException | IOException e) {
4338                throw new IllegalStateException("Failed parsing permissions file: "
4339                        + permissionsFile , e);
4340            } finally {
4341                IoUtils.closeQuietly(in);
4342            }
4343        }
4344
4345        private void parseRuntimePermissionsLPr(XmlPullParser parser, int userId)
4346                throws IOException, XmlPullParserException {
4347            final int outerDepth = parser.getDepth();
4348            int type;
4349            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4350                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
4351                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4352                    continue;
4353                }
4354
4355                switch (parser.getName()) {
4356                    case TAG_PACKAGE: {
4357                        String name = parser.getAttributeValue(null, ATTR_NAME);
4358                        PackageSetting ps = mPackages.get(name);
4359                        if (ps == null) {
4360                            Slog.w(PackageManagerService.TAG, "Unknown package:" + name);
4361                            XmlUtils.skipCurrentTag(parser);
4362                            continue;
4363                        }
4364                        parsePermissionsLPr(parser, ps.getPermissionsState(), userId);
4365                    } break;
4366
4367                    case TAG_SHARED_USER: {
4368                        String name = parser.getAttributeValue(null, ATTR_NAME);
4369                        SharedUserSetting sus = mSharedUsers.get(name);
4370                        if (sus == null) {
4371                            Slog.w(PackageManagerService.TAG, "Unknown shared user:" + name);
4372                            XmlUtils.skipCurrentTag(parser);
4373                            continue;
4374                        }
4375                        parsePermissionsLPr(parser, sus.getPermissionsState(), userId);
4376                    } break;
4377                }
4378            }
4379        }
4380
4381        private void parsePermissionsLPr(XmlPullParser parser, PermissionsState permissionsState,
4382                int userId) throws IOException, XmlPullParserException {
4383            final int outerDepth = parser.getDepth();
4384            int type;
4385            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4386                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
4387                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4388                    continue;
4389                }
4390
4391                switch (parser.getName()) {
4392                    case TAG_ITEM: {
4393                        String name = parser.getAttributeValue(null, ATTR_NAME);
4394                        BasePermission bp = mPermissions.get(name);
4395                        if (bp == null) {
4396                            Slog.w(PackageManagerService.TAG, "Unknown permission:" + name);
4397                            XmlUtils.skipCurrentTag(parser);
4398                            continue;
4399                        }
4400
4401                        if (permissionsState.grantRuntimePermission(bp, userId) ==
4402                                PermissionsState.PERMISSION_OPERATION_FAILURE) {
4403                            Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
4404                        }
4405                    } break;
4406                }
4407            }
4408        }
4409
4410        private void writePermissions(XmlSerializer serializer, Set<String> permissions)
4411                throws IOException {
4412            for (String permission : permissions) {
4413                serializer.startTag(null, TAG_ITEM);
4414                serializer.attribute(null, ATTR_NAME, permission);
4415                serializer.endTag(null, TAG_ITEM);
4416            }
4417        }
4418
4419        private final class MyHandler extends Handler {
4420            public MyHandler() {
4421                super(BackgroundThread.getHandler().getLooper());
4422            }
4423
4424            @Override
4425            public void handleMessage(Message message) {
4426                final int userId = message.what;
4427                Runnable callback = (Runnable) message.obj;
4428                writePermissionsSync(userId);
4429                if (callback != null) {
4430                    callback.run();
4431                }
4432            }
4433        }
4434    }
4435}
4436