Settings.java revision 258848d2ae04f447ff1c18023fa76b139fcc0862
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_USER;
22import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
23import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
24
25import com.android.internal.util.FastXmlSerializer;
26import com.android.internal.util.JournaledFile;
27import com.android.internal.util.XmlUtils;
28import com.android.server.IntentResolver;
29import com.android.server.pm.PackageManagerService.DumpState;
30
31import org.xmlpull.v1.XmlPullParser;
32import org.xmlpull.v1.XmlPullParserException;
33import org.xmlpull.v1.XmlSerializer;
34
35import android.app.AppGlobals;
36import android.content.ComponentName;
37import android.content.Context;
38import android.content.Intent;
39import android.content.pm.ApplicationInfo;
40import android.content.pm.ComponentInfo;
41import android.content.pm.PackageManager;
42import android.content.pm.PackageParser;
43import android.content.pm.PermissionInfo;
44import android.content.pm.Signature;
45import android.content.pm.UserInfo;
46import android.content.pm.VerifierDeviceIdentity;
47import android.os.Binder;
48import android.os.Environment;
49import android.os.FileUtils;
50import android.os.Process;
51import android.os.RemoteException;
52import android.os.UserId;
53import android.util.Log;
54import android.util.Slog;
55import android.util.SparseArray;
56import android.util.Xml;
57
58import java.io.BufferedOutputStream;
59import java.io.File;
60import java.io.FileInputStream;
61import java.io.FileOutputStream;
62import java.io.IOException;
63import java.io.PrintWriter;
64import java.text.SimpleDateFormat;
65import java.util.ArrayList;
66import java.util.Arrays;
67import java.util.Date;
68import java.util.HashMap;
69import java.util.HashSet;
70import java.util.Iterator;
71import java.util.List;
72import java.util.Map;
73
74import libcore.io.IoUtils;
75
76/**
77 * Holds information about dynamic settings.
78 */
79final class Settings {
80    private static final String TAG = "PackageSettings";
81
82    private static final boolean DEBUG_STOPPED = false;
83    private static final boolean DEBUG_MU = false;
84
85    private static final String TAG_READ_EXTERNAL_STORAGE = "read-external-storage";
86    private static final String ATTR_ENFORCEMENT = "enforcement";
87
88    private static final String TAG_ITEM = "item";
89    private static final String TAG_DISABLED_COMPONENTS = "disabled-components";
90    private static final String TAG_ENABLED_COMPONENTS = "enabled-components";
91    private static final String TAG_PACKAGE_RESTRICTIONS = "package-restrictions";
92    private static final String TAG_PACKAGE = "pkg";
93
94    private static final String ATTR_NAME = "name";
95    private static final String ATTR_NOT_LAUNCHED = "nl";
96    private static final String ATTR_ENABLED = "enabled";
97    private static final String ATTR_STOPPED = "stopped";
98
99    private final File mSettingsFilename;
100    private final File mBackupSettingsFilename;
101    private final File mPackageListFilename;
102    private final File mStoppedPackagesFilename;
103    private final File mBackupStoppedPackagesFilename;
104    final HashMap<String, PackageSetting> mPackages =
105            new HashMap<String, PackageSetting>();
106    // List of replaced system applications
107    private final HashMap<String, PackageSetting> mDisabledSysPackages =
108        new HashMap<String, PackageSetting>();
109
110    // These are the last platform API version we were using for
111    // the apps installed on internal and external storage.  It is
112    // used to grant newer permissions one time during a system upgrade.
113    int mInternalSdkPlatform;
114    int mExternalSdkPlatform;
115
116    Boolean mReadExternalStorageEnforced;
117
118    /** Device identity for the purpose of package verification. */
119    private VerifierDeviceIdentity mVerifierDeviceIdentity;
120
121    // The user's preferred activities associated with particular intent
122    // filters.
123    final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
124                new IntentResolver<PreferredActivity, PreferredActivity>() {
125        @Override
126        protected PreferredActivity[] newArray(int size) {
127            return new PreferredActivity[size];
128        }
129        @Override
130        protected String packageForFilter(PreferredActivity filter) {
131            return filter.mPref.mComponent.getPackageName();
132        }
133        @Override
134        protected void dumpFilter(PrintWriter out, String prefix,
135                PreferredActivity filter) {
136            filter.mPref.dump(out, prefix, filter);
137        }
138    };
139    final HashMap<String, SharedUserSetting> mSharedUsers =
140            new HashMap<String, SharedUserSetting>();
141    private final ArrayList<Object> mUserIds = new ArrayList<Object>();
142    private final SparseArray<Object> mOtherUserIds =
143            new SparseArray<Object>();
144
145    // For reading/writing settings file.
146    private final ArrayList<Signature> mPastSignatures =
147            new ArrayList<Signature>();
148
149    // Mapping from permission names to info about them.
150    final HashMap<String, BasePermission> mPermissions =
151            new HashMap<String, BasePermission>();
152
153    // Mapping from permission tree names to info about them.
154    final HashMap<String, BasePermission> mPermissionTrees =
155            new HashMap<String, BasePermission>();
156
157    // Packages that have been uninstalled and still need their external
158    // storage data deleted.
159    final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
160
161    // Packages that have been renamed since they were first installed.
162    // Keys are the new names of the packages, values are the original
163    // names.  The packages appear everwhere else under their original
164    // names.
165    final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
166
167    final StringBuilder mReadMessages = new StringBuilder();
168
169    /**
170     * Used to track packages that have a shared user ID that hasn't been read
171     * in yet.
172     * <p>
173     * TODO: make this just a local variable that is passed in during package
174     * scanning to make it less confusing.
175     */
176    private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
177
178    private final Context mContext;
179
180    private final File mSystemDir;
181    Settings(Context context) {
182        this(context, Environment.getDataDirectory());
183    }
184
185    Settings(Context context, File dataDir) {
186        mContext = context;
187        mSystemDir = new File(dataDir, "system");
188        mSystemDir.mkdirs();
189        FileUtils.setPermissions(mSystemDir.toString(),
190                FileUtils.S_IRWXU|FileUtils.S_IRWXG
191                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
192                -1, -1);
193        mSettingsFilename = new File(mSystemDir, "packages.xml");
194        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
195        mPackageListFilename = new File(mSystemDir, "packages.list");
196        // Deprecated: Needed for migration
197        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
198        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
199    }
200
201    PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
202            String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
203            String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) {
204        final String name = pkg.packageName;
205        PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
206                resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add);
207        return p;
208    }
209
210    PackageSetting peekPackageLPr(String name) {
211        return mPackages.get(name);
212    }
213
214    void setInstallStatus(String pkgName, int status) {
215        PackageSetting p = mPackages.get(pkgName);
216        if(p != null) {
217            if(p.getInstallStatus() != status) {
218                p.setInstallStatus(status);
219            }
220        }
221    }
222
223    void setInstallerPackageName(String pkgName,
224            String installerPkgName) {
225        PackageSetting p = mPackages.get(pkgName);
226        if(p != null) {
227            p.setInstallerPackageName(installerPkgName);
228        }
229    }
230
231    SharedUserSetting getSharedUserLPw(String name,
232            int pkgFlags, boolean create) {
233        SharedUserSetting s = mSharedUsers.get(name);
234        if (s == null) {
235            if (!create) {
236                return null;
237            }
238            s = new SharedUserSetting(name, pkgFlags);
239            s.userId = newUserIdLPw(s);
240            Log.i(PackageManagerService.TAG, "New shared user " + name + ": id=" + s.userId);
241            // < 0 means we couldn't assign a userid; fall out and return
242            // s, which is currently null
243            if (s.userId >= 0) {
244                mSharedUsers.put(name, s);
245            }
246        }
247
248        return s;
249    }
250
251    boolean disableSystemPackageLPw(String name) {
252        final PackageSetting p = mPackages.get(name);
253        if(p == null) {
254            Log.w(PackageManagerService.TAG, "Package:"+name+" is not an installed package");
255            return false;
256        }
257        final PackageSetting dp = mDisabledSysPackages.get(name);
258        // always make sure the system package code and resource paths dont change
259        if (dp == null) {
260            if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
261                p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
262            }
263            mDisabledSysPackages.put(name, p);
264
265            // a little trick...  when we install the new package, we don't
266            // want to modify the existing PackageSetting for the built-in
267            // version.  so at this point we need a new PackageSetting that
268            // is okay to muck with.
269            PackageSetting newp = new PackageSetting(p);
270            replacePackageLPw(name, newp);
271            return true;
272        }
273        return false;
274    }
275
276    PackageSetting enableSystemPackageLPw(String name) {
277        PackageSetting p = mDisabledSysPackages.get(name);
278        if(p == null) {
279            Log.w(PackageManagerService.TAG, "Package:"+name+" is not disabled");
280            return null;
281        }
282        // Reset flag in ApplicationInfo object
283        if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
284            p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
285        }
286        PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
287                p.nativeLibraryPathString, p.appId, p.versionCode, p.pkgFlags);
288        mDisabledSysPackages.remove(name);
289        return ret;
290    }
291
292    boolean isDisabledSystemPackageLPr(String name) {
293        return mDisabledSysPackages.containsKey(name);
294    }
295
296    void removeDisabledSystemPackageLPw(String name) {
297        mDisabledSysPackages.remove(name);
298    }
299
300    PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
301            String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
302        PackageSetting p = mPackages.get(name);
303        if (p != null) {
304            if (p.appId == uid) {
305                return p;
306            }
307            PackageManagerService.reportSettingsProblem(Log.ERROR,
308                    "Adding duplicate package, keeping first: " + name);
309            return null;
310        }
311        p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString,
312                vc, pkgFlags);
313        p.appId = uid;
314        if (addUserIdLPw(uid, p, name)) {
315            mPackages.put(name, p);
316            return p;
317        }
318        return null;
319    }
320
321    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags) {
322        SharedUserSetting s = mSharedUsers.get(name);
323        if (s != null) {
324            if (s.userId == uid) {
325                return s;
326            }
327            PackageManagerService.reportSettingsProblem(Log.ERROR,
328                    "Adding duplicate shared user, keeping first: " + name);
329            return null;
330        }
331        s = new SharedUserSetting(name, pkgFlags);
332        s.userId = uid;
333        if (addUserIdLPw(uid, s, name)) {
334            mSharedUsers.put(name, s);
335            return s;
336        }
337        return null;
338    }
339
340    // Transfer ownership of permissions from one package to another.
341    void transferPermissionsLPw(String origPkg, String newPkg) {
342        // Transfer ownership of permissions to the new package.
343        for (int i=0; i<2; i++) {
344            HashMap<String, BasePermission> permissions =
345                    i == 0 ? mPermissionTrees : mPermissions;
346            for (BasePermission bp : permissions.values()) {
347                if (origPkg.equals(bp.sourcePackage)) {
348                    if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG,
349                            "Moving permission " + bp.name
350                            + " from pkg " + bp.sourcePackage
351                            + " to " + newPkg);
352                    bp.sourcePackage = newPkg;
353                    bp.packageSetting = null;
354                    bp.perm = null;
355                    if (bp.pendingInfo != null) {
356                        bp.pendingInfo.packageName = newPkg;
357                    }
358                    bp.uid = 0;
359                    bp.gids = null;
360                }
361            }
362        }
363    }
364
365    private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
366            String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
367            String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {
368        PackageSetting p = mPackages.get(name);
369        if (p != null) {
370            if (!p.codePath.equals(codePath)) {
371                // Check to see if its a disabled system app
372                if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
373                    // This is an updated system app with versions in both system
374                    // and data partition. Just let the most recent version
375                    // take precedence.
376                    Slog.w(PackageManagerService.TAG, "Trying to update system app code path from "
377                            + p.codePathString + " to " + codePath.toString());
378                } else {
379                    // Just a change in the code path is not an issue, but
380                    // let's log a message about it.
381                    Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from "
382                            + p.codePath + " to " + codePath + "; Retaining data and using new");
383                    /*
384                     * Since we've changed paths, we need to prefer the new
385                     * native library path over the one stored in the
386                     * package settings since we might have moved from
387                     * internal to external storage or vice versa.
388                     */
389                    p.nativeLibraryPathString = nativeLibraryPathString;
390                }
391            }
392            if (p.sharedUser != sharedUser) {
393                PackageManagerService.reportSettingsProblem(Log.WARN,
394                        "Package " + name + " shared user changed from "
395                        + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
396                        + " to "
397                        + (sharedUser != null ? sharedUser.name : "<nothing>")
398                        + "; replacing with new");
399                p = null;
400            } else {
401                if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
402                    // If what we are scanning is a system package, then
403                    // make it so, regardless of whether it was previously
404                    // installed only in the data partition.
405                    p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
406                }
407            }
408        }
409        if (p == null) {
410            // Create a new PackageSettings entry. this can end up here because
411            // of code path mismatch or user id mismatch of an updated system partition
412            if (!create) {
413                return null;
414            }
415            if (origPackage != null) {
416                // We are consuming the data from an existing package.
417                p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
418                        nativeLibraryPathString, vc, pkgFlags);
419                if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
420                        + name + " is adopting original package " + origPackage.name);
421                // Note that we will retain the new package's signature so
422                // that we can keep its data.
423                PackageSignatures s = p.signatures;
424                p.copyFrom(origPackage);
425                p.signatures = s;
426                p.sharedUser = origPackage.sharedUser;
427                p.appId = origPackage.appId;
428                p.origPackage = origPackage;
429                mRenamedPackages.put(name, origPackage.name);
430                name = origPackage.name;
431                // Update new package state.
432                p.setTimeStamp(codePath.lastModified());
433            } else {
434                p = new PackageSetting(name, realName, codePath, resourcePath,
435                        nativeLibraryPathString, vc, pkgFlags);
436                p.setTimeStamp(codePath.lastModified());
437                p.sharedUser = sharedUser;
438                // If this is not a system app, it starts out stopped.
439                if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
440                    if (DEBUG_STOPPED) {
441                        RuntimeException e = new RuntimeException("here");
442                        e.fillInStackTrace();
443                        Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
444                    }
445                    List<UserInfo> users = getAllUsers();
446                    if (users != null) {
447                        for (UserInfo user : users) {
448                            p.setStopped(true, user.id);
449                            p.setNotLaunched(true, user.id);
450                            writePackageRestrictionsLPr(user.id);
451                        }
452                    }
453                }
454                if (sharedUser != null) {
455                    p.appId = sharedUser.userId;
456                } else {
457                    // Clone the setting here for disabled system packages
458                    PackageSetting dis = mDisabledSysPackages.get(name);
459                    if (dis != null) {
460                        // For disabled packages a new setting is created
461                        // from the existing user id. This still has to be
462                        // added to list of user id's
463                        // Copy signatures from previous setting
464                        if (dis.signatures.mSignatures != null) {
465                            p.signatures.mSignatures = dis.signatures.mSignatures.clone();
466                        }
467                        p.appId = dis.appId;
468                        // Clone permissions
469                        p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
470                        // Clone component info
471                        List<UserInfo> users = getAllUsers();
472                        if (users != null) {
473                            for (UserInfo user : users) {
474                                int userId = user.id;
475                                p.setDisabledComponents(
476                                        new HashSet<String>(dis.getDisabledComponents(userId)),
477                                        userId);
478                                p.setEnabledComponents(
479                                        new HashSet<String>(dis.getEnabledComponents(userId)),
480                                        userId);
481                            }
482                        }
483                        // Add new setting to list of user ids
484                        addUserIdLPw(p.appId, p, name);
485                    } else {
486                        // Assign new user id
487                        p.appId = newUserIdLPw(p);
488                    }
489                }
490            }
491            if (p.appId < 0) {
492                PackageManagerService.reportSettingsProblem(Log.WARN,
493                        "Package " + name + " could not be assigned a valid uid");
494                return null;
495            }
496            if (add) {
497                // Finish adding new package by adding it and updating shared
498                // user preferences
499                addPackageSettingLPw(p, name, sharedUser);
500            }
501        }
502        return p;
503    }
504
505    void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
506        p.pkg = pkg;
507        // pkg.mSetEnabled = p.getEnabled(userId);
508        // pkg.mSetStopped = p.getStopped(userId);
509        final String codePath = pkg.applicationInfo.sourceDir;
510        final String resourcePath = pkg.applicationInfo.publicSourceDir;
511        // Update code path if needed
512        if (!codePath.equalsIgnoreCase(p.codePathString)) {
513            Slog.w(PackageManagerService.TAG, "Code path for pkg : " + p.pkg.packageName +
514                    " changing from " + p.codePathString + " to " + codePath);
515            p.codePath = new File(codePath);
516            p.codePathString = codePath;
517        }
518        //Update resource path if needed
519        if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
520            Slog.w(PackageManagerService.TAG, "Resource path for pkg : " + p.pkg.packageName +
521                    " changing from " + p.resourcePathString + " to " + resourcePath);
522            p.resourcePath = new File(resourcePath);
523            p.resourcePathString = resourcePath;
524        }
525        // Update the native library path if needed
526        final String nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir;
527        if (nativeLibraryPath != null
528                && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) {
529            p.nativeLibraryPathString = nativeLibraryPath;
530        }
531        // Update version code if needed
532        if (pkg.mVersionCode != p.versionCode) {
533            p.versionCode = pkg.mVersionCode;
534        }
535        // Update signatures if needed.
536        if (p.signatures.mSignatures == null) {
537            p.signatures.assignSignatures(pkg.mSignatures);
538        }
539        // If this app defines a shared user id initialize
540        // the shared user signatures as well.
541        if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
542            p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
543        }
544        addPackageSettingLPw(p, pkg.packageName, p.sharedUser);
545    }
546
547    // Utility method that adds a PackageSetting to mPackages and
548    // completes updating the shared user attributes
549    private void addPackageSettingLPw(PackageSetting p, String name,
550            SharedUserSetting sharedUser) {
551        mPackages.put(name, p);
552        if (sharedUser != null) {
553            if (p.sharedUser != null && p.sharedUser != sharedUser) {
554                PackageManagerService.reportSettingsProblem(Log.ERROR,
555                        "Package " + p.name + " was user "
556                        + p.sharedUser + " but is now " + sharedUser
557                        + "; I am not changing its files so it will probably fail!");
558                p.sharedUser.packages.remove(p);
559            } else if (p.appId != sharedUser.userId) {
560                PackageManagerService.reportSettingsProblem(Log.ERROR,
561                    "Package " + p.name + " was user id " + p.appId
562                    + " but is now user " + sharedUser
563                    + " with id " + sharedUser.userId
564                    + "; I am not changing its files so it will probably fail!");
565            }
566
567            sharedUser.packages.add(p);
568            p.sharedUser = sharedUser;
569            p.appId = sharedUser.userId;
570        }
571    }
572
573    /*
574     * Update the shared user setting when a package using
575     * specifying the shared user id is removed. The gids
576     * associated with each permission of the deleted package
577     * are removed from the shared user's gid list only if its
578     * not in use by other permissions of packages in the
579     * shared user setting.
580     */
581    void updateSharedUserPermsLPw(PackageSetting deletedPs, int[] globalGids) {
582        if ((deletedPs == null) || (deletedPs.pkg == null)) {
583            Slog.i(PackageManagerService.TAG,
584                    "Trying to update info for null package. Just ignoring");
585            return;
586        }
587        // No sharedUserId
588        if (deletedPs.sharedUser == null) {
589            return;
590        }
591        SharedUserSetting sus = deletedPs.sharedUser;
592        // Update permissions
593        for (String eachPerm : deletedPs.pkg.requestedPermissions) {
594            boolean used = false;
595            if (!sus.grantedPermissions.contains(eachPerm)) {
596                continue;
597            }
598            for (PackageSetting pkg:sus.packages) {
599                if (pkg.pkg != null &&
600                        !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) &&
601                        pkg.pkg.requestedPermissions.contains(eachPerm)) {
602                    used = true;
603                    break;
604                }
605            }
606            if (!used) {
607                // can safely delete this permission from list
608                sus.grantedPermissions.remove(eachPerm);
609            }
610        }
611        // Update gids
612        int newGids[] = globalGids;
613        for (String eachPerm : sus.grantedPermissions) {
614            BasePermission bp = mPermissions.get(eachPerm);
615            if (bp != null) {
616                newGids = PackageManagerService.appendInts(newGids, bp.gids);
617            }
618        }
619        sus.gids = newGids;
620    }
621
622    int removePackageLPw(String name) {
623        final PackageSetting p = mPackages.get(name);
624        if (p != null) {
625            mPackages.remove(name);
626            if (p.sharedUser != null) {
627                p.sharedUser.packages.remove(p);
628                if (p.sharedUser.packages.size() == 0) {
629                    mSharedUsers.remove(p.sharedUser.name);
630                    removeUserIdLPw(p.sharedUser.userId);
631                    return p.sharedUser.userId;
632                }
633            } else {
634                removeUserIdLPw(p.appId);
635                return p.appId;
636            }
637        }
638        return -1;
639    }
640
641    private void replacePackageLPw(String name, PackageSetting newp) {
642        final PackageSetting p = mPackages.get(name);
643        if (p != null) {
644            if (p.sharedUser != null) {
645                p.sharedUser.packages.remove(p);
646                p.sharedUser.packages.add(newp);
647            } else {
648                replaceUserIdLPw(p.appId, newp);
649            }
650        }
651        mPackages.put(name, newp);
652    }
653
654    private boolean addUserIdLPw(int uid, Object obj, Object name) {
655        if (uid > Process.LAST_APPLICATION_UID) {
656            return false;
657        }
658
659        if (uid >= Process.FIRST_APPLICATION_UID) {
660            int N = mUserIds.size();
661            final int index = uid - Process.FIRST_APPLICATION_UID;
662            while (index >= N) {
663                mUserIds.add(null);
664                N++;
665            }
666            if (mUserIds.get(index) != null) {
667                PackageManagerService.reportSettingsProblem(Log.ERROR,
668                        "Adding duplicate user id: " + uid
669                        + " name=" + name);
670                return false;
671            }
672            mUserIds.set(index, obj);
673        } else {
674            if (mOtherUserIds.get(uid) != null) {
675                PackageManagerService.reportSettingsProblem(Log.ERROR,
676                        "Adding duplicate shared id: " + uid
677                        + " name=" + name);
678                return false;
679            }
680            mOtherUserIds.put(uid, obj);
681        }
682        return true;
683    }
684
685    public Object getUserIdLPr(int uid) {
686        if (uid >= Process.FIRST_APPLICATION_UID) {
687            final int N = mUserIds.size();
688            final int index = uid - Process.FIRST_APPLICATION_UID;
689            return index < N ? mUserIds.get(index) : null;
690        } else {
691            return mOtherUserIds.get(uid);
692        }
693    }
694
695    private void removeUserIdLPw(int uid) {
696        if (uid >= Process.FIRST_APPLICATION_UID) {
697            final int N = mUserIds.size();
698            final int index = uid - Process.FIRST_APPLICATION_UID;
699            if (index < N) mUserIds.set(index, null);
700        } else {
701            mOtherUserIds.remove(uid);
702        }
703    }
704
705    private void replaceUserIdLPw(int uid, Object obj) {
706        if (uid >= Process.FIRST_APPLICATION_UID) {
707            final int N = mUserIds.size();
708            final int index = uid - Process.FIRST_APPLICATION_UID;
709            if (index < N) mUserIds.set(index, obj);
710        } else {
711            mOtherUserIds.put(uid, obj);
712        }
713    }
714
715    private File getUserPackagesStateFile(int userId) {
716        return new File(mSystemDir,
717                "users/" + userId + "/package-restrictions.xml");
718    }
719
720    private File getUserPackagesStateBackupFile(int userId) {
721        return new File(mSystemDir,
722                "users/" + userId + "/package-restrictions-backup.xml");
723    }
724
725    void writeAllUsersPackageRestrictionsLPr() {
726        List<UserInfo> users = getAllUsers();
727        if (users == null) return;
728
729        for (UserInfo user : users) {
730            writePackageRestrictionsLPr(user.id);
731        }
732    }
733
734    void readAllUsersPackageRestrictionsLPr() {
735        List<UserInfo> users = getAllUsers();
736        if (users == null) {
737            readPackageRestrictionsLPr(0);
738            return;
739        }
740
741        for (UserInfo user : users) {
742            readPackageRestrictionsLPr(user.id);
743        }
744    }
745
746    void readPackageRestrictionsLPr(int userId) {
747        if (DEBUG_MU) {
748            Log.i(TAG, "Reading package restrictions for user=" + userId);
749        }
750        FileInputStream str = null;
751        File userPackagesStateFile = getUserPackagesStateFile(userId);
752        File backupFile = getUserPackagesStateBackupFile(userId);
753        if (backupFile.exists()) {
754            try {
755                str = new FileInputStream(backupFile);
756                mReadMessages.append("Reading from backup stopped packages file\n");
757                PackageManagerService.reportSettingsProblem(Log.INFO,
758                        "Need to read from backup stopped packages file");
759                if (userPackagesStateFile.exists()) {
760                    // If both the backup and normal file exist, we
761                    // ignore the normal one since it might have been
762                    // corrupted.
763                    Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
764                            + userPackagesStateFile);
765                    userPackagesStateFile.delete();
766                }
767            } catch (java.io.IOException e) {
768                // We'll try for the normal settings file.
769            }
770        }
771
772        try {
773            if (str == null) {
774                if (!userPackagesStateFile.exists()) {
775                    mReadMessages.append("No stopped packages file found\n");
776                    PackageManagerService.reportSettingsProblem(Log.INFO,
777                            "No stopped packages file; "
778                            + "assuming all started");
779                    // At first boot, make sure no packages are stopped.
780                    // We usually want to have third party apps initialize
781                    // in the stopped state, but not at first boot.
782                    for (PackageSetting pkg : mPackages.values()) {
783                        pkg.setStopped(false, userId);
784                        pkg.setNotLaunched(false, userId);
785                    }
786                    return;
787                }
788                str = new FileInputStream(userPackagesStateFile);
789            }
790            final XmlPullParser parser = Xml.newPullParser();
791            parser.setInput(str, null);
792
793            int type;
794            while ((type=parser.next()) != XmlPullParser.START_TAG
795                       && type != XmlPullParser.END_DOCUMENT) {
796                ;
797            }
798
799            if (type != XmlPullParser.START_TAG) {
800                mReadMessages.append("No start tag found in package restrictions file\n");
801                PackageManagerService.reportSettingsProblem(Log.WARN,
802                        "No start tag found in package manager stopped packages");
803                return;
804            }
805
806            int outerDepth = parser.getDepth();
807            PackageSetting ps = null;
808            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
809                   && (type != XmlPullParser.END_TAG
810                           || parser.getDepth() > outerDepth)) {
811                if (type == XmlPullParser.END_TAG
812                        || type == XmlPullParser.TEXT) {
813                    continue;
814                }
815
816                String tagName = parser.getName();
817                if (tagName.equals(TAG_PACKAGE)) {
818                    String name = parser.getAttributeValue(null, ATTR_NAME);
819                    ps = mPackages.get(name);
820                    if (ps == null) {
821                        Slog.w(PackageManagerService.TAG, "No package known for stopped package: "
822                                + name);
823                        XmlUtils.skipCurrentTag(parser);
824                        continue;
825                    }
826                    String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
827                    int enabled = enabledStr == null ? COMPONENT_ENABLED_STATE_DEFAULT
828                            : Integer.parseInt(enabledStr);
829                    ps.setEnabled(enabled, userId);
830                    String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
831                    boolean stopped = stoppedStr == null ? false : Boolean.parseBoolean(stoppedStr);
832                    ps.setStopped(stopped, userId);
833                    String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
834                    boolean notLaunched = stoppedStr == null ? false
835                            : Boolean.parseBoolean(notLaunchedStr);
836                    ps.setNotLaunched(notLaunched, userId);
837
838                    int packageDepth = parser.getDepth();
839                    while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
840                            && (type != XmlPullParser.END_TAG
841                            || parser.getDepth() > packageDepth)) {
842                        if (type == XmlPullParser.END_TAG
843                                || type == XmlPullParser.TEXT) {
844                            continue;
845                        }
846                        tagName = parser.getName();
847                        if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
848                            HashSet<String> components = readComponentsLPr(parser);
849                            ps.setEnabledComponents(components, userId);
850                        } else if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
851                            HashSet<String> components = readComponentsLPr(parser);
852                            ps.setDisabledComponents(components, userId);
853                        }
854                    }
855                } else {
856                    Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
857                          + parser.getName());
858                    XmlUtils.skipCurrentTag(parser);
859                }
860            }
861
862            str.close();
863
864        } catch (XmlPullParserException e) {
865            mReadMessages.append("Error reading: " + e.toString());
866            PackageManagerService.reportSettingsProblem(Log.ERROR,
867                    "Error reading stopped packages: " + e);
868            Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
869
870        } catch (java.io.IOException e) {
871            mReadMessages.append("Error reading: " + e.toString());
872            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
873            Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
874        }
875    }
876
877    private HashSet<String> readComponentsLPr(XmlPullParser parser)
878            throws IOException, XmlPullParserException {
879        HashSet<String> components = new HashSet<String>();
880        int type;
881        int outerDepth = parser.getDepth();
882        String tagName;
883        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
884                && (type != XmlPullParser.END_TAG
885                || parser.getDepth() > outerDepth)) {
886            if (type == XmlPullParser.END_TAG
887                    || type == XmlPullParser.TEXT) {
888                continue;
889            }
890            tagName = parser.getName();
891            if (tagName.equals(TAG_ITEM)) {
892                String componentName = parser.getAttributeValue(null, ATTR_NAME);
893                if (componentName != null) {
894                    components.add(componentName);
895                }
896            }
897        }
898        return components;
899    }
900
901    void writePackageRestrictionsLPr(int userId) {
902        if (DEBUG_MU) {
903            Log.i(TAG, "Writing package restrictions for user=" + userId);
904        }
905        // Keep the old stopped packages around until we know the new ones have
906        // been successfully written.
907        File userPackagesStateFile = getUserPackagesStateFile(userId);
908        File backupFile = getUserPackagesStateBackupFile(userId);
909        new File(userPackagesStateFile.getParent()).mkdirs();
910        if (userPackagesStateFile.exists()) {
911            // Presence of backup settings file indicates that we failed
912            // to persist packages earlier. So preserve the older
913            // backup for future reference since the current packages
914            // might have been corrupted.
915            if (!backupFile.exists()) {
916                if (!userPackagesStateFile.renameTo(backupFile)) {
917                    Log.wtf(PackageManagerService.TAG, "Unable to backup user packages state file, "
918                            + "current changes will be lost at reboot");
919                    return;
920                }
921            } else {
922                userPackagesStateFile.delete();
923                Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
924            }
925        }
926
927        try {
928            final FileOutputStream fstr = new FileOutputStream(userPackagesStateFile);
929            final BufferedOutputStream str = new BufferedOutputStream(fstr);
930
931            final XmlSerializer serializer = new FastXmlSerializer();
932            serializer.setOutput(str, "utf-8");
933            serializer.startDocument(null, true);
934            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
935
936            serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
937
938            for (final PackageSetting pkg : mPackages.values()) {
939                if (pkg.getStopped(userId)
940                        || pkg.getNotLaunched(userId)
941                        || pkg.getEnabled(userId) != COMPONENT_ENABLED_STATE_DEFAULT
942                        || pkg.getEnabledComponents(userId).size() > 0
943                        || pkg.getDisabledComponents(userId).size() > 0) {
944                    serializer.startTag(null, TAG_PACKAGE);
945                    serializer.attribute(null, ATTR_NAME, pkg.name);
946                    boolean stopped = pkg.getStopped(userId);
947                    boolean notLaunched = pkg.getNotLaunched(userId);
948                    int enabled = pkg.getEnabled(userId);
949                    if (DEBUG_MU) Log.i(TAG, "  pkg=" + pkg.name + ", state=" + enabled);
950                    HashSet<String> enabledComponents = pkg.getEnabledComponents(userId);
951                    HashSet<String> disabledComponents = pkg.getDisabledComponents(userId);
952
953                    if (stopped) {
954                        serializer.attribute(null, ATTR_STOPPED, "true");
955                    }
956                    if (notLaunched) {
957                        serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
958                    }
959                    if (enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
960                        serializer.attribute(null, ATTR_ENABLED, Integer.toString(enabled));
961                    }
962                    if (enabledComponents.size() > 0) {
963                        serializer.startTag(null, TAG_ENABLED_COMPONENTS);
964                        for (final String name : enabledComponents) {
965                            serializer.startTag(null, TAG_ITEM);
966                            serializer.attribute(null, ATTR_NAME, name);
967                            serializer.endTag(null, TAG_ITEM);
968                        }
969                        serializer.endTag(null, TAG_ENABLED_COMPONENTS);
970                    }
971                    if (disabledComponents.size() > 0) {
972                        serializer.startTag(null, TAG_DISABLED_COMPONENTS);
973                        for (final String name : disabledComponents) {
974                            serializer.startTag(null, TAG_ITEM);
975                            serializer.attribute(null, ATTR_NAME, name);
976                            serializer.endTag(null, TAG_ITEM);
977                        }
978                        serializer.endTag(null, TAG_DISABLED_COMPONENTS);
979                    }
980                    serializer.endTag(null, TAG_PACKAGE);
981                }
982            }
983
984            serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
985
986            serializer.endDocument();
987
988            str.flush();
989            FileUtils.sync(fstr);
990            str.close();
991
992            // New settings successfully written, old ones are no longer
993            // needed.
994            backupFile.delete();
995            FileUtils.setPermissions(userPackagesStateFile.toString(),
996                    FileUtils.S_IRUSR|FileUtils.S_IWUSR
997                    |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
998                    -1, -1);
999
1000            // Done, all is good!
1001            return;
1002        } catch(java.io.IOException e) {
1003            Log.wtf(PackageManagerService.TAG,
1004                    "Unable to write package manager user packages state, "
1005                    + " current changes will be lost at reboot", e);
1006        }
1007
1008        // Clean up partially written files
1009        if (userPackagesStateFile.exists()) {
1010            if (!userPackagesStateFile.delete()) {
1011                Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "
1012                        + mStoppedPackagesFilename);
1013            }
1014        }
1015    }
1016
1017    // Note: assumed "stopped" field is already cleared in all packages.
1018    // Legacy reader, used to read in the old file format after an upgrade. Not used after that.
1019    void readStoppedLPw() {
1020        FileInputStream str = null;
1021        if (mBackupStoppedPackagesFilename.exists()) {
1022            try {
1023                str = new FileInputStream(mBackupStoppedPackagesFilename);
1024                mReadMessages.append("Reading from backup stopped packages file\n");
1025                PackageManagerService.reportSettingsProblem(Log.INFO,
1026                        "Need to read from backup stopped packages file");
1027                if (mSettingsFilename.exists()) {
1028                    // If both the backup and normal file exist, we
1029                    // ignore the normal one since it might have been
1030                    // corrupted.
1031                    Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
1032                            + mStoppedPackagesFilename);
1033                    mStoppedPackagesFilename.delete();
1034                }
1035            } catch (java.io.IOException e) {
1036                // We'll try for the normal settings file.
1037            }
1038        }
1039
1040        try {
1041            if (str == null) {
1042                if (!mStoppedPackagesFilename.exists()) {
1043                    mReadMessages.append("No stopped packages file found\n");
1044                    PackageManagerService.reportSettingsProblem(Log.INFO,
1045                            "No stopped packages file file; assuming all started");
1046                    // At first boot, make sure no packages are stopped.
1047                    // We usually want to have third party apps initialize
1048                    // in the stopped state, but not at first boot.
1049                    for (PackageSetting pkg : mPackages.values()) {
1050                        pkg.setStopped(false, 0);
1051                        pkg.setNotLaunched(false, 0);
1052                    }
1053                    return;
1054                }
1055                str = new FileInputStream(mStoppedPackagesFilename);
1056            }
1057            final XmlPullParser parser = Xml.newPullParser();
1058            parser.setInput(str, null);
1059
1060            int type;
1061            while ((type=parser.next()) != XmlPullParser.START_TAG
1062                       && type != XmlPullParser.END_DOCUMENT) {
1063                ;
1064            }
1065
1066            if (type != XmlPullParser.START_TAG) {
1067                mReadMessages.append("No start tag found in stopped packages file\n");
1068                PackageManagerService.reportSettingsProblem(Log.WARN,
1069                        "No start tag found in package manager stopped packages");
1070                return;
1071            }
1072
1073            int outerDepth = parser.getDepth();
1074            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1075                   && (type != XmlPullParser.END_TAG
1076                           || parser.getDepth() > outerDepth)) {
1077                if (type == XmlPullParser.END_TAG
1078                        || type == XmlPullParser.TEXT) {
1079                    continue;
1080                }
1081
1082                String tagName = parser.getName();
1083                if (tagName.equals(TAG_PACKAGE)) {
1084                    String name = parser.getAttributeValue(null, ATTR_NAME);
1085                    PackageSetting ps = mPackages.get(name);
1086                    if (ps != null) {
1087                        ps.setStopped(true, 0);
1088                        if ("1".equals(parser.getAttributeValue(null, ATTR_NOT_LAUNCHED))) {
1089                            ps.setNotLaunched(true, 0);
1090                        }
1091                    } else {
1092                        Slog.w(PackageManagerService.TAG,
1093                                "No package known for stopped package: " + name);
1094                    }
1095                    XmlUtils.skipCurrentTag(parser);
1096                } else {
1097                    Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
1098                          + parser.getName());
1099                    XmlUtils.skipCurrentTag(parser);
1100                }
1101            }
1102
1103            str.close();
1104
1105        } catch (XmlPullParserException e) {
1106            mReadMessages.append("Error reading: " + e.toString());
1107            PackageManagerService.reportSettingsProblem(Log.ERROR,
1108                    "Error reading stopped packages: " + e);
1109            Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
1110
1111        } catch (java.io.IOException e) {
1112            mReadMessages.append("Error reading: " + e.toString());
1113            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
1114            Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
1115
1116        }
1117    }
1118
1119    void writeLPr() {
1120        //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
1121
1122        // Keep the old settings around until we know the new ones have
1123        // been successfully written.
1124        if (mSettingsFilename.exists()) {
1125            // Presence of backup settings file indicates that we failed
1126            // to persist settings earlier. So preserve the older
1127            // backup for future reference since the current settings
1128            // might have been corrupted.
1129            if (!mBackupSettingsFilename.exists()) {
1130                if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
1131                    Log.wtf(PackageManagerService.TAG, "Unable to backup package manager settings, "
1132                            + " current changes will be lost at reboot");
1133                    return;
1134                }
1135            } else {
1136                mSettingsFilename.delete();
1137                Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
1138            }
1139        }
1140
1141        mPastSignatures.clear();
1142
1143        try {
1144            FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
1145            BufferedOutputStream str = new BufferedOutputStream(fstr);
1146
1147            //XmlSerializer serializer = XmlUtils.serializerInstance();
1148            XmlSerializer serializer = new FastXmlSerializer();
1149            serializer.setOutput(str, "utf-8");
1150            serializer.startDocument(null, true);
1151            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1152
1153            serializer.startTag(null, "packages");
1154
1155            serializer.startTag(null, "last-platform-version");
1156            serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
1157            serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
1158            serializer.endTag(null, "last-platform-version");
1159
1160            if (mVerifierDeviceIdentity != null) {
1161                serializer.startTag(null, "verifier");
1162                serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
1163                serializer.endTag(null, "verifier");
1164            }
1165
1166            if (mReadExternalStorageEnforced != null) {
1167                serializer.startTag(null, TAG_READ_EXTERNAL_STORAGE);
1168                serializer.attribute(
1169                        null, ATTR_ENFORCEMENT, mReadExternalStorageEnforced ? "1" : "0");
1170                serializer.endTag(null, TAG_READ_EXTERNAL_STORAGE);
1171            }
1172
1173            serializer.startTag(null, "permission-trees");
1174            for (BasePermission bp : mPermissionTrees.values()) {
1175                writePermissionLPr(serializer, bp);
1176            }
1177            serializer.endTag(null, "permission-trees");
1178
1179            serializer.startTag(null, "permissions");
1180            for (BasePermission bp : mPermissions.values()) {
1181                writePermissionLPr(serializer, bp);
1182            }
1183            serializer.endTag(null, "permissions");
1184
1185            for (final PackageSetting pkg : mPackages.values()) {
1186                writePackageLPr(serializer, pkg);
1187            }
1188
1189            for (final PackageSetting pkg : mDisabledSysPackages.values()) {
1190                writeDisabledSysPackageLPr(serializer, pkg);
1191            }
1192
1193            writePreferredActivitiesLPr(serializer);
1194
1195            for (final SharedUserSetting usr : mSharedUsers.values()) {
1196                serializer.startTag(null, "shared-user");
1197                serializer.attribute(null, ATTR_NAME, usr.name);
1198                serializer.attribute(null, "userId",
1199                        Integer.toString(usr.userId));
1200                usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
1201                serializer.startTag(null, "perms");
1202                for (String name : usr.grantedPermissions) {
1203                    serializer.startTag(null, TAG_ITEM);
1204                    serializer.attribute(null, ATTR_NAME, name);
1205                    serializer.endTag(null, TAG_ITEM);
1206                }
1207                serializer.endTag(null, "perms");
1208                serializer.endTag(null, "shared-user");
1209            }
1210
1211            if (mPackagesToBeCleaned.size() > 0) {
1212                for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
1213                    serializer.startTag(null, "cleaning-package");
1214                    serializer.attribute(null, ATTR_NAME, mPackagesToBeCleaned.get(i));
1215                    serializer.endTag(null, "cleaning-package");
1216                }
1217            }
1218
1219            if (mRenamedPackages.size() > 0) {
1220                for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
1221                    serializer.startTag(null, "renamed-package");
1222                    serializer.attribute(null, "new", e.getKey());
1223                    serializer.attribute(null, "old", e.getValue());
1224                    serializer.endTag(null, "renamed-package");
1225                }
1226            }
1227
1228            serializer.endTag(null, "packages");
1229
1230            serializer.endDocument();
1231
1232            str.flush();
1233            FileUtils.sync(fstr);
1234            str.close();
1235
1236            // New settings successfully written, old ones are no longer
1237            // needed.
1238            mBackupSettingsFilename.delete();
1239            FileUtils.setPermissions(mSettingsFilename.toString(),
1240                    FileUtils.S_IRUSR|FileUtils.S_IWUSR
1241                    |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
1242                    -1, -1);
1243
1244            // Write package list file now, use a JournaledFile.
1245            //
1246            File tempFile = new File(mPackageListFilename.toString() + ".tmp");
1247            JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
1248
1249            fstr = new FileOutputStream(journal.chooseForWrite());
1250            str = new BufferedOutputStream(fstr);
1251            try {
1252                StringBuilder sb = new StringBuilder();
1253                for (final PackageSetting pkg : mPackages.values()) {
1254                    ApplicationInfo ai = pkg.pkg.applicationInfo;
1255                    String dataPath = ai.dataDir;
1256                    boolean isDebug  = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
1257
1258                    // Avoid any application that has a space in its path
1259                    // or that is handled by the system.
1260                    if (dataPath.indexOf(" ") >= 0 || ai.uid < Process.FIRST_APPLICATION_UID)
1261                        continue;
1262
1263                    // we store on each line the following information for now:
1264                    //
1265                    // pkgName    - package name
1266                    // userId     - application-specific user id
1267                    // debugFlag  - 0 or 1 if the package is debuggable.
1268                    // dataPath   - path to package's data path
1269                    //
1270                    // NOTE: We prefer not to expose all ApplicationInfo flags for now.
1271                    //
1272                    // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
1273                    // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
1274                    //   system/core/run-as/run-as.c
1275                    //
1276                    sb.setLength(0);
1277                    sb.append(ai.packageName);
1278                    sb.append(" ");
1279                    sb.append((int)ai.uid);
1280                    sb.append(isDebug ? " 1 " : " 0 ");
1281                    sb.append(dataPath);
1282                    sb.append("\n");
1283                    str.write(sb.toString().getBytes());
1284                }
1285                str.flush();
1286                FileUtils.sync(fstr);
1287                str.close();
1288                journal.commit();
1289            } catch (Exception e) {
1290                IoUtils.closeQuietly(str);
1291                journal.rollback();
1292            }
1293
1294            FileUtils.setPermissions(mPackageListFilename.toString(),
1295                    FileUtils.S_IRUSR|FileUtils.S_IWUSR
1296                    |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
1297                    -1, -1);
1298
1299            writeAllUsersPackageRestrictionsLPr();
1300            return;
1301
1302        } catch(XmlPullParserException e) {
1303            Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
1304                    + "current changes will be lost at reboot", e);
1305        } catch(java.io.IOException e) {
1306            Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
1307                    + "current changes will be lost at reboot", e);
1308        }
1309        // Clean up partially written files
1310        if (mSettingsFilename.exists()) {
1311            if (!mSettingsFilename.delete()) {
1312                Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
1313                        + mSettingsFilename);
1314            }
1315        }
1316        //Debug.stopMethodTracing();
1317    }
1318
1319    void writePreferredActivitiesLPr(XmlSerializer serializer)
1320            throws IllegalArgumentException, IllegalStateException, IOException {
1321        serializer.startTag(null, "preferred-activities");
1322        for (final PreferredActivity pa : mPreferredActivities.filterSet()) {
1323            serializer.startTag(null, TAG_ITEM);
1324            pa.writeToXml(serializer);
1325            serializer.endTag(null, TAG_ITEM);
1326        }
1327        serializer.endTag(null, "preferred-activities");
1328    }
1329
1330    void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
1331            throws java.io.IOException {
1332        serializer.startTag(null, "updated-package");
1333        serializer.attribute(null, ATTR_NAME, pkg.name);
1334        if (pkg.realName != null) {
1335            serializer.attribute(null, "realName", pkg.realName);
1336        }
1337        serializer.attribute(null, "codePath", pkg.codePathString);
1338        serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
1339        serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
1340        serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
1341        serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
1342        if (!pkg.resourcePathString.equals(pkg.codePathString)) {
1343            serializer.attribute(null, "resourcePath", pkg.resourcePathString);
1344        }
1345        if (pkg.nativeLibraryPathString != null) {
1346            serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
1347        }
1348        if (pkg.sharedUser == null) {
1349            serializer.attribute(null, "userId", Integer.toString(pkg.appId));
1350        } else {
1351            serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId));
1352        }
1353        serializer.startTag(null, "perms");
1354        if (pkg.sharedUser == null) {
1355            // If this is a shared user, the permissions will
1356            // be written there. We still need to write an
1357            // empty permissions list so permissionsFixed will
1358            // be set.
1359            for (final String name : pkg.grantedPermissions) {
1360                BasePermission bp = mPermissions.get(name);
1361                if (bp != null) {
1362                    // We only need to write signature or system permissions but
1363                    // this wont
1364                    // match the semantics of grantedPermissions. So write all
1365                    // permissions.
1366                    serializer.startTag(null, TAG_ITEM);
1367                    serializer.attribute(null, ATTR_NAME, name);
1368                    serializer.endTag(null, TAG_ITEM);
1369                }
1370            }
1371        }
1372        serializer.endTag(null, "perms");
1373        serializer.endTag(null, "updated-package");
1374    }
1375
1376    void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg)
1377            throws java.io.IOException {
1378        serializer.startTag(null, "package");
1379        serializer.attribute(null, ATTR_NAME, pkg.name);
1380        if (pkg.realName != null) {
1381            serializer.attribute(null, "realName", pkg.realName);
1382        }
1383        serializer.attribute(null, "codePath", pkg.codePathString);
1384        if (!pkg.resourcePathString.equals(pkg.codePathString)) {
1385            serializer.attribute(null, "resourcePath", pkg.resourcePathString);
1386        }
1387        if (pkg.nativeLibraryPathString != null) {
1388            serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
1389        }
1390        serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags));
1391        serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
1392        serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
1393        serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
1394        serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
1395        if (pkg.sharedUser == null) {
1396            serializer.attribute(null, "userId", Integer.toString(pkg.appId));
1397        } else {
1398            serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId));
1399        }
1400        if (pkg.uidError) {
1401            serializer.attribute(null, "uidError", "true");
1402        }
1403        if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
1404            serializer.attribute(null, "installStatus", "false");
1405        }
1406        if (pkg.installerPackageName != null) {
1407            serializer.attribute(null, "installer", pkg.installerPackageName);
1408        }
1409        pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
1410        if ((pkg.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
1411            serializer.startTag(null, "perms");
1412            if (pkg.sharedUser == null) {
1413                // If this is a shared user, the permissions will
1414                // be written there. We still need to write an
1415                // empty permissions list so permissionsFixed will
1416                // be set.
1417                for (final String name : pkg.grantedPermissions) {
1418                    serializer.startTag(null, TAG_ITEM);
1419                    serializer.attribute(null, ATTR_NAME, name);
1420                    serializer.endTag(null, TAG_ITEM);
1421                }
1422            }
1423            serializer.endTag(null, "perms");
1424        }
1425
1426        serializer.endTag(null, "package");
1427    }
1428
1429    void writePermissionLPr(XmlSerializer serializer, BasePermission bp)
1430            throws XmlPullParserException, java.io.IOException {
1431        if (bp.type != BasePermission.TYPE_BUILTIN && bp.sourcePackage != null) {
1432            serializer.startTag(null, TAG_ITEM);
1433            serializer.attribute(null, ATTR_NAME, bp.name);
1434            serializer.attribute(null, "package", bp.sourcePackage);
1435            if (bp.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
1436                serializer.attribute(null, "protection", Integer.toString(bp.protectionLevel));
1437            }
1438            if (PackageManagerService.DEBUG_SETTINGS)
1439                Log.v(PackageManagerService.TAG, "Writing perm: name=" + bp.name + " type="
1440                        + bp.type);
1441            if (bp.type == BasePermission.TYPE_DYNAMIC) {
1442                final PermissionInfo pi = bp.perm != null ? bp.perm.info : bp.pendingInfo;
1443                if (pi != null) {
1444                    serializer.attribute(null, "type", "dynamic");
1445                    if (pi.icon != 0) {
1446                        serializer.attribute(null, "icon", Integer.toString(pi.icon));
1447                    }
1448                    if (pi.nonLocalizedLabel != null) {
1449                        serializer.attribute(null, "label", pi.nonLocalizedLabel.toString());
1450                    }
1451                }
1452            }
1453            serializer.endTag(null, TAG_ITEM);
1454        }
1455    }
1456
1457    ArrayList<PackageSetting> getListOfIncompleteInstallPackagesLPr() {
1458        final HashSet<String> kList = new HashSet<String>(mPackages.keySet());
1459        final Iterator<String> its = kList.iterator();
1460        final ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
1461        while (its.hasNext()) {
1462            final String key = its.next();
1463            final PackageSetting ps = mPackages.get(key);
1464            if (ps.getInstallStatus() == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
1465                ret.add(ps);
1466            }
1467        }
1468        return ret;
1469    }
1470
1471    boolean readLPw(List<UserInfo> users) {
1472        FileInputStream str = null;
1473        if (mBackupSettingsFilename.exists()) {
1474            try {
1475                str = new FileInputStream(mBackupSettingsFilename);
1476                mReadMessages.append("Reading from backup settings file\n");
1477                PackageManagerService.reportSettingsProblem(Log.INFO,
1478                        "Need to read from backup settings file");
1479                if (mSettingsFilename.exists()) {
1480                    // If both the backup and settings file exist, we
1481                    // ignore the settings since it might have been
1482                    // corrupted.
1483                    Slog.w(PackageManagerService.TAG, "Cleaning up settings file "
1484                            + mSettingsFilename);
1485                    mSettingsFilename.delete();
1486                }
1487            } catch (java.io.IOException e) {
1488                // We'll try for the normal settings file.
1489            }
1490        }
1491
1492        mPendingPackages.clear();
1493        mPastSignatures.clear();
1494
1495        try {
1496            if (str == null) {
1497                if (!mSettingsFilename.exists()) {
1498                    mReadMessages.append("No settings file found\n");
1499                    PackageManagerService.reportSettingsProblem(Log.INFO,
1500                            "No settings file; creating initial state");
1501                    readDefaultPreferredAppsLPw();
1502                    return false;
1503                }
1504                str = new FileInputStream(mSettingsFilename);
1505            }
1506            XmlPullParser parser = Xml.newPullParser();
1507            parser.setInput(str, null);
1508
1509            int type;
1510            while ((type = parser.next()) != XmlPullParser.START_TAG
1511                    && type != XmlPullParser.END_DOCUMENT) {
1512                ;
1513            }
1514
1515            if (type != XmlPullParser.START_TAG) {
1516                mReadMessages.append("No start tag found in settings file\n");
1517                PackageManagerService.reportSettingsProblem(Log.WARN,
1518                        "No start tag found in package manager settings");
1519                Log.wtf(PackageManagerService.TAG,
1520                        "No start tag found in package manager settings");
1521                return false;
1522            }
1523
1524            int outerDepth = parser.getDepth();
1525            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1526                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1527                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1528                    continue;
1529                }
1530
1531                String tagName = parser.getName();
1532                if (tagName.equals("package")) {
1533                    readPackageLPw(parser);
1534                } else if (tagName.equals("permissions")) {
1535                    readPermissionsLPw(mPermissions, parser);
1536                } else if (tagName.equals("permission-trees")) {
1537                    readPermissionsLPw(mPermissionTrees, parser);
1538                } else if (tagName.equals("shared-user")) {
1539                    readSharedUserLPw(parser);
1540                } else if (tagName.equals("preferred-packages")) {
1541                    // no longer used.
1542                } else if (tagName.equals("preferred-activities")) {
1543                    readPreferredActivitiesLPw(parser);
1544                } else if (tagName.equals("updated-package")) {
1545                    readDisabledSysPackageLPw(parser);
1546                } else if (tagName.equals("cleaning-package")) {
1547                    String name = parser.getAttributeValue(null, ATTR_NAME);
1548                    if (name != null) {
1549                        mPackagesToBeCleaned.add(name);
1550                    }
1551                } else if (tagName.equals("renamed-package")) {
1552                    String nname = parser.getAttributeValue(null, "new");
1553                    String oname = parser.getAttributeValue(null, "old");
1554                    if (nname != null && oname != null) {
1555                        mRenamedPackages.put(nname, oname);
1556                    }
1557                } else if (tagName.equals("last-platform-version")) {
1558                    mInternalSdkPlatform = mExternalSdkPlatform = 0;
1559                    try {
1560                        String internal = parser.getAttributeValue(null, "internal");
1561                        if (internal != null) {
1562                            mInternalSdkPlatform = Integer.parseInt(internal);
1563                        }
1564                        String external = parser.getAttributeValue(null, "external");
1565                        if (external != null) {
1566                            mExternalSdkPlatform = Integer.parseInt(external);
1567                        }
1568                    } catch (NumberFormatException e) {
1569                    }
1570                } else if (tagName.equals("verifier")) {
1571                    final String deviceIdentity = parser.getAttributeValue(null, "device");
1572                    try {
1573                        mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
1574                    } catch (IllegalArgumentException e) {
1575                        Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
1576                                + e.getMessage());
1577                    }
1578                } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
1579                    final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
1580                    mReadExternalStorageEnforced = "1".equals(enforcement);
1581                } else {
1582                    Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
1583                            + parser.getName());
1584                    XmlUtils.skipCurrentTag(parser);
1585                }
1586            }
1587
1588            str.close();
1589
1590        } catch (XmlPullParserException e) {
1591            mReadMessages.append("Error reading: " + e.toString());
1592            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
1593            Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
1594
1595        } catch (java.io.IOException e) {
1596            mReadMessages.append("Error reading: " + e.toString());
1597            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
1598            Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
1599        }
1600
1601        if (mBackupStoppedPackagesFilename.exists()
1602                || mStoppedPackagesFilename.exists()) {
1603            // Read old file
1604            readStoppedLPw();
1605            mBackupStoppedPackagesFilename.delete();
1606            mStoppedPackagesFilename.delete();
1607            // Migrate to new file format
1608            writePackageRestrictionsLPr(0);
1609        } else {
1610            if (users == null) {
1611                readPackageRestrictionsLPr(0);
1612            } else {
1613                for (UserInfo user : users) {
1614                    readPackageRestrictionsLPr(user.id);
1615                }
1616            }
1617        }
1618
1619        final int N = mPendingPackages.size();
1620        for (int i = 0; i < N; i++) {
1621            final PendingPackage pp = mPendingPackages.get(i);
1622            Object idObj = getUserIdLPr(pp.sharedId);
1623            if (idObj != null && idObj instanceof SharedUserSetting) {
1624                PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
1625                        (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
1626                        pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, true, true);
1627                if (p == null) {
1628                    PackageManagerService.reportSettingsProblem(Log.WARN,
1629                            "Unable to create application package for " + pp.name);
1630                    continue;
1631                }
1632                p.copyFrom(pp);
1633            } else if (idObj != null) {
1634                String msg = "Bad package setting: package " + pp.name + " has shared uid "
1635                        + pp.sharedId + " that is not a shared uid\n";
1636                mReadMessages.append(msg);
1637                PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
1638            } else {
1639                String msg = "Bad package setting: package " + pp.name + " has shared uid "
1640                        + pp.sharedId + " that is not defined\n";
1641                mReadMessages.append(msg);
1642                PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
1643            }
1644        }
1645        mPendingPackages.clear();
1646
1647        /*
1648         * Make sure all the updated system packages have their shared users
1649         * associated with them.
1650         */
1651        final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
1652        while (disabledIt.hasNext()) {
1653            final PackageSetting disabledPs = disabledIt.next();
1654            final Object id = getUserIdLPr(disabledPs.appId);
1655            if (id != null && id instanceof SharedUserSetting) {
1656                disabledPs.sharedUser = (SharedUserSetting) id;
1657            }
1658        }
1659
1660        mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
1661                + mSharedUsers.size() + " shared uids\n");
1662
1663        return true;
1664    }
1665
1666    private void readDefaultPreferredAppsLPw() {
1667        // Read preferred apps from .../etc/preferred-apps directory.
1668        File preferredDir = new File(Environment.getRootDirectory(), "etc/preferred-apps");
1669        if (!preferredDir.exists() || !preferredDir.isDirectory()) {
1670            return;
1671        }
1672        if (!preferredDir.canRead()) {
1673            Slog.w(TAG, "Directory " + preferredDir + " cannot be read");
1674            return;
1675        }
1676
1677        // Iterate over the files in the directory and scan .xml files
1678        for (File f : preferredDir.listFiles()) {
1679            if (!f.getPath().endsWith(".xml")) {
1680                Slog.i(TAG, "Non-xml file " + f + " in " + preferredDir + " directory, ignoring");
1681                continue;
1682            }
1683            if (!f.canRead()) {
1684                Slog.w(TAG, "Preferred apps file " + f + " cannot be read");
1685                continue;
1686            }
1687
1688            FileInputStream str = null;
1689            try {
1690                str = new FileInputStream(f);
1691                XmlPullParser parser = Xml.newPullParser();
1692                parser.setInput(str, null);
1693
1694                int type;
1695                while ((type = parser.next()) != XmlPullParser.START_TAG
1696                        && type != XmlPullParser.END_DOCUMENT) {
1697                    ;
1698                }
1699
1700                if (type != XmlPullParser.START_TAG) {
1701                    Slog.w(TAG, "Preferred apps file " + f + " does not have start tag");
1702                    continue;
1703                }
1704                if (!"preferred-activities".equals(parser.getName())) {
1705                    Slog.w(TAG, "Preferred apps file " + f
1706                            + " does not start with 'preferred-activities'");
1707                    continue;
1708                }
1709                readPreferredActivitiesLPw(parser);
1710            } catch (XmlPullParserException e) {
1711                Slog.w(TAG, "Error reading apps file " + f, e);
1712            } catch (IOException e) {
1713                Slog.w(TAG, "Error reading apps file " + f, e);
1714            } finally {
1715                if (str != null) {
1716                    try {
1717                        str.close();
1718                    } catch (IOException e) {
1719                    }
1720                }
1721            }
1722        }
1723    }
1724
1725    private int readInt(XmlPullParser parser, String ns, String name, int defValue) {
1726        String v = parser.getAttributeValue(ns, name);
1727        try {
1728            if (v == null) {
1729                return defValue;
1730            }
1731            return Integer.parseInt(v);
1732        } catch (NumberFormatException e) {
1733            PackageManagerService.reportSettingsProblem(Log.WARN,
1734                    "Error in package manager settings: attribute " + name
1735                            + " has bad integer value " + v + " at "
1736                            + parser.getPositionDescription());
1737        }
1738        return defValue;
1739    }
1740
1741    private void readPermissionsLPw(HashMap<String, BasePermission> out, XmlPullParser parser)
1742            throws IOException, XmlPullParserException {
1743        int outerDepth = parser.getDepth();
1744        int type;
1745        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1746                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1747            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1748                continue;
1749            }
1750
1751            final String tagName = parser.getName();
1752            if (tagName.equals(TAG_ITEM)) {
1753                final String name = parser.getAttributeValue(null, ATTR_NAME);
1754                final String sourcePackage = parser.getAttributeValue(null, "package");
1755                final String ptype = parser.getAttributeValue(null, "type");
1756                if (name != null && sourcePackage != null) {
1757                    final boolean dynamic = "dynamic".equals(ptype);
1758                    final BasePermission bp = new BasePermission(name, sourcePackage,
1759                            dynamic ? BasePermission.TYPE_DYNAMIC : BasePermission.TYPE_NORMAL);
1760                    bp.protectionLevel = readInt(parser, null, "protection",
1761                            PermissionInfo.PROTECTION_NORMAL);
1762                    bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel);
1763                    if (dynamic) {
1764                        PermissionInfo pi = new PermissionInfo();
1765                        pi.packageName = sourcePackage.intern();
1766                        pi.name = name.intern();
1767                        pi.icon = readInt(parser, null, "icon", 0);
1768                        pi.nonLocalizedLabel = parser.getAttributeValue(null, "label");
1769                        pi.protectionLevel = bp.protectionLevel;
1770                        bp.pendingInfo = pi;
1771                    }
1772                    out.put(bp.name, bp);
1773                } else {
1774                    PackageManagerService.reportSettingsProblem(Log.WARN,
1775                            "Error in package manager settings: permissions has" + " no name at "
1776                                    + parser.getPositionDescription());
1777                }
1778            } else {
1779                PackageManagerService.reportSettingsProblem(Log.WARN,
1780                        "Unknown element reading permissions: " + parser.getName() + " at "
1781                                + parser.getPositionDescription());
1782            }
1783            XmlUtils.skipCurrentTag(parser);
1784        }
1785    }
1786
1787    private void readDisabledSysPackageLPw(XmlPullParser parser) throws XmlPullParserException,
1788            IOException {
1789        String name = parser.getAttributeValue(null, ATTR_NAME);
1790        String realName = parser.getAttributeValue(null, "realName");
1791        String codePathStr = parser.getAttributeValue(null, "codePath");
1792        String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
1793        String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
1794        if (resourcePathStr == null) {
1795            resourcePathStr = codePathStr;
1796        }
1797        String version = parser.getAttributeValue(null, "version");
1798        int versionCode = 0;
1799        if (version != null) {
1800            try {
1801                versionCode = Integer.parseInt(version);
1802            } catch (NumberFormatException e) {
1803            }
1804        }
1805
1806        int pkgFlags = 0;
1807        pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
1808        PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
1809                new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags);
1810        String timeStampStr = parser.getAttributeValue(null, "ft");
1811        if (timeStampStr != null) {
1812            try {
1813                long timeStamp = Long.parseLong(timeStampStr, 16);
1814                ps.setTimeStamp(timeStamp);
1815            } catch (NumberFormatException e) {
1816            }
1817        } else {
1818            timeStampStr = parser.getAttributeValue(null, "ts");
1819            if (timeStampStr != null) {
1820                try {
1821                    long timeStamp = Long.parseLong(timeStampStr);
1822                    ps.setTimeStamp(timeStamp);
1823                } catch (NumberFormatException e) {
1824                }
1825            }
1826        }
1827        timeStampStr = parser.getAttributeValue(null, "it");
1828        if (timeStampStr != null) {
1829            try {
1830                ps.firstInstallTime = Long.parseLong(timeStampStr, 16);
1831            } catch (NumberFormatException e) {
1832            }
1833        }
1834        timeStampStr = parser.getAttributeValue(null, "ut");
1835        if (timeStampStr != null) {
1836            try {
1837                ps.lastUpdateTime = Long.parseLong(timeStampStr, 16);
1838            } catch (NumberFormatException e) {
1839            }
1840        }
1841        String idStr = parser.getAttributeValue(null, "userId");
1842        ps.appId = idStr != null ? Integer.parseInt(idStr) : 0;
1843        if (ps.appId <= 0) {
1844            String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
1845            ps.appId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
1846        }
1847        int outerDepth = parser.getDepth();
1848        int type;
1849        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1850                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1851            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1852                continue;
1853            }
1854
1855            String tagName = parser.getName();
1856            if (tagName.equals("perms")) {
1857                readGrantedPermissionsLPw(parser, ps.grantedPermissions);
1858            } else {
1859                PackageManagerService.reportSettingsProblem(Log.WARN,
1860                        "Unknown element under <updated-package>: " + parser.getName());
1861                XmlUtils.skipCurrentTag(parser);
1862            }
1863        }
1864        mDisabledSysPackages.put(name, ps);
1865    }
1866
1867    private void readPackageLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
1868        String name = null;
1869        String realName = null;
1870        String idStr = null;
1871        String sharedIdStr = null;
1872        String codePathStr = null;
1873        String resourcePathStr = null;
1874        String nativeLibraryPathStr = null;
1875        String systemStr = null;
1876        String installerPackageName = null;
1877        String uidError = null;
1878        int pkgFlags = 0;
1879        long timeStamp = 0;
1880        long firstInstallTime = 0;
1881        long lastUpdateTime = 0;
1882        PackageSettingBase packageSetting = null;
1883        String version = null;
1884        int versionCode = 0;
1885        try {
1886            name = parser.getAttributeValue(null, ATTR_NAME);
1887            realName = parser.getAttributeValue(null, "realName");
1888            idStr = parser.getAttributeValue(null, "userId");
1889            uidError = parser.getAttributeValue(null, "uidError");
1890            sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
1891            codePathStr = parser.getAttributeValue(null, "codePath");
1892            resourcePathStr = parser.getAttributeValue(null, "resourcePath");
1893            nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
1894            version = parser.getAttributeValue(null, "version");
1895            if (version != null) {
1896                try {
1897                    versionCode = Integer.parseInt(version);
1898                } catch (NumberFormatException e) {
1899                }
1900            }
1901            installerPackageName = parser.getAttributeValue(null, "installer");
1902
1903            systemStr = parser.getAttributeValue(null, "flags");
1904            if (systemStr != null) {
1905                try {
1906                    pkgFlags = Integer.parseInt(systemStr);
1907                } catch (NumberFormatException e) {
1908                }
1909            } else {
1910                // For backward compatibility
1911                systemStr = parser.getAttributeValue(null, "system");
1912                if (systemStr != null) {
1913                    pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM
1914                            : 0;
1915                } else {
1916                    // Old settings that don't specify system... just treat
1917                    // them as system, good enough.
1918                    pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
1919                }
1920            }
1921            String timeStampStr = parser.getAttributeValue(null, "ft");
1922            if (timeStampStr != null) {
1923                try {
1924                    timeStamp = Long.parseLong(timeStampStr, 16);
1925                } catch (NumberFormatException e) {
1926                }
1927            } else {
1928                timeStampStr = parser.getAttributeValue(null, "ts");
1929                if (timeStampStr != null) {
1930                    try {
1931                        timeStamp = Long.parseLong(timeStampStr);
1932                    } catch (NumberFormatException e) {
1933                    }
1934                }
1935            }
1936            timeStampStr = parser.getAttributeValue(null, "it");
1937            if (timeStampStr != null) {
1938                try {
1939                    firstInstallTime = Long.parseLong(timeStampStr, 16);
1940                } catch (NumberFormatException e) {
1941                }
1942            }
1943            timeStampStr = parser.getAttributeValue(null, "ut");
1944            if (timeStampStr != null) {
1945                try {
1946                    lastUpdateTime = Long.parseLong(timeStampStr, 16);
1947                } catch (NumberFormatException e) {
1948                }
1949            }
1950            if (PackageManagerService.DEBUG_SETTINGS)
1951                Log.v(PackageManagerService.TAG, "Reading package: " + name + " userId=" + idStr
1952                        + " sharedUserId=" + sharedIdStr);
1953            int userId = idStr != null ? Integer.parseInt(idStr) : 0;
1954            if (resourcePathStr == null) {
1955                resourcePathStr = codePathStr;
1956            }
1957            if (realName != null) {
1958                realName = realName.intern();
1959            }
1960            if (name == null) {
1961                PackageManagerService.reportSettingsProblem(Log.WARN,
1962                        "Error in package manager settings: <package> has no name at "
1963                                + parser.getPositionDescription());
1964            } else if (codePathStr == null) {
1965                PackageManagerService.reportSettingsProblem(Log.WARN,
1966                        "Error in package manager settings: <package> has no codePath at "
1967                                + parser.getPositionDescription());
1968            } else if (userId > 0) {
1969                packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
1970                        new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode,
1971                        pkgFlags);
1972                if (PackageManagerService.DEBUG_SETTINGS)
1973                    Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
1974                            + userId + " pkg=" + packageSetting);
1975                if (packageSetting == null) {
1976                    PackageManagerService.reportSettingsProblem(Log.ERROR, "Failure adding uid "
1977                            + userId + " while parsing settings at "
1978                            + parser.getPositionDescription());
1979                } else {
1980                    packageSetting.setTimeStamp(timeStamp);
1981                    packageSetting.firstInstallTime = firstInstallTime;
1982                    packageSetting.lastUpdateTime = lastUpdateTime;
1983                }
1984            } else if (sharedIdStr != null) {
1985                userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
1986                if (userId > 0) {
1987                    packageSetting = new PendingPackage(name.intern(), realName, new File(
1988                            codePathStr), new File(resourcePathStr), nativeLibraryPathStr, userId,
1989                            versionCode, pkgFlags);
1990                    packageSetting.setTimeStamp(timeStamp);
1991                    packageSetting.firstInstallTime = firstInstallTime;
1992                    packageSetting.lastUpdateTime = lastUpdateTime;
1993                    mPendingPackages.add((PendingPackage) packageSetting);
1994                    if (PackageManagerService.DEBUG_SETTINGS)
1995                        Log.i(PackageManagerService.TAG, "Reading package " + name
1996                                + ": sharedUserId=" + userId + " pkg=" + packageSetting);
1997                } else {
1998                    PackageManagerService.reportSettingsProblem(Log.WARN,
1999                            "Error in package manager settings: package " + name
2000                                    + " has bad sharedId " + sharedIdStr + " at "
2001                                    + parser.getPositionDescription());
2002                }
2003            } else {
2004                PackageManagerService.reportSettingsProblem(Log.WARN,
2005                        "Error in package manager settings: package " + name + " has bad userId "
2006                                + idStr + " at " + parser.getPositionDescription());
2007            }
2008        } catch (NumberFormatException e) {
2009            PackageManagerService.reportSettingsProblem(Log.WARN,
2010                    "Error in package manager settings: package " + name + " has bad userId "
2011                            + idStr + " at " + parser.getPositionDescription());
2012        }
2013        if (packageSetting != null) {
2014            packageSetting.uidError = "true".equals(uidError);
2015            packageSetting.installerPackageName = installerPackageName;
2016            packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
2017            // Handle legacy string here for single-user mode
2018            final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
2019            if (enabledStr != null) {
2020                try {
2021                    packageSetting.setEnabled(Integer.parseInt(enabledStr), 0 /* userId */);
2022                } catch (NumberFormatException e) {
2023                    if (enabledStr.equalsIgnoreCase("true")) {
2024                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 0);
2025                    } else if (enabledStr.equalsIgnoreCase("false")) {
2026                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0);
2027                    } else if (enabledStr.equalsIgnoreCase("default")) {
2028                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0);
2029                    } else {
2030                        PackageManagerService.reportSettingsProblem(Log.WARN,
2031                                "Error in package manager settings: package " + name
2032                                        + " has bad enabled value: " + idStr + " at "
2033                                        + parser.getPositionDescription());
2034                    }
2035                }
2036            } else {
2037                packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0);
2038            }
2039
2040            final String installStatusStr = parser.getAttributeValue(null, "installStatus");
2041            if (installStatusStr != null) {
2042                if (installStatusStr.equalsIgnoreCase("false")) {
2043                    packageSetting.installStatus = PackageSettingBase.PKG_INSTALL_INCOMPLETE;
2044                } else {
2045                    packageSetting.installStatus = PackageSettingBase.PKG_INSTALL_COMPLETE;
2046                }
2047            }
2048
2049            int outerDepth = parser.getDepth();
2050            int type;
2051            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2052                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2053                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2054                    continue;
2055                }
2056
2057                String tagName = parser.getName();
2058                // Legacy
2059                if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
2060                    readDisabledComponentsLPw(packageSetting, parser, 0);
2061                } else if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
2062                    readEnabledComponentsLPw(packageSetting, parser, 0);
2063                } else if (tagName.equals("sigs")) {
2064                    packageSetting.signatures.readXml(parser, mPastSignatures);
2065                } else if (tagName.equals("perms")) {
2066                    readGrantedPermissionsLPw(parser, packageSetting.grantedPermissions);
2067                    packageSetting.permissionsFixed = true;
2068                } else {
2069                    PackageManagerService.reportSettingsProblem(Log.WARN,
2070                            "Unknown element under <package>: " + parser.getName());
2071                    XmlUtils.skipCurrentTag(parser);
2072                }
2073            }
2074        } else {
2075            XmlUtils.skipCurrentTag(parser);
2076        }
2077    }
2078
2079    private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
2080            int userId) throws IOException, XmlPullParserException {
2081        int outerDepth = parser.getDepth();
2082        int type;
2083        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2084                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2085            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2086                continue;
2087            }
2088
2089            String tagName = parser.getName();
2090            if (tagName.equals(TAG_ITEM)) {
2091                String name = parser.getAttributeValue(null, ATTR_NAME);
2092                if (name != null) {
2093                    packageSetting.addDisabledComponent(name.intern(), userId);
2094                } else {
2095                    PackageManagerService.reportSettingsProblem(Log.WARN,
2096                            "Error in package manager settings: <disabled-components> has"
2097                                    + " no name at " + parser.getPositionDescription());
2098                }
2099            } else {
2100                PackageManagerService.reportSettingsProblem(Log.WARN,
2101                        "Unknown element under <disabled-components>: " + parser.getName());
2102            }
2103            XmlUtils.skipCurrentTag(parser);
2104        }
2105    }
2106
2107    private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
2108            int userId) throws IOException, XmlPullParserException {
2109        int outerDepth = parser.getDepth();
2110        int type;
2111        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2112                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2113            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2114                continue;
2115            }
2116
2117            String tagName = parser.getName();
2118            if (tagName.equals(TAG_ITEM)) {
2119                String name = parser.getAttributeValue(null, ATTR_NAME);
2120                if (name != null) {
2121                    packageSetting.addEnabledComponent(name.intern(), userId);
2122                } else {
2123                    PackageManagerService.reportSettingsProblem(Log.WARN,
2124                            "Error in package manager settings: <enabled-components> has"
2125                                    + " no name at " + parser.getPositionDescription());
2126                }
2127            } else {
2128                PackageManagerService.reportSettingsProblem(Log.WARN,
2129                        "Unknown element under <enabled-components>: " + parser.getName());
2130            }
2131            XmlUtils.skipCurrentTag(parser);
2132        }
2133    }
2134
2135    private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException,IOException {
2136        String name = null;
2137        String idStr = null;
2138        int pkgFlags = 0;
2139        SharedUserSetting su = null;
2140        try {
2141            name = parser.getAttributeValue(null, ATTR_NAME);
2142            idStr = parser.getAttributeValue(null, "userId");
2143            int userId = idStr != null ? Integer.parseInt(idStr) : 0;
2144            if ("true".equals(parser.getAttributeValue(null, "system"))) {
2145                pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
2146            }
2147            if (name == null) {
2148                PackageManagerService.reportSettingsProblem(Log.WARN,
2149                        "Error in package manager settings: <shared-user> has no name at "
2150                                + parser.getPositionDescription());
2151            } else if (userId == 0) {
2152                PackageManagerService.reportSettingsProblem(Log.WARN,
2153                        "Error in package manager settings: shared-user " + name
2154                                + " has bad userId " + idStr + " at "
2155                                + parser.getPositionDescription());
2156            } else {
2157                if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags)) == null) {
2158                    PackageManagerService
2159                            .reportSettingsProblem(Log.ERROR, "Occurred while parsing settings at "
2160                                    + parser.getPositionDescription());
2161                }
2162            }
2163        } catch (NumberFormatException e) {
2164            PackageManagerService.reportSettingsProblem(Log.WARN,
2165                    "Error in package manager settings: package " + name + " has bad userId "
2166                            + idStr + " at " + parser.getPositionDescription());
2167        }
2168        ;
2169
2170        if (su != null) {
2171            int outerDepth = parser.getDepth();
2172            int type;
2173            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2174                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2175                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2176                    continue;
2177                }
2178
2179                String tagName = parser.getName();
2180                if (tagName.equals("sigs")) {
2181                    su.signatures.readXml(parser, mPastSignatures);
2182                } else if (tagName.equals("perms")) {
2183                    readGrantedPermissionsLPw(parser, su.grantedPermissions);
2184                } else {
2185                    PackageManagerService.reportSettingsProblem(Log.WARN,
2186                            "Unknown element under <shared-user>: " + parser.getName());
2187                    XmlUtils.skipCurrentTag(parser);
2188                }
2189            }
2190
2191        } else {
2192            XmlUtils.skipCurrentTag(parser);
2193        }
2194    }
2195
2196    private void readGrantedPermissionsLPw(XmlPullParser parser, HashSet<String> outPerms)
2197            throws IOException, XmlPullParserException {
2198        int outerDepth = parser.getDepth();
2199        int type;
2200        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2201                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2202            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2203                continue;
2204            }
2205
2206            String tagName = parser.getName();
2207            if (tagName.equals(TAG_ITEM)) {
2208                String name = parser.getAttributeValue(null, ATTR_NAME);
2209                if (name != null) {
2210                    outPerms.add(name.intern());
2211                } else {
2212                    PackageManagerService.reportSettingsProblem(Log.WARN,
2213                            "Error in package manager settings: <perms> has" + " no name at "
2214                                    + parser.getPositionDescription());
2215                }
2216            } else {
2217                PackageManagerService.reportSettingsProblem(Log.WARN,
2218                        "Unknown element under <perms>: " + parser.getName());
2219            }
2220            XmlUtils.skipCurrentTag(parser);
2221        }
2222    }
2223
2224    private void readPreferredActivitiesLPw(XmlPullParser parser) throws XmlPullParserException,
2225            IOException {
2226        int outerDepth = parser.getDepth();
2227        int type;
2228        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2229                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2230            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2231                continue;
2232            }
2233
2234            String tagName = parser.getName();
2235            if (tagName.equals(TAG_ITEM)) {
2236                PreferredActivity pa = new PreferredActivity(parser);
2237                if (pa.mPref.getParseError() == null) {
2238                    mPreferredActivities.addFilter(pa);
2239                } else {
2240                    PackageManagerService.reportSettingsProblem(Log.WARN,
2241                            "Error in package manager settings: <preferred-activity> "
2242                                    + pa.mPref.getParseError() + " at "
2243                                    + parser.getPositionDescription());
2244                }
2245            } else {
2246                PackageManagerService.reportSettingsProblem(Log.WARN,
2247                        "Unknown element under <preferred-activities>: " + parser.getName());
2248                XmlUtils.skipCurrentTag(parser);
2249            }
2250        }
2251    }
2252
2253    void removeUserLPr(int userId) {
2254        File file = getUserPackagesStateFile(userId);
2255        file.delete();
2256        file = getUserPackagesStateBackupFile(userId);
2257        file.delete();
2258    }
2259
2260    // Returns -1 if we could not find an available UserId to assign
2261    private int newUserIdLPw(Object obj) {
2262        // Let's be stupidly inefficient for now...
2263        final int N = mUserIds.size();
2264        for (int i = 0; i < N; i++) {
2265            if (mUserIds.get(i) == null) {
2266                mUserIds.set(i, obj);
2267                return Process.FIRST_APPLICATION_UID + i;
2268            }
2269        }
2270
2271        // None left?
2272        if (N > (Process.LAST_APPLICATION_UID-Process.FIRST_APPLICATION_UID)) {
2273            return -1;
2274        }
2275
2276        mUserIds.add(obj);
2277        return Process.FIRST_APPLICATION_UID + N;
2278    }
2279
2280    public VerifierDeviceIdentity getVerifierDeviceIdentityLPw() {
2281        if (mVerifierDeviceIdentity == null) {
2282            mVerifierDeviceIdentity = VerifierDeviceIdentity.generate();
2283
2284            writeLPr();
2285        }
2286
2287        return mVerifierDeviceIdentity;
2288    }
2289
2290    public PackageSetting getDisabledSystemPkgLPr(String name) {
2291        PackageSetting ps = mDisabledSysPackages.get(name);
2292        return ps;
2293    }
2294
2295    boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
2296        if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
2297            return true;
2298        }
2299        final String pkgName = componentInfo.packageName;
2300        final PackageSetting packageSettings = mPackages.get(pkgName);
2301        if (PackageManagerService.DEBUG_SETTINGS) {
2302            Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
2303                    + componentInfo.packageName + " componentName = " + componentInfo.name);
2304            Log.v(PackageManagerService.TAG, "enabledComponents: "
2305                    + Arrays.toString(packageSettings.getEnabledComponents(userId).toArray()));
2306            Log.v(PackageManagerService.TAG, "disabledComponents: "
2307                    + Arrays.toString(packageSettings.getDisabledComponents(userId).toArray()));
2308        }
2309        if (packageSettings == null) {
2310            return false;
2311        }
2312        final int enabled = packageSettings.getEnabled(userId);
2313        if (enabled == COMPONENT_ENABLED_STATE_DISABLED
2314                || enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
2315                || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
2316                    && enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
2317            return false;
2318        }
2319        if (packageSettings.getEnabledComponents(userId).contains(componentInfo.name)) {
2320            return true;
2321        }
2322        if (packageSettings.getDisabledComponents(userId).contains(componentInfo.name)) {
2323            return false;
2324        }
2325        return componentInfo.enabled;
2326    }
2327
2328    String getInstallerPackageNameLPr(String packageName) {
2329        final PackageSetting pkg = mPackages.get(packageName);
2330        if (pkg == null) {
2331            throw new IllegalArgumentException("Unknown package: " + packageName);
2332        }
2333        return pkg.installerPackageName;
2334    }
2335
2336    int getApplicationEnabledSettingLPr(String packageName, int userId) {
2337        final PackageSetting pkg = mPackages.get(packageName);
2338        if (pkg == null) {
2339            throw new IllegalArgumentException("Unknown package: " + packageName);
2340        }
2341        return pkg.getEnabled(userId);
2342    }
2343
2344    int getComponentEnabledSettingLPr(ComponentName componentName, int userId) {
2345        final String packageName = componentName.getPackageName();
2346        final PackageSetting pkg = mPackages.get(packageName);
2347        if (pkg == null) {
2348            throw new IllegalArgumentException("Unknown component: " + componentName);
2349        }
2350        final String classNameStr = componentName.getClassName();
2351        return pkg.getCurrentEnabledStateLPr(classNameStr, userId);
2352    }
2353
2354    boolean setPackageStoppedStateLPw(String packageName, boolean stopped,
2355            boolean allowedByPermission, int uid, int userId) {
2356        int appId = UserId.getAppId(uid);
2357        final PackageSetting pkgSetting = mPackages.get(packageName);
2358        if (pkgSetting == null) {
2359            throw new IllegalArgumentException("Unknown package: " + packageName);
2360        }
2361        if (!allowedByPermission && (appId != pkgSetting.appId)) {
2362            throw new SecurityException(
2363                    "Permission Denial: attempt to change stopped state from pid="
2364                    + Binder.getCallingPid()
2365                    + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
2366        }
2367        if (DEBUG_STOPPED) {
2368            if (stopped) {
2369                RuntimeException e = new RuntimeException("here");
2370                e.fillInStackTrace();
2371                Slog.i(TAG, "Stopping package " + packageName, e);
2372            }
2373        }
2374        if (pkgSetting.getStopped(userId) != stopped) {
2375            pkgSetting.setStopped(stopped, userId);
2376            // pkgSetting.pkg.mSetStopped = stopped;
2377            if (pkgSetting.getNotLaunched(userId)) {
2378                if (pkgSetting.installerPackageName != null) {
2379                    PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
2380                            pkgSetting.name, null,
2381                            pkgSetting.installerPackageName, null, userId);
2382                }
2383                pkgSetting.setNotLaunched(false, userId);
2384            }
2385            return true;
2386        }
2387        return false;
2388    }
2389
2390    private List<UserInfo> getAllUsers() {
2391        long id = Binder.clearCallingIdentity();
2392        try {
2393            return UserManagerService.getInstance(mContext).getUsers();
2394        } catch (NullPointerException npe) {
2395            // packagemanager not yet initialized
2396        } finally {
2397            Binder.restoreCallingIdentity(id);
2398        }
2399        return null;
2400    }
2401
2402    static final void printFlags(PrintWriter pw, int val, Object[] spec) {
2403        pw.print("[ ");
2404        for (int i=0; i<spec.length; i+=2) {
2405            int mask = (Integer)spec[i];
2406            if ((val & mask) != 0) {
2407                pw.print(spec[i+1]);
2408                pw.print(" ");
2409            }
2410        }
2411        pw.print("]");
2412    }
2413
2414    static final Object[] FLAG_DUMP_SPEC = new Object[] {
2415        ApplicationInfo.FLAG_SYSTEM, "SYSTEM",
2416        ApplicationInfo.FLAG_DEBUGGABLE, "DEBUGGABLE",
2417        ApplicationInfo.FLAG_HAS_CODE, "HAS_CODE",
2418        ApplicationInfo.FLAG_PERSISTENT, "PERSISTENT",
2419        ApplicationInfo.FLAG_FACTORY_TEST, "FACTORY_TEST",
2420        ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING, "ALLOW_TASK_REPARENTING",
2421        ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA, "ALLOW_CLEAR_USER_DATA",
2422        ApplicationInfo.FLAG_UPDATED_SYSTEM_APP, "UPDATED_SYSTEM_APP",
2423        ApplicationInfo.FLAG_TEST_ONLY, "TEST_ONLY",
2424        ApplicationInfo.FLAG_VM_SAFE_MODE, "VM_SAFE_MODE",
2425        ApplicationInfo.FLAG_ALLOW_BACKUP, "ALLOW_BACKUP",
2426        ApplicationInfo.FLAG_KILL_AFTER_RESTORE, "KILL_AFTER_RESTORE",
2427        ApplicationInfo.FLAG_RESTORE_ANY_VERSION, "RESTORE_ANY_VERSION",
2428        ApplicationInfo.FLAG_EXTERNAL_STORAGE, "EXTERNAL_STORAGE",
2429        ApplicationInfo.FLAG_LARGE_HEAP, "LARGE_HEAP",
2430        ApplicationInfo.FLAG_STOPPED, "STOPPED",
2431        ApplicationInfo.FLAG_FORWARD_LOCK, "FORWARD_LOCK",
2432        ApplicationInfo.FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
2433    };
2434
2435    void dumpPackagesLPr(PrintWriter pw, String packageName, DumpState dumpState) {
2436        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2437        final Date date = new Date();
2438        boolean printedSomething = false;
2439        List<UserInfo> users = getAllUsers();
2440        for (final PackageSetting ps : mPackages.values()) {
2441            if (packageName != null && !packageName.equals(ps.realName)
2442                    && !packageName.equals(ps.name)) {
2443                continue;
2444            }
2445
2446            if (packageName != null) {
2447                dumpState.setSharedUser(ps.sharedUser);
2448            }
2449
2450            if (!printedSomething) {
2451                if (dumpState.onTitlePrinted())
2452                    pw.println(" ");
2453                pw.println("Packages:");
2454                printedSomething = true;
2455            }
2456            pw.print("  Package [");
2457                pw.print(ps.realName != null ? ps.realName : ps.name);
2458                pw.print("] (");
2459                pw.print(Integer.toHexString(System.identityHashCode(ps)));
2460                pw.println("):");
2461
2462            if (ps.realName != null) {
2463                pw.print("    compat name=");
2464                pw.println(ps.name);
2465            }
2466
2467            pw.print("    userId="); pw.print(ps.appId);
2468            pw.print(" gids="); pw.println(PackageManagerService.arrayToString(ps.gids));
2469            pw.print("    sharedUser="); pw.println(ps.sharedUser);
2470            pw.print("    pkg="); pw.println(ps.pkg);
2471            pw.print("    codePath="); pw.println(ps.codePathString);
2472            pw.print("    resourcePath="); pw.println(ps.resourcePathString);
2473            pw.print("    nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
2474            pw.print("    versionCode="); pw.println(ps.versionCode);
2475            if (ps.pkg != null) {
2476                pw.print("    applicationInfo="); pw.println(ps.pkg.applicationInfo.toString());
2477                pw.print("    flags="); printFlags(pw, ps.pkg.applicationInfo.flags, FLAG_DUMP_SPEC); pw.println();
2478                pw.print("    versionName="); pw.println(ps.pkg.mVersionName);
2479                pw.print("    dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
2480                pw.print("    targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
2481                if (ps.pkg.mOperationPending) {
2482                    pw.println("    mOperationPending=true");
2483                }
2484                pw.print("    supportsScreens=[");
2485                boolean first = true;
2486                if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
2487                    if (!first)
2488                        pw.print(", ");
2489                    first = false;
2490                    pw.print("small");
2491                }
2492                if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
2493                    if (!first)
2494                        pw.print(", ");
2495                    first = false;
2496                    pw.print("medium");
2497                }
2498                if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
2499                    if (!first)
2500                        pw.print(", ");
2501                    first = false;
2502                    pw.print("large");
2503                }
2504                if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
2505                    if (!first)
2506                        pw.print(", ");
2507                    first = false;
2508                    pw.print("xlarge");
2509                }
2510                if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
2511                    if (!first)
2512                        pw.print(", ");
2513                    first = false;
2514                    pw.print("resizeable");
2515                }
2516                if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
2517                    if (!first)
2518                        pw.print(", ");
2519                    first = false;
2520                    pw.print("anyDensity");
2521                }
2522            }
2523            pw.println("]");
2524            pw.print("    timeStamp=");
2525                date.setTime(ps.timeStamp);
2526                pw.println(sdf.format(date));
2527            pw.print("    firstInstallTime=");
2528                date.setTime(ps.firstInstallTime);
2529                pw.println(sdf.format(date));
2530            pw.print("    lastUpdateTime=");
2531                date.setTime(ps.lastUpdateTime);
2532                pw.println(sdf.format(date));
2533            if (ps.installerPackageName != null) {
2534                pw.print("    installerPackageName="); pw.println(ps.installerPackageName);
2535            }
2536            pw.print("    signatures="); pw.println(ps.signatures);
2537            pw.print("    permissionsFixed="); pw.print(ps.permissionsFixed);
2538            pw.print(" haveGids="); pw.println(ps.haveGids);
2539            pw.print("    pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
2540            pw.print(" installStatus="); pw.print(ps.installStatus);
2541            for (UserInfo user : users) {
2542                pw.print(" User "); pw.print(user.id); pw.print(": ");
2543                pw.print(" stopped=");
2544                pw.print(ps.getStopped(user.id));
2545                pw.print(" enabled=");
2546                pw.println(ps.getEnabled(user.id));
2547                if (ps.getDisabledComponents(user.id).size() > 0) {
2548                    pw.println("    disabledComponents:");
2549                    for (String s : ps.getDisabledComponents(user.id)) {
2550                        pw.print("      "); pw.println(s);
2551                    }
2552                }
2553                if (ps.getEnabledComponents(user.id).size() > 0) {
2554                    pw.println("    enabledComponents:");
2555                    for (String s : ps.getEnabledComponents(user.id)) {
2556                        pw.print("      "); pw.println(s);
2557                    }
2558                }
2559            }
2560            if (ps.grantedPermissions.size() > 0) {
2561                pw.println("    grantedPermissions:");
2562                for (String s : ps.grantedPermissions) {
2563                    pw.print("      "); pw.println(s);
2564                }
2565            }
2566        }
2567
2568        printedSomething = false;
2569        if (mRenamedPackages.size() > 0) {
2570            for (final Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
2571                if (packageName != null && !packageName.equals(e.getKey())
2572                        && !packageName.equals(e.getValue())) {
2573                    continue;
2574                }
2575                if (!printedSomething) {
2576                    if (dumpState.onTitlePrinted())
2577                        pw.println(" ");
2578                    pw.println("Renamed packages:");
2579                    printedSomething = true;
2580                }
2581                pw.print("  ");
2582                pw.print(e.getKey());
2583                pw.print(" -> ");
2584                pw.println(e.getValue());
2585            }
2586        }
2587
2588        printedSomething = false;
2589        if (mDisabledSysPackages.size() > 0) {
2590            for (final PackageSetting ps : mDisabledSysPackages.values()) {
2591                if (packageName != null && !packageName.equals(ps.realName)
2592                        && !packageName.equals(ps.name)) {
2593                    continue;
2594                }
2595                if (!printedSomething) {
2596                    if (dumpState.onTitlePrinted())
2597                        pw.println(" ");
2598                    pw.println("Hidden system packages:");
2599                    printedSomething = true;
2600                }
2601                pw.print("  Package [");
2602                pw.print(ps.realName != null ? ps.realName : ps.name);
2603                pw.print("] (");
2604                pw.print(Integer.toHexString(System.identityHashCode(ps)));
2605                pw.println("):");
2606                if (ps.realName != null) {
2607                    pw.print("    compat name=");
2608                    pw.println(ps.name);
2609                }
2610                if (ps.pkg != null && ps.pkg.applicationInfo != null) {
2611                    pw.print("    applicationInfo=");
2612                    pw.println(ps.pkg.applicationInfo.toString());
2613                }
2614                pw.print("    userId=");
2615                pw.println(ps.appId);
2616                pw.print("    sharedUser=");
2617                pw.println(ps.sharedUser);
2618                pw.print("    codePath=");
2619                pw.println(ps.codePathString);
2620                pw.print("    resourcePath=");
2621                pw.println(ps.resourcePathString);
2622            }
2623        }
2624    }
2625
2626    void dumpPermissionsLPr(PrintWriter pw, String packageName, DumpState dumpState) {
2627        boolean printedSomething = false;
2628        for (BasePermission p : mPermissions.values()) {
2629            if (packageName != null && !packageName.equals(p.sourcePackage)) {
2630                continue;
2631            }
2632            if (!printedSomething) {
2633                if (dumpState.onTitlePrinted())
2634                    pw.println(" ");
2635                pw.println("Permissions:");
2636                printedSomething = true;
2637            }
2638            pw.print("  Permission ["); pw.print(p.name); pw.print("] (");
2639                    pw.print(Integer.toHexString(System.identityHashCode(p)));
2640                    pw.println("):");
2641            pw.print("    sourcePackage="); pw.println(p.sourcePackage);
2642            pw.print("    uid="); pw.print(p.uid);
2643                    pw.print(" gids="); pw.print(PackageManagerService.arrayToString(p.gids));
2644                    pw.print(" type="); pw.print(p.type);
2645                    pw.print(" prot=");
2646                    pw.println(PermissionInfo.protectionToString(p.protectionLevel));
2647            if (p.packageSetting != null) {
2648                pw.print("    packageSetting="); pw.println(p.packageSetting);
2649            }
2650            if (p.perm != null) {
2651                pw.print("    perm="); pw.println(p.perm);
2652            }
2653            if (READ_EXTERNAL_STORAGE.equals(p.name)) {
2654                pw.print("    enforced=");
2655                pw.println(mReadExternalStorageEnforced);
2656            }
2657        }
2658    }
2659
2660    void dumpSharedUsersLPr(PrintWriter pw, String packageName, DumpState dumpState) {
2661        boolean printedSomething = false;
2662        for (SharedUserSetting su : mSharedUsers.values()) {
2663            if (packageName != null && su != dumpState.getSharedUser()) {
2664                continue;
2665            }
2666            if (!printedSomething) {
2667                if (dumpState.onTitlePrinted())
2668                    pw.println(" ");
2669                pw.println("Shared users:");
2670                printedSomething = true;
2671            }
2672            pw.print("  SharedUser [");
2673            pw.print(su.name);
2674            pw.print("] (");
2675            pw.print(Integer.toHexString(System.identityHashCode(su)));
2676                    pw.println("):");
2677            pw.print("    userId=");
2678            pw.print(su.userId);
2679            pw.print(" gids=");
2680            pw.println(PackageManagerService.arrayToString(su.gids));
2681            pw.println("    grantedPermissions:");
2682            for (String s : su.grantedPermissions) {
2683                pw.print("      ");
2684                pw.println(s);
2685            }
2686        }
2687    }
2688
2689    void dumpReadMessagesLPr(PrintWriter pw, DumpState dumpState) {
2690        pw.println("Settings parse messages:");
2691        pw.print(mReadMessages.toString());
2692    }
2693}
2694