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