FileDocCategorySizeDatePackage
PackageManagerService.javaAPI DocAndroid 1.5 API285149Wed May 06 22:42:00 BST 2009com.android.server

PackageManagerService

public class PackageManagerService extends IPackageManager.Stub

Fields Summary
private static final String
TAG
private static final boolean
DEBUG_SETTINGS
private static final boolean
DEBUG_PREFERRED
private static final boolean
MULTIPLE_APPLICATION_UIDS
private static final int
RADIO_UID
private static final int
FIRST_APPLICATION_UID
private static final int
MAX_APPLICATION_UIDS
private static final boolean
SHOW_INFO
private static final boolean
GET_CERTIFICATES
private static final int
REMOVE_EVENTS
private static final int
ADD_EVENTS
private static final int
OBSERVER_EVENTS
static final int
SCAN_MONITOR
static final int
SCAN_NO_DEX
static final int
SCAN_FORCE_DEX
static final int
SCAN_UPDATE_SIGNATURE
static final int
SCAN_FORWARD_LOCKED
static final int
SCAN_NEW_INSTALL
static final int
LOG_BOOT_PROGRESS_PMS_START
static final int
LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
static final int
LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START
static final int
LOG_BOOT_PROGRESS_PMS_SCAN_END
static final int
LOG_BOOT_PROGRESS_PMS_READY
final android.os.HandlerThread
mHandlerThread
final android.os.Handler
mHandler
final int
mSdkVersion
final android.content.Context
mContext
final boolean
mFactoryTest
final DisplayMetrics
mMetrics
final int
mDefParseFlags
final String[]
mSeparateProcesses
final File
mAppDataDir
final android.os.FileObserver
mFrameworkInstallObserver
final android.os.FileObserver
mSystemInstallObserver
final android.os.FileObserver
mAppInstallObserver
final android.os.FileObserver
mDrmAppInstallObserver
final Installer
mInstaller
final File
mFrameworkDir
final File
mSystemAppDir
final File
mAppInstallDir
final File
mDrmAppPrivateInstallDir
final Object
mInstallLock
final HashMap
mAppDirs
File
mScanningPath
int
mLastScanError
final int[]
mOutPermissions
final HashMap
mPackages
final Settings
mSettings
boolean
mRestoredSettings
boolean
mReportedUidError
int[]
mGlobalGids
final SparseArray
mSystemPermissions
final HashMap
mSharedLibraries
final ActivityIntentResolver
mActivities
final ActivityIntentResolver
mReceivers
final ServiceIntentResolver
mServices
final HashMap
mProvidersByComponent
final HashMap
mProviders
final HashMap
mInstrumentation
final HashMap
mPermissionGroups
boolean
mSystemReady
boolean
mSafeMode
boolean
mHasSystemUidErrors
android.content.pm.ApplicationInfo
mAndroidApplication
final android.content.pm.ActivityInfo
mResolveActivity
final android.content.pm.ResolveInfo
mResolveInfo
android.content.ComponentName
mResolveComponentName
PackageParser.Package
mPlatformPackage
private static final Comparator
mResolvePrioritySorter
private static final Comparator
mProviderInitOrderSorter
Constructors Summary
public PackageManagerService(android.content.Context context, boolean factoryTest)

        EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());
        
        if (mSdkVersion <= 0) {
            Log.w(TAG, "**** ro.build.version.sdk not set!");
        }
        
        mContext = context;
        mFactoryTest = factoryTest;
        mMetrics = new DisplayMetrics();
        mSettings = new Settings();
        mSettings.addSharedUserLP("android.uid.system",
                Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
        mSettings.addSharedUserLP("android.uid.phone",
                MULTIPLE_APPLICATION_UIDS
                        ? RADIO_UID : FIRST_APPLICATION_UID,
                ApplicationInfo.FLAG_SYSTEM);

        String separateProcesses = SystemProperties.get("debug.separate_processes");
        if (separateProcesses != null && separateProcesses.length() > 0) {
            if ("*".equals(separateProcesses)) {
                mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
                mSeparateProcesses = null;
                Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
            } else {
                mDefParseFlags = 0;
                mSeparateProcesses = separateProcesses.split(",");
                Log.w(TAG, "Running with debug.separate_processes: "
                        + separateProcesses);
            }
        } else {
            mDefParseFlags = 0;
            mSeparateProcesses = null;
        }
        
        Installer installer = new Installer();
        // Little hacky thing to check if installd is here, to determine
        // whether we are running on the simulator and thus need to take
        // care of building the /data file structure ourself.
        // (apparently the sim now has a working installer)
        if (installer.ping() && Process.supportsProcesses()) {
            mInstaller = installer;
        } else {
            mInstaller = null;
        }

        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        Display d = wm.getDefaultDisplay();
        d.getMetrics(mMetrics);

        synchronized (mInstallLock) {
        synchronized (mPackages) {
            mHandlerThread.start();
            mHandler = new Handler(mHandlerThread.getLooper());
            
            File dataDir = Environment.getDataDirectory();
            mAppDataDir = new File(dataDir, "data");
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");

            if (mInstaller == null) {
                // Make sure these dirs exist, when we are running in
                // the simulator.
                // Make a wide-open directory for random misc stuff.
                File miscDir = new File(dataDir, "misc");
                miscDir.mkdirs();
                mAppDataDir.mkdirs();
                mDrmAppPrivateInstallDir.mkdirs();
            }

            readPermissions();

            mRestoredSettings = mSettings.readLP();
            long startTime = SystemClock.uptimeMillis();
            
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);
            
            int scanMode = SCAN_MONITOR;
            
            final HashSet<String> libFiles = new HashSet<String>();
            
            mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
            
            if (mInstaller != null) {
                /**
                 * Out of paranoia, ensure that everything in the boot class
                 * path has been dexed.
                 */
                String bootClassPath = System.getProperty("java.boot.class.path");
                if (bootClassPath != null) {
                    String[] paths = splitString(bootClassPath, ':");
                    for (int i=0; i<paths.length; i++) {
                        try {
                            if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
                                libFiles.add(paths[i]);
                                mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
                            }
                        } catch (FileNotFoundException e) {
                            Log.w(TAG, "Boot class path not found: " + paths[i]);
                        } catch (IOException e) {
                            Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
                        }
                    }
                } else {
                    Log.w(TAG, "No BOOTCLASSPATH found!");
                }
                
                /**
                 * Also ensure all external libraries have had dexopt run on them.
                 */
                if (mSharedLibraries.size() > 0) {
                    Iterator<String> libs = mSharedLibraries.values().iterator();
                    while (libs.hasNext()) {
                        String lib = libs.next();
                        try {
                            if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
                                libFiles.add(lib);
                                mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
                            }
                        } catch (FileNotFoundException e) {
                            Log.w(TAG, "Library not found: " + lib);
                        } catch (IOException e) {
                            Log.w(TAG, "Exception reading library: " + lib, e);
                        }
                    }
                }
                
                // Gross hack for now: we know this file doesn't contain any
                // code, so don't dexopt it to avoid the resulting log spew.
                libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
                
                /**
                 * And there are a number of commands implemented in Java, which
                 * we currently need to do the dexopt on so that they can be
                 * run from a non-root shell.
                 */
                String[] frameworkFiles = mFrameworkDir.list();
                if (frameworkFiles != null && mInstaller != null) {
                    for (int i=0; i<frameworkFiles.length; i++) {
                        File libPath = new File(mFrameworkDir, frameworkFiles[i]);
                        String path = libPath.getPath();
                        // Skip the file if we alrady did it.
                        if (libFiles.contains(path)) {
                            continue;
                        }
                        // Skip the file if it is not a type we want to dexopt.
                        if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
                            continue;
                        }
                        try {
                            if (dalvik.system.DexFile.isDexOptNeeded(path)) {
                                mInstaller.dexopt(path, Process.SYSTEM_UID, true);
                            }
                        } catch (FileNotFoundException e) {
                            Log.w(TAG, "Jar not found: " + path);
                        } catch (IOException e) {
                            Log.w(TAG, "Exception reading jar: " + path, e);
                        }
                    }
                }
            }
            
            mFrameworkInstallObserver = new AppDirObserver(
                mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
            mFrameworkInstallObserver.startWatching();
            scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
                    scanMode | SCAN_NO_DEX);
            mSystemAppDir = new File(Environment.getRootDirectory(), "app");
            mSystemInstallObserver = new AppDirObserver(
                mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
            mSystemInstallObserver.startWatching();
            scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
            mAppInstallDir = new File(dataDir, "app");
            if (mInstaller == null) {
                // Make sure these dirs exist, when we are running in
                // the simulator.
                mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
            }
            //look for any incomplete package installations
            ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
            //clean up list
            for(int i = 0; i < deletePkgsList.size(); i++) {
                //clean up here
                cleanupInstallFailedPackage(deletePkgsList.get(i));
            }
            //delete tmp files
            deleteTempPackageFiles();
            
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START,
                    SystemClock.uptimeMillis());
            mAppInstallObserver = new AppDirObserver(
                mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
            mAppInstallObserver.startWatching();
            scanDirLI(mAppInstallDir, 0, scanMode);

            mDrmAppInstallObserver = new AppDirObserver(
                mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
            mDrmAppInstallObserver.startWatching();
            scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode);

            EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
                    SystemClock.uptimeMillis());
            Log.i(TAG, "Time to scan packages: "
                    + ((SystemClock.uptimeMillis()-startTime)/1000f)
                    + " seconds");

            updatePermissionsLP();

            mSettings.writeLP();

            EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());
            
            // Now after opening every single application zip, make sure they
            // are all flushed.  Not really needed, but keeps things nice and
            // tidy.
            Runtime.getRuntime().gc();
        } // synchronized (mPackages)
        } // synchronized (mInstallLock)
    
Methods Summary
public voidaddPackageToPreferred(java.lang.String packageName)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);

        synchronized (mPackages) {
            PackageParser.Package p = mPackages.get(packageName);
            if (p == null) {
                return;
            }
            PackageSetting ps = (PackageSetting)p.mExtras;
            if (ps != null) {
                mSettings.mPreferredPackages.remove(ps);
                mSettings.mPreferredPackages.add(0, ps);
                updatePreferredIndicesLP();
                mSettings.writeLP();
            }
        }
    
public booleanaddPermission(android.content.pm.PermissionInfo info)

        synchronized (mPackages) {
            if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
                throw new SecurityException("Label must be specified in permission");
            }
            BasePermission tree = checkPermissionTreeLP(info.name);
            BasePermission bp = mSettings.mPermissions.get(info.name);
            boolean added = bp == null;
            if (added) {
                bp = new BasePermission(info.name, tree.sourcePackage,
                        BasePermission.TYPE_DYNAMIC);
            } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
                throw new SecurityException(
                        "Not allowed to modify non-dynamic permission "
                        + info.name);
            }
            bp.perm = new PackageParser.Permission(tree.perm.owner,
                    new PermissionInfo(info));
            bp.perm.info.packageName = tree.perm.info.packageName;
            bp.uid = tree.uid;
            if (added) {
                mSettings.mPermissions.put(info.name, bp);
            }
            mSettings.writeLP();
            return added;
        }
    
public voidaddPreferredActivity(android.content.IntentFilter filter, int match, android.content.ComponentName[] set, android.content.ComponentName activity)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);

        synchronized (mPackages) {
            Log.i(TAG, "Adding preferred activity " + activity + ":");
            filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
            mSettings.mPreferredActivities.addFilter(
                    new PreferredActivity(filter, match, set, activity));
            mSettings.writeLP();
        }
    
static int[]appendInt(int[] cur, int val)

        if (cur == null) {
            return new int[] { val };
        }
        final int N = cur.length;
        for (int i=0; i<N; i++) {
            if (cur[i] == val) {
                return cur;
            }
        }
        int[] ret = new int[N+1];
        System.arraycopy(cur, 0, ret, 0, N);
        ret[N] = val;
        return ret;
    
static int[]appendInts(int[] cur, int[] add)

        if (add == null) return cur;
        if (cur == null) return add;
        final int N = add.length;
        for (int i=0; i<N; i++) {
            cur = appendInt(cur, add[i]);
        }
        return cur;
    
static java.lang.StringarrayToString(int[] array)

        StringBuffer buf = new StringBuffer(128);
        buf.append('[");
        if (array != null) {
            for (int i=0; i<array.length; i++) {
                if (i > 0) buf.append(", ");
                buf.append(array[i]);
            }
        }
        buf.append(']");
        return buf.toString();
    
private voidcachePackageSharedLibsLI(PackageParser.Package pkg, java.io.File dataPath, java.io.File scanFile)

        File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
        final String sharedLibraryABI = "armeabi";
        final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
        final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
        final String sharedLibrarySuffix = ".so";
        boolean createdSharedLib = false;
        try {
            ZipFile zipFile = new ZipFile(scanFile);
            Enumeration<ZipEntry> entries =
                (Enumeration<ZipEntry>) zipFile.entries();

            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                if (entry.isDirectory()) {
                    continue;
                }
                String entryName = entry.getName();
                if (! (entryName.startsWith(apkSharedLibraryPrefix)
                        && entryName.endsWith(sharedLibrarySuffix))) {
                    continue;
                }
                String libFileName = entryName.substring(
                        apkLibraryDirectory.length());
                if (libFileName.contains("/")
                        || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
                    continue;
                }
                String sharedLibraryFilePath = sharedLibraryDir.getPath() +
                    File.separator + libFileName;
                File sharedLibraryFile = new File(sharedLibraryFilePath);
                if (! sharedLibraryFile.exists() ||
                    sharedLibraryFile.length() != entry.getSize() ||
                    sharedLibraryFile.lastModified() != entry.getTime()) {
                    if (Config.LOGD) {
                        Log.d(TAG, "Caching shared lib " + entry.getName());
                    }
                    if (mInstaller == null) {
                        sharedLibraryDir.mkdir();
                        createdSharedLib = true;
                    }
                    cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
                            sharedLibraryFile);
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Failed to cache package shared libs", e);
            if(createdSharedLib) {
                sharedLibraryDir.delete();
            }
            throw e;
        }
    
private voidcacheSharedLibLI(PackageParser.Package pkg, java.util.zip.ZipFile zipFile, java.util.zip.ZipEntry entry, java.io.File sharedLibraryDir, java.io.File sharedLibraryFile)

        InputStream inputStream = zipFile.getInputStream(entry);
        try {
            File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
            String tempFilePath = tempFile.getPath();
            // XXX package manager can't change owner, so the lib files for
            // now need to be left as world readable and owned by the system.
            if (! FileUtils.copyToFile(inputStream, tempFile) ||
                ! tempFile.setLastModified(entry.getTime()) ||
                FileUtils.setPermissions(tempFilePath,
                        FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
                        |FileUtils.S_IROTH, -1, -1) != 0 ||
                ! tempFile.renameTo(sharedLibraryFile)) {
                // Failed to properly write file.
                tempFile.delete();
                throw new IOException("Couldn't create cached shared lib "
                        + sharedLibraryFile + " in " + sharedLibraryDir);
            }
        } finally {
            inputStream.close();
        }
    
public intcheckPermission(java.lang.String permName, java.lang.String pkgName)

        synchronized (mPackages) {
            PackageParser.Package p = mPackages.get(pkgName);
            if (p != null && p.mExtras != null) {
                PackageSetting ps = (PackageSetting)p.mExtras;
                if (ps.sharedUser != null) {
                    if (ps.sharedUser.grantedPermissions.contains(permName)) {
                        return PackageManager.PERMISSION_GRANTED;
                    }
                } else if (ps.grantedPermissions.contains(permName)) {
                    return PackageManager.PERMISSION_GRANTED;
                }
            }
        }
        return PackageManager.PERMISSION_DENIED;
    
private com.android.server.PackageManagerService$BasePermissioncheckPermissionTreeLP(java.lang.String permName)

        if (permName != null) {
            BasePermission bp = findPermissionTreeLP(permName);
            if (bp != null) {
                if (bp.uid == Binder.getCallingUid()) {
                    return bp;
                }
                throw new SecurityException("Calling uid "
                        + Binder.getCallingUid()
                        + " is not allowed to add to permission tree "
                        + bp.name + " owned by uid " + bp.uid);
            }
        }
        throw new SecurityException("No permission tree found for " + permName);
    
public intcheckSignatures(java.lang.String pkg1, java.lang.String pkg2)

        synchronized (mPackages) {
            PackageParser.Package p1 = mPackages.get(pkg1);
            PackageParser.Package p2 = mPackages.get(pkg2);
            if (p1 == null || p1.mExtras == null
                    || p2 == null || p2.mExtras == null) {
                return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
            }
            return checkSignaturesLP(p1, p2);
        }
    
intcheckSignaturesLP(PackageParser.Package p1, PackageParser.Package p2)

        if (p1.mSignatures == null) {
            return p2.mSignatures == null
                    ? PackageManager.SIGNATURE_NEITHER_SIGNED
                    : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
        }
        if (p2.mSignatures == null) {
            return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
        }
        final int N1 = p1.mSignatures.length;
        final int N2 = p2.mSignatures.length;
        for (int i=0; i<N1; i++) {
            boolean match = false;
            for (int j=0; j<N2; j++) {
                if (p1.mSignatures[i].equals(p2.mSignatures[j])) {
                    match = true;
                    break;
                }
            }
            if (!match) {
                return PackageManager.SIGNATURE_NO_MATCH;
            }
        }
        return PackageManager.SIGNATURE_MATCH;
    
public intcheckUidPermission(java.lang.String permName, int uid)

        synchronized (mPackages) {
            Object obj = mSettings.getUserIdLP(uid);
            if (obj != null) {
                if (obj instanceof SharedUserSetting) {
                    SharedUserSetting sus = (SharedUserSetting)obj;
                    if (sus.grantedPermissions.contains(permName)) {
                        return PackageManager.PERMISSION_GRANTED;
                    }
                } else if (obj instanceof PackageSetting) {
                    PackageSetting ps = (PackageSetting)obj;
                    if (ps.grantedPermissions.contains(permName)) {
                        return PackageManager.PERMISSION_GRANTED;
                    }
                }
            } else {
                HashSet<String> perms = mSystemPermissions.get(uid);
                if (perms != null && perms.contains(permName)) {
                    return PackageManager.PERMISSION_GRANTED;
                }
            }
        }
        return PackageManager.PERMISSION_DENIED;
    
voidcleanupInstallFailedPackage(java.lang.String packageName)

        if (mInstaller != null) {
            int retCode = mInstaller.remove(packageName);
            if (retCode < 0) {
                Log.w(TAG, "Couldn't remove app data directory for package: "
                           + packageName + ", retcode=" + retCode);
            }
        } else {
            //for emulator
            PackageParser.Package pkg = mPackages.get(packageName);
            File dataDir = new File(pkg.applicationInfo.dataDir);
            dataDir.delete();
        }
        mSettings.removePackageLP(packageName);
    
public voidclearApplicationUserData(java.lang.String packageName, android.content.pm.IPackageDataObserver observer)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.CLEAR_APP_USER_DATA, null);
        // Queue up an async operation since the package deletion may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                final boolean succeeded;
                synchronized (mInstallLock) {
                    succeeded = clearApplicationUserDataLI(packageName);
                }
                if (succeeded) {
                    // invoke DeviceStorageMonitor's update method to clear any notifications
                    DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
                            ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
                    if (dsm != null) {
                        dsm.updateMemory();
                    }
                }
                if(observer != null) {
                    try {
                        observer.onRemoveCompleted(packageName, succeeded);
                    } catch (RemoteException e) {
                        Log.i(TAG, "Observer no longer exists.");
                    }
                } //end if observer
            } //end run
        });
    
private booleanclearApplicationUserDataLI(java.lang.String packageName)

        if (packageName == null) {
            Log.w(TAG, "Attempt to delete null packageName.");
            return false;
        }
        PackageParser.Package p;
        boolean dataOnly = false;
        synchronized (mPackages) {
            p = mPackages.get(packageName);
            if(p == null) {
                dataOnly = true;
                PackageSetting ps = mSettings.mPackages.get(packageName);
                if((ps == null) || (ps.pkg == null)) {
                    Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
                    return false;
                }
                p = ps.pkg;
            }
        }
        if(!dataOnly) {
            //need to check this only for fully installed applications
            if (p == null) {
                Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
                return false;
            }
            final ApplicationInfo applicationInfo = p.applicationInfo;
            if (applicationInfo == null) {
                Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
                return false;
            }
        }
        if (mInstaller != null) {
            int retCode = mInstaller.clearUserData(packageName);
            if (retCode < 0) {
                Log.w(TAG, "Couldn't remove cache files for package: "
                        + packageName);
                return false;
            }
        }
        return true;
    
public voidclearPackagePreferredActivities(java.lang.String packageName)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);

        synchronized (mPackages) {
            if (clearPackagePreferredActivitiesLP(packageName)) {
                mSettings.writeLP();
            }
        }
    
booleanclearPackagePreferredActivitiesLP(java.lang.String packageName)

        boolean changed = false;
        Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
        while (it.hasNext()) {
            PreferredActivity pa = it.next();
            if (pa.mActivity.getPackageName().equals(packageName)) {
                it.remove();
                changed = true;
            }
        }
        return changed;
    
private booleancollectCertificatesLI(android.content.pm.PackageParser pp, com.android.server.PackageManagerService$PackageSetting ps, PackageParser.Package pkg, java.io.File srcFile, int parseFlags)

        if (GET_CERTIFICATES) {
            if (ps == null || !ps.codePath.equals(srcFile)
                    || ps.getTimeStamp() != srcFile.lastModified()) {
                Log.i(TAG, srcFile.toString() + " changed; collecting certs");
                if (!pp.collectCertificates(pkg, parseFlags)) {
                    mLastScanError = pp.getParseError();
                    return false;
                }
            }
        }
        return true;
    
private static voidcopyZipEntry(java.util.zip.ZipEntry zipEntry, java.util.zip.ZipFile inZipFile, java.util.zip.ZipOutputStream outZipStream)

        byte[] buffer = new byte[4096];
        int num;

        ZipEntry newEntry;
        if (zipEntry.getMethod() == ZipEntry.STORED) {
            // Preserve the STORED method of the input entry.
            newEntry = new ZipEntry(zipEntry);
        } else {
            // Create a new entry so that the compressed len is recomputed.
            newEntry = new ZipEntry(zipEntry.getName());
        }
        outZipStream.putNextEntry(newEntry);

        InputStream data = inZipFile.getInputStream(zipEntry);
        while ((num = data.read(buffer)) > 0) {
            outZipStream.write(buffer, 0, num);
        }
        outZipStream.flush();
    
private java.io.FilecreateTempPackageFile()

        File tmpPackageFile;
        try {
            tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
        } catch (IOException e) {
            Log.e(TAG, "Couldn't create temp file for downloaded package file.");
            return null;
        }
        try {
            FileUtils.setPermissions(
                    tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
                    -1, -1);
        } catch (IOException e) {
            Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
            return null;
        }
        return tmpPackageFile;
    
public voiddeleteApplicationCacheFiles(java.lang.String packageName, android.content.pm.IPackageDataObserver observer)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.DELETE_CACHE_FILES, null);
        // Queue up an async operation since the package deletion may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                final boolean succeded;
                synchronized (mInstallLock) {
                    succeded = deleteApplicationCacheFilesLI(packageName);
                }
                if(observer != null) {
                    try {
                        observer.onRemoveCompleted(packageName, succeded);
                    } catch (RemoteException e) {
                        Log.i(TAG, "Observer no longer exists.");
                    }
                } //end if observer
            } //end run
        });
    
private booleandeleteApplicationCacheFilesLI(java.lang.String packageName)

        if (packageName == null) {
            Log.w(TAG, "Attempt to delete null packageName.");
            return false;
        }
        PackageParser.Package p;
        synchronized (mPackages) {
            p = mPackages.get(packageName);
        }
        if (p == null) {
            Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
            return false;
        }
        final ApplicationInfo applicationInfo = p.applicationInfo;
        if (applicationInfo == null) {
            Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
            return false;
        }
        if (mInstaller != null) {
            int retCode = mInstaller.deleteCacheFiles(packageName);
            if (retCode < 0) {
                Log.w(TAG, "Couldn't remove cache files for package: "
                           + packageName);
                return false;
            }
        }
        return true;
    
private booleandeleteInstalledPackageLI(PackageParser.Package p, boolean deleteCodeAndResources, int flags, com.android.server.PackageManagerService$PackageRemovedInfo outInfo)

        ApplicationInfo applicationInfo = p.applicationInfo;
        if (applicationInfo == null) {
            Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
            return false;
        }
        // Delete application's source directory
        File sourceFile = new File(applicationInfo.sourceDir);
        if (!sourceFile.exists()) {
            Log.w(TAG, "Package source " + applicationInfo.sourceDir + " does not exist.");
        }
        outInfo.uid = applicationInfo.uid;

        // Delete package data from internal structures and also remove data if flag is set
        removePackageDataLI(p, outInfo, flags);

        // Delete application code and resources
        if (deleteCodeAndResources) {
            sourceFile.delete();
            final File publicSourceFile = new File(applicationInfo.publicSourceDir);
            if (publicSourceFile.exists()) {
                publicSourceFile.delete();
            }
            if (mInstaller != null) {
                int retCode = mInstaller.rmdex(sourceFile.toString());
                if (retCode < 0) {
                    Log.w(TAG, "Couldn't remove dex file for package: "
                            + p.packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
                    // we don't consider this to be a failure of the core package deletion
                }
            }
        }
        return true;
    
public voiddeletePackage(java.lang.String packageName, android.content.pm.IPackageDeleteObserver observer, int flags)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.DELETE_PACKAGES, null);
        // Queue up an async operation since the package deletion may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                final boolean succeded = deletePackageX(packageName, true, true, flags);
                if (observer != null) {
                    try {
                        observer.packageDeleted(succeded);
                    } catch (RemoteException e) {
                        Log.i(TAG, "Observer no longer exists.");
                    } //end catch
                } //end if
            } //end run
        });
    
private booleandeletePackageLI(java.lang.String packageName, boolean deleteCodeAndResources, int flags, com.android.server.PackageManagerService$PackageRemovedInfo outInfo)

        if (packageName == null) {
            Log.w(TAG, "Attempt to delete null packageName.");
            return false;
        }
        PackageParser.Package p;
        boolean dataOnly = false;
        synchronized (mPackages) {
            p = mPackages.get(packageName);
            if (p == null) {
                //this retrieves partially installed apps
                dataOnly = true;
                PackageSetting ps = mSettings.mPackages.get(packageName);
                if (ps == null) {
                    Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
                    return false;
                }
                p = ps.pkg;
            }
        }
        if (p == null) {
            Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
            return false;
        }
        
        if (dataOnly) {
            // Delete application data first
            removePackageDataLI(p, outInfo, flags);
            return true;
        }
        // At this point the package should have ApplicationInfo associated with it
        if (p.applicationInfo == null) {
            Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
            return false;
        }
        if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
            Log.i(TAG, "Removing system package:"+p.packageName);
            // When an updated system application is deleted we delete the existing resources as well and
            // fall back to existing code in system partition
            return deleteSystemPackageLI(p, true, flags, outInfo);
        }
        Log.i(TAG, "Removing non-system package:"+p.packageName);
        return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
    
private booleandeletePackageX(java.lang.String packageName, boolean sendBroadCast, boolean deleteCodeAndResources, int flags)
This method is an internal method that could be get invoked either to delete an installed package or to clean up a failed installation. After deleting an installed package, a broadcast is sent to notify any listeners that the package has been installed. For cleaning up a failed installation, the broadcast is not necessary since the package's installation wouldn't have sent the initial broadcast either The key steps in deleting a package are deleting the package information in internal structures like mPackages, deleting the packages base directories through installd updating mSettings to reflect current status persisting settings for later use sending a broadcast if necessary

        PackageRemovedInfo info = new PackageRemovedInfo();
        boolean res;

        synchronized (mInstallLock) {
            res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
        }
        
        if(res && sendBroadCast) {
            boolean systemUpdate = info.isRemovedPackageSystemUpdate;
            info.sendBroadcast(deleteCodeAndResources, systemUpdate);

            // If the removed package was a system update, the old system packaged
            // was re-enabled; we need to broadcast this information
            if (systemUpdate) {
                Bundle extras = new Bundle(1);
                extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
                extras.putBoolean(Intent.EXTRA_REPLACING, true);

                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
                sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
            }
        }
        return res;
    
private booleandeleteSystemPackageLI(PackageParser.Package p, boolean deleteCodeAndResources, int flags, com.android.server.PackageManagerService$PackageRemovedInfo outInfo)

        ApplicationInfo applicationInfo = p.applicationInfo;
        //applicable for non-partially installed applications only
        if (applicationInfo == null) {
            Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
            return false;
        }
        PackageSetting ps = null;
        // Confirm if the system package has been updated
        // An updated system app can be deleted. This will also have to restore
        // the system pkg from system partition
        synchronized (mPackages) {
            ps = mSettings.getDisabledSystemPkg(p.packageName);
        }
        if (ps == null) {
            Log.w(TAG, "Attempt to delete system package "+ p.packageName);
            return false;
        } else {
            Log.i(TAG, "Deleting system pkg from data partition");
        }
        // Delete the updated package
        outInfo.isRemovedPackageSystemUpdate = true;
        boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
        if (!ret) {
            return false;
        }
        synchronized (mPackages) {
            // Reinstate the old system package
            mSettings.enableSystemPackageLP(p.packageName);
        }
        // Install the system package
        PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
                PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
                SCAN_MONITOR);
        
        if (newPkg == null) {
            Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
            return false;
        }
        synchronized (mPackages) {
            mSettings.writeLP();
        }
        return true;
    
private voiddeleteTempPackageFiles()

        FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.startsWith("vmdl") && name.endsWith(".tmp");
            }
        };
        String tmpFilesList[] = mAppInstallDir.list(filter);
        if(tmpFilesList == null) {
            return;
        }
        for(int i = 0; i < tmpFilesList.length; i++) {
            File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
            tmpFile.delete();
        }
    
protected voiddump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)

        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {
            pw.println("Permission Denial: can't dump ActivityManager from from pid="
                    + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid()
                    + " without permission "
                    + android.Manifest.permission.DUMP);
            return;
        }

        Printer printer = new PrintWriterPrinter(pw);
        synchronized (mPackages) {
            pw.println("Activity Resolver Table:");
            mActivities.dump(printer, "  ");
            pw.println(" ");
            pw.println("Receiver Resolver Table:");
            mReceivers.dump(printer, "  ");
            pw.println(" ");
            pw.println("Service Resolver Table:");
            mServices.dump(printer, "  ");
            pw.println(" ");
            pw.println("Preferred Activities:");
            mSettings.mPreferredActivities.dump(printer, "  ");
            pw.println(" ");
            pw.println("Preferred Packages:");
            {
                for (PackageSetting ps : mSettings.mPreferredPackages) {
                    pw.println("  " + ps.name);
                }
            }
            pw.println(" ");
            pw.println("Permissions:");
            {
                for (BasePermission p : mSettings.mPermissions.values()) {
                    pw.println("  Permission [" + p.name + "] ("
                            + Integer.toHexString(System.identityHashCode(p))
                            + "):");
                    pw.println("    sourcePackage=" + p.sourcePackage);
                    pw.println("    uid=" + p.uid
                            + " gids=" + arrayToString(p.gids)
                            + " type=" + p.type);
                }
            }
            pw.println(" ");
            pw.println("Packages:");
            {
                for (PackageSetting ps : mSettings.mPackages.values()) {
                    pw.println("  Package [" + ps.name + "] ("
                            + Integer.toHexString(System.identityHashCode(ps))
                            + "):");
                    pw.println("    userId=" + ps.userId
                            + " gids=" + arrayToString(ps.gids));
                    pw.println("    sharedUser=" + ps.sharedUser);
                    pw.println("    pkg=" + ps.pkg);
                    pw.println("    codePath=" + ps.codePathString);
                    pw.println("    resourcePath=" + ps.resourcePathString);
                    if (ps.pkg != null) {
                        pw.println("    dataDir=" + ps.pkg.applicationInfo.dataDir);
                    }
                    pw.println("    timeStamp=" + ps.getTimeStampStr());
                    pw.println("    signatures=" + ps.signatures);
                    pw.println("    permissionsFixed=" + ps.permissionsFixed
                            + " pkgFlags=0x" + Integer.toHexString(ps.pkgFlags)
                            + " installStatus=" + ps.installStatus
                            + " enabled=" + ps.enabled);
                    if (ps.disabledComponents.size() > 0) {
                        pw.println("    disabledComponents:");
                        for (String s : ps.disabledComponents) {
                            pw.println("      " + s);
                        }
                    }
                    if (ps.enabledComponents.size() > 0) {
                        pw.println("    enabledComponents:");
                        for (String s : ps.enabledComponents) {
                            pw.println("      " + s);
                        }
                    }
                    pw.println("    grantedPermissions:");
                    for (String s : ps.grantedPermissions) {
                        pw.println("      " + s);
                    }
                    pw.println("    loadedPermissions:");
                    for (String s : ps.loadedPermissions) {
                        pw.println("      " + s);
                    }
                }
            }
            pw.println(" ");
            pw.println("Shared Users:");
            {
                for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
                    pw.println("  SharedUser [" + su.name + "] ("
                            + Integer.toHexString(System.identityHashCode(su))
                            + "):");
                    pw.println("    userId=" + su.userId
                            + " gids=" + arrayToString(su.gids));
                    pw.println("    grantedPermissions:");
                    for (String s : su.grantedPermissions) {
                        pw.println("      " + s);
                    }
                    pw.println("    loadedPermissions:");
                    for (String s : su.loadedPermissions) {
                        pw.println("      " + s);
                    }
                }
            }
            pw.println(" ");
            pw.println("Settings parse messages:");
            pw.println(mSettings.mReadMessages.toString());
        }
    
public voidenterSafeMode()

        if (!mSystemReady) {
            mSafeMode = true;
        }
    
private voidextractPublicFiles(PackageParser.Package newPackage, java.io.File publicZipFile)

        final ZipOutputStream publicZipOutStream =
                new ZipOutputStream(new FileOutputStream(publicZipFile));
        final ZipFile privateZip = new ZipFile(newPackage.mPath);

        // Copy manifest, resources.arsc and res directory to public zip

        final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
        while (privateZipEntries.hasMoreElements()) {
            final ZipEntry zipEntry = privateZipEntries.nextElement();
            final String zipEntryName = zipEntry.getName();
            if ("AndroidManifest.xml".equals(zipEntryName)
                || "resources.arsc".equals(zipEntryName)
                || zipEntryName.startsWith("res/")) {
                try {
                    copyZipEntry(zipEntry, privateZip, publicZipOutStream);
                } catch (IOException e) {
                    try {
                        publicZipOutStream.close();
                        throw e;
                    } finally {
                        publicZipFile.delete();
                    }
                }
            }
        }

        publicZipOutStream.close();
        FileUtils.setPermissions(
                publicZipFile.getAbsolutePath(),
                FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
                -1, -1);
    
private com.android.server.PackageManagerService$BasePermissionfindPermissionTreeLP(java.lang.String permName)

        for(BasePermission bp : mSettings.mPermissionTrees.values()) {
            if (permName.startsWith(bp.name) &&
                    permName.length() > bp.name.length() &&
                    permName.charAt(bp.name.length()) == '.") {
                return bp;
            }
        }
        return null;
    
android.content.pm.ResolveInfofindPreferredActivity(android.content.Intent intent, java.lang.String resolvedType, int flags, java.util.List query, int priority)

        synchronized (mPackages) {
            if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
            List<PreferredActivity> prefs =
                    mSettings.mPreferredActivities.queryIntent(null,
                            intent, resolvedType,
                            (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
            if (prefs != null && prefs.size() > 0) {
                // First figure out how good the original match set is.
                // We will only allow preferred activities that came
                // from the same match quality.
                int match = 0;
                final int N = query.size();
                if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
                for (int j=0; j<N; j++) {
                    ResolveInfo ri = query.get(j);
                    if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
                            + ": 0x" + Integer.toHexString(match));
                    if (ri.match > match) match = ri.match;
                }
                if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
                        + Integer.toHexString(match));
                match &= IntentFilter.MATCH_CATEGORY_MASK;
                final int M = prefs.size();
                for (int i=0; i<M; i++) {
                    PreferredActivity pa = prefs.get(i);
                    if (pa.mMatch != match) {
                        continue;
                    }
                    ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
                    if (DEBUG_PREFERRED) {
                        Log.v(TAG, "Got preferred activity:");
                        ai.dump(new LogPrinter(Log.INFO, TAG), "  ");
                    }
                    if (ai != null) {
                        for (int j=0; j<N; j++) {
                            ResolveInfo ri = query.get(j);
                            if (!ri.activityInfo.applicationInfo.packageName
                                    .equals(ai.applicationInfo.packageName)) {
                                continue;
                            }
                            if (!ri.activityInfo.name.equals(ai.name)) {
                                continue;
                            }

                            // Okay we found a previously set preferred app.
                            // If the result set is different from when this
                            // was created, we need to clear it and re-ask the
                            // user their preference.
                            if (!pa.sameSet(query, priority)) {
                                Log.i(TAG, "Result set changed, dropping preferred activity for "
                                        + intent + " type " + resolvedType);
                                mSettings.mPreferredActivities.removeFilter(pa);
                                return null;
                            }

                            // Yay!
                            return ri;
                        }
                    }
                }
            }
        }
        return null;
    
private static java.lang.StringfixProcessName(java.lang.String defProcessName, java.lang.String processName, int uid)

        if (processName == null) {
            return defProcessName;
        }
        return processName;
    
public voidfreeStorage(long freeStorageSize, android.app.PendingIntent opFinishedIntent)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.CLEAR_APP_CACHE, null);
        // Queue up an async operation since clearing cache may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                int retCode = -1;
                if (mInstaller != null) {
                    retCode = mInstaller.freeCache(freeStorageSize);
                    if (retCode < 0) {
                        Log.w(TAG, "Couldn't clear application caches");
                    }
                }
                if(opFinishedIntent != null) {
                    try {
                        // Callback via pending intent
                        opFinishedIntent.send((retCode >= 0) ? 1 : 0);
                    } catch (CanceledException e1) {
                        Log.i(TAG, "Failed to send pending intent");
                    }
                }
            }
        });
    
public voidfreeStorageAndNotify(long freeStorageSize, android.content.pm.IPackageDataObserver observer)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.CLEAR_APP_CACHE, null);
        // Queue up an async operation since clearing cache may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                int retCode = -1;
                if (mInstaller != null) {
                    retCode = mInstaller.freeCache(freeStorageSize);
                    if (retCode < 0) {
                        Log.w(TAG, "Couldn't clear application caches");
                    }
                } //end if mInstaller
                if (observer != null) {
                    try {
                        observer.onRemoveCompleted(null, (retCode >= 0));
                    } catch (RemoteException e) {
                        Log.w(TAG, "RemoveException when invoking call back");
                    }
                }
            }
        });
    
private android.content.pm.ApplicationInfogenerateApplicationInfoFromSettingsLP(java.lang.String packageName, int flags)

        PackageSetting ps = mSettings.mPackages.get(packageName);
        if(ps != null) {
            if(ps.pkg == null) {
                PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
                if(pInfo != null) {
                    return pInfo.applicationInfo;
                }
                return null;
            }
            return PackageParser.generateApplicationInfo(ps.pkg, flags);
        }
        return null;
    
android.content.pm.PackageInfogeneratePackageInfo(PackageParser.Package p, int flags)

        final PackageSetting ps = (PackageSetting)p.mExtras;
        if (ps == null) {
            return null;
        }
        final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
        return PackageParser.generatePackageInfo(p, gp.gids, flags);
    
private android.content.pm.PackageInfogeneratePackageInfoFromSettingsLP(java.lang.String packageName, int flags)

        PackageSetting ps = mSettings.mPackages.get(packageName);
        if(ps != null) {
            if(ps.pkg == null) {
                ps.pkg = new PackageParser.Package(packageName);
                ps.pkg.applicationInfo.packageName = packageName;
            }
            return generatePackageInfo(ps.pkg, flags);
        }
        return null;
    
public android.content.pm.ActivityInfogetActivityInfo(android.content.ComponentName component, int flags)

        synchronized (mPackages) {
            PackageParser.Activity a = mActivities.mActivities.get(component);
            if (Config.LOGV) Log.v(
                TAG, "getActivityInfo " + component + ": " + a);
            if (a != null && mSettings.isEnabledLP(a.info, flags)) {
                return PackageParser.generateActivityInfo(a, flags);
            }
            if (mResolveComponentName.equals(component)) {
                return mResolveActivity;
            }
        }
        return null;
    
public java.util.ListgetAllPermissionGroups(int flags)

        synchronized (mPackages) {
            final int N = mPermissionGroups.size();
            ArrayList<PermissionGroupInfo> out
                    = new ArrayList<PermissionGroupInfo>(N);
            for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
                out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
            }
            return out;
        }
    
public intgetApplicationEnabledSetting(java.lang.String appPackageName)

        synchronized (mPackages) {
            PackageSetting pkg = mSettings.mPackages.get(appPackageName);
            if (pkg == null) {
                throw new IllegalArgumentException("Unknown package: " + appPackageName);
            }
            return pkg.enabled;
        }
    
public android.content.pm.ApplicationInfogetApplicationInfo(java.lang.String packageName, int flags)

        synchronized (mPackages) {
            PackageParser.Package p = mPackages.get(packageName);
            if (Config.LOGV) Log.v(
                    TAG, "getApplicationInfo " + packageName
                    + ": " + p);
            if (p != null) {
                // Note: isEnabledLP() does not apply here - always return info
                return PackageParser.generateApplicationInfo(p, flags);
            }
            if ("android".equals(packageName)||"system".equals(packageName)) {
                return mAndroidApplication;
            }
            if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
                return generateApplicationInfoFromSettingsLP(packageName, flags);
            }
        }
        return null;
    
public intgetComponentEnabledSetting(android.content.ComponentName componentName)

        synchronized (mPackages) {
            final String packageNameStr = componentName.getPackageName();
            PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
            if (pkg == null) {
                throw new IllegalArgumentException("Unknown component: " + componentName);
            }
            final String classNameStr = componentName.getClassName();
            return pkg.currentEnabledStateLP(classNameStr);
        }
    
public java.util.ListgetInstalledApplications(int flags)

        ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
        synchronized(mPackages) {
            if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
                Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
                while (i.hasNext()) {
                    final PackageSetting ps = i.next();
                    ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
                    if(ai != null) {
                        finalList.add(ai);
                    }
                }
            }
            else {
                Iterator<PackageParser.Package> i = mPackages.values().iterator();
                while (i.hasNext()) {
                    final PackageParser.Package p = i.next();
                    if (p.applicationInfo != null) {
                        ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
                        if(ai != null) {
                            finalList.add(ai);
                        }
                    }
                }
            }
        }
        return finalList;
    
public java.util.ListgetInstalledPackages(int flags)

        ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();

        synchronized (mPackages) {
            if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
                Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
                while (i.hasNext()) {
                    final PackageSetting ps = i.next();
                    PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
                    if(psPkg != null) {
                        finalList.add(psPkg);
                    }
                }
            }
            else {
                Iterator<PackageParser.Package> i = mPackages.values().iterator();
                while (i.hasNext()) {
                    final PackageParser.Package p = i.next();
                    if (p.applicationInfo != null) {
                        PackageInfo pi = generatePackageInfo(p, flags);
                        if(pi != null) {
                            finalList.add(pi);
                        }
                    }
                }
            }
        }
        return finalList;
    
public android.content.pm.InstrumentationInfogetInstrumentationInfo(android.content.ComponentName name, int flags)

        synchronized (mPackages) {
            final PackageParser.Instrumentation i = mInstrumentation.get(name);
            return PackageParser.generateInstrumentationInfo(i, flags);
        }
    
public java.lang.StringgetNameForUid(int uid)

        synchronized (mPackages) {
            Object obj = mSettings.getUserIdLP(uid);
            if (obj instanceof SharedUserSetting) {
                SharedUserSetting sus = (SharedUserSetting)obj;
                return sus.name + ":" + sus.userId;
            } else if (obj instanceof PackageSetting) {
                PackageSetting ps = (PackageSetting)obj;
                return ps.name;
            }
        }
        return null;
    
public int[]getPackageGids(java.lang.String packageName)

        synchronized (mPackages) {
            PackageParser.Package p = mPackages.get(packageName);
            if (Config.LOGV) Log.v(
                TAG, "getApplicationInfo " + packageName
                + ": " + p);
            if (p != null) {
                final PackageSetting ps = (PackageSetting)p.mExtras;
                final SharedUserSetting suid = ps.sharedUser;
                return suid != null ? suid.gids : ps.gids;
            }
        }
        // stupid thing to indicate an error.
        return new int[0];
    
public android.content.pm.PackageInfogetPackageInfo(java.lang.String packageName, int flags)

        synchronized (mPackages) {
            PackageParser.Package p = mPackages.get(packageName);
            if (Config.LOGV) Log.v(
                TAG, "getApplicationInfo " + packageName
                + ": " + p);
            if (p != null) {
                return generatePackageInfo(p, flags);
            }
            if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
                return generatePackageInfoFromSettingsLP(packageName, flags);
            }
        }
        return null;
    
public voidgetPackageSizeInfo(java.lang.String packageName, android.content.pm.IPackageStatsObserver observer)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.GET_PACKAGE_SIZE, null);
        // Queue up an async operation since the package deletion may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                PackageStats lStats = new PackageStats(packageName);
                final boolean succeded;
                synchronized (mInstallLock) {
                    succeded = getPackageSizeInfoLI(packageName, lStats);
                }
                if(observer != null) {
                    try {
                        observer.onGetStatsCompleted(lStats, succeded);
                    } catch (RemoteException e) {
                        Log.i(TAG, "Observer no longer exists.");
                    }
                } //end if observer
            } //end run
        });
    
private booleangetPackageSizeInfoLI(java.lang.String packageName, android.content.pm.PackageStats pStats)

        if (packageName == null) {
            Log.w(TAG, "Attempt to get size of null packageName.");
            return false;
        }
        PackageParser.Package p;
        boolean dataOnly = false;
        synchronized (mPackages) {
            p = mPackages.get(packageName);
            if(p == null) {
                dataOnly = true;
                PackageSetting ps = mSettings.mPackages.get(packageName);
                if((ps == null) || (ps.pkg == null)) {
                    Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
                    return false;
                }
                p = ps.pkg;
            }
        }
        String publicSrcDir = null;
        if(!dataOnly) {
            final ApplicationInfo applicationInfo = p.applicationInfo;
            if (applicationInfo == null) {
                Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
                return false;
            }
            publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
        }
        if (mInstaller != null) {
            int res = mInstaller.getSizeInfo(packageName, p.mPath,
                    publicSrcDir, pStats);
            if (res < 0) {
                return false;
            } else {
                return true;
            }
        }
        return true;
    
public intgetPackageUid(java.lang.String packageName)

        synchronized (mPackages) {
            PackageParser.Package p = mPackages.get(packageName);
            if(p != null) {
                return p.applicationInfo.uid;
            }
            PackageSetting ps = mSettings.mPackages.get(packageName);
            if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
                return -1;
            }
            p = ps.pkg;
            return p != null ? p.applicationInfo.uid : -1;
        }
    
public java.lang.String[]getPackagesForUid(int uid)

        synchronized (mPackages) {
            Object obj = mSettings.getUserIdLP(uid);
            if (obj instanceof SharedUserSetting) {
                SharedUserSetting sus = (SharedUserSetting)obj;
                final int N = sus.packages.size();
                String[] res = new String[N];
                Iterator<PackageSetting> it = sus.packages.iterator();
                int i=0;
                while (it.hasNext()) {
                    res[i++] = it.next().name;
                }
                return res;
            } else if (obj instanceof PackageSetting) {
                PackageSetting ps = (PackageSetting)obj;
                return new String[] { ps.name };
            }
        }
        return null;
    
public android.content.pm.PermissionGroupInfogetPermissionGroupInfo(java.lang.String name, int flags)

        synchronized (mPackages) {
            return PackageParser.generatePermissionGroupInfo(
                    mPermissionGroups.get(name), flags);
        }
    
public android.content.pm.PermissionInfogetPermissionInfo(java.lang.String name, int flags)

        synchronized (mPackages) {
            final BasePermission p = mSettings.mPermissions.get(name);
            if (p != null && p.perm != null) {
                return PackageParser.generatePermissionInfo(p.perm, flags);
            }
            return null;
        }
    
public java.util.ListgetPersistentApplications(int flags)

        ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();

        synchronized (mPackages) {
            Iterator<PackageParser.Package> i = mPackages.values().iterator();
            while (i.hasNext()) {
                PackageParser.Package p = i.next();
                if (p.applicationInfo != null
                        && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
                        && (!mSafeMode || (p.applicationInfo.flags
                                &ApplicationInfo.FLAG_SYSTEM) != 0)) {
                    finalList.add(p.applicationInfo);
                }
            }
        }

        return finalList;
    
public intgetPreferredActivities(java.util.List outFilters, java.util.List outActivities, java.lang.String packageName)


        int num = 0;
        synchronized (mPackages) {
            Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
            while (it.hasNext()) {
                PreferredActivity pa = it.next();
                if (packageName == null
                        || pa.mActivity.getPackageName().equals(packageName)) {
                    if (outFilters != null) {
                        outFilters.add(new IntentFilter(pa));
                    }
                    if (outActivities != null) {
                        outActivities.add(pa.mActivity);
                    }
                }
            }
        }

        return num;
    
public java.util.ListgetPreferredPackages(int flags)

        synchronized (mPackages) {
            final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
            final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
            final int N = pref.size();
            for (int i=0; i<N; i++) {
                res.add(generatePackageInfo(pref.get(i).pkg, flags));
            }
            return res;
        }
    
public android.content.pm.ActivityInfogetReceiverInfo(android.content.ComponentName component, int flags)

        synchronized (mPackages) {
            PackageParser.Activity a = mReceivers.mActivities.get(component);
            if (Config.LOGV) Log.v(
                TAG, "getReceiverInfo " + component + ": " + a);
            if (a != null && mSettings.isEnabledLP(a.info, flags)) {
                return PackageParser.generateActivityInfo(a, flags);
            }
        }
        return null;
    
public android.content.pm.ServiceInfogetServiceInfo(android.content.ComponentName component, int flags)

        synchronized (mPackages) {
            PackageParser.Service s = mServices.mServices.get(component);
            if (Config.LOGV) Log.v(
                TAG, "getServiceInfo " + component + ": " + s);
            if (s != null && mSettings.isEnabledLP(s.info, flags)) {
                return PackageParser.generateServiceInfo(s, flags);
            }
        }
        return null;
    
public java.lang.String[]getSystemSharedLibraryNames()

        Set<String> libSet;
        synchronized (mPackages) {
            libSet = mSharedLibraries.keySet();
        }
        int size = libSet.size();
        if (size > 0) {
            String[] libs = new String[size];
            libSet.toArray(libs);
            return libs;
        }
        return null;
    
public intgetUidForSharedUser(java.lang.String sharedUserName)

        if(sharedUserName == null) {
            return -1;
        }
        synchronized (mPackages) {
            SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
            if(suid == null) {
                return -1;
            }
            return suid.userId;
        }
    
private voidgrantPermissionsLP(PackageParser.Package pkg, boolean replace)

        final PackageSetting ps = (PackageSetting)pkg.mExtras;
        if (ps == null) {
            return;
        }
        final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
        boolean addedPermission = false;
        
        if (replace) {
            ps.permissionsFixed = false;
            if (gp == ps) {
                gp.grantedPermissions.clear();
                gp.gids = mGlobalGids;
            }
        }
        
        if (gp.gids == null) {
            gp.gids = mGlobalGids;
        }
        
        final int N = pkg.requestedPermissions.size();
        for (int i=0; i<N; i++) {
            String name = pkg.requestedPermissions.get(i);
            BasePermission bp = mSettings.mPermissions.get(name);
            PackageParser.Permission p = bp != null ? bp.perm : null;
            if (false) {
                if (gp != ps) {
                    Log.i(TAG, "Package " + pkg.packageName + " checking " + name
                            + ": " + p);
                }
            }
            if (p != null) {
                final String perm = p.info.name;
                boolean allowed;
                if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
                        || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
                    allowed = true;
                } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
                        || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
                    allowed = (checkSignaturesLP(p.owner, pkg)
                                    == PackageManager.SIGNATURE_MATCH)
                            || (checkSignaturesLP(mPlatformPackage, pkg)
                                    == PackageManager.SIGNATURE_MATCH);
                    if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
                        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
                            // For updated system applications, the signatureOrSystem permission
                            // is granted only if it had been defined by the original application.
                            if ((pkg.applicationInfo.flags 
                                    & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)  != 0) {
                                PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
                                if(sysPs.grantedPermissions.contains(perm)) {
                                    allowed = true;
                                } else {
                                    allowed = false;
                                }
                            } else {
                                allowed = true;
                            }
                        }
                    }
                } else {
                    allowed = false;
                }
                if (false) {
                    if (gp != ps) {
                        Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
                    }
                }
                if (allowed) {
                    if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
                            && ps.permissionsFixed) {
                        // If this is an existing, non-system package, then
                        // we can't add any new permissions to it.
                        if (!gp.loadedPermissions.contains(perm)) {
                            allowed = false;
                        }
                    }
                    if (allowed) {
                        if (!gp.grantedPermissions.contains(perm)) {
                            addedPermission = true;
                            gp.grantedPermissions.add(perm);
                            gp.gids = appendInts(gp.gids, bp.gids);
                        }
                    } else {
                        Log.w(TAG, "Not granting permission " + perm
                                + " to package " + pkg.packageName
                                + " because it was previously installed without");
                    }
                } else {
                    Log.w(TAG, "Not granting permission " + perm
                            + " to package " + pkg.packageName
                            + " (protectionLevel=" + p.info.protectionLevel
                            + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
                            + ")");
                }
            } else {
                Log.w(TAG, "Unknown permission " + name
                        + " in package " + pkg.packageName);
            }
        }
        
        if ((addedPermission || replace) && !ps.permissionsFixed &&
                (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
            // This is the first that we have heard about this package, so the
            // permissions we have now selected are fixed until explicitly
            // changed.
            ps.permissionsFixed = true;
            gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
        }
    
public booleanhasSystemUidErrors()

        return mHasSystemUidErrors;
    
private voidinstallNewPackageLI(java.lang.String pkgName, java.io.File tmpPackageFile, java.lang.String destFilePath, java.io.File destPackageFile, java.io.File destResourceFile, PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, com.android.server.PackageManagerService$PackageInstalledInfo res)

        // Remember this for later, in case we need to rollback this install
        boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
        res.name = pkgName;
        synchronized(mPackages) {
            if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
                // Don't allow installation over an existing package with the same name.
                Log.w(TAG, "Attempt to re-install " + pkgName 
                        + " without first uninstalling.");
                res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
                return;
            }
        }
        if (destPackageFile.exists()) {
            // It's safe to do this because we know (from the above check) that the file
            // isn't currently used for an installed package.
            destPackageFile.delete();
        }
        mLastScanError = PackageManager.INSTALL_SUCCEEDED;
        PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
                destResourceFile, pkg, 0,
                SCAN_MONITOR | SCAN_FORCE_DEX
                | SCAN_UPDATE_SIGNATURE 
                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
                | (newInstall ? SCAN_NEW_INSTALL : 0));
        if (newPackage == null) {
            Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
            if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
                res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
            }
        } else {
            updateSettingsLI(pkgName, tmpPackageFile, 
                    destFilePath, destPackageFile,
                    destResourceFile, pkg, 
                    newPackage,
                    true,
                    forwardLocked,  
                    res);
            // delete the partially installed application. the data directory will have to be
            // restored if it was already existing
            if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
                // remove package from internal structures.  Note that we want deletePackageX to
                // delete the package data and cache directories that it created in
                // scanPackageLocked, unless those directories existed before we even tried to
                // install.
                deletePackageLI(
                        pkgName, true,
                        dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
                                res.removedInfo);
            }
        }
    
public voidinstallPackage(android.net.Uri packageURI, android.content.pm.IPackageInstallObserver observer, int flags)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.INSTALL_PACKAGES, null);

        // Queue up an async operation since the package installation may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                PackageInstalledInfo res;
                synchronized (mInstallLock) {
                    res = installPackageLI(packageURI, flags, true);
                }
                if (observer != null) {
                    try {
                        observer.packageInstalled(res.name, res.returnCode);
                    } catch (RemoteException e) {
                        Log.i(TAG, "Observer no longer exists.");
                    }
                }
                // There appears to be a subtle deadlock condition if the sendPackageBroadcast
                // call appears in the synchronized block above.
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                    res.removedInfo.sendBroadcast(false, true);
                    Bundle extras = new Bundle(1);
                    extras.putInt(Intent.EXTRA_UID, res.uid);
                    final boolean update = res.removedInfo.removedPackage != null;
                    if (update) {
                        extras.putBoolean(Intent.EXTRA_REPLACING, true);
                    }
                    sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
                                         res.pkg.applicationInfo.packageName,
                                         extras);
                    if (update) {
                        sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
                                res.pkg.applicationInfo.packageName,
                                extras);
                    }
                }
                Runtime.getRuntime().gc();
            }
        });
    
private com.android.server.PackageManagerService$PackageInstalledInfoinstallPackageLI(android.net.Uri pPackageURI, int pFlags, boolean newInstall)

        File tmpPackageFile = null;
        String pkgName = null;
        boolean forwardLocked = false;
        boolean replacingExistingPackage = false;
        // Result object to be returned
        PackageInstalledInfo res = new PackageInstalledInfo();
        res.returnCode = PackageManager.INSTALL_SUCCEEDED;
        res.uid = -1;
        res.pkg = null;
        res.removedInfo = new PackageRemovedInfo();

        main_flow: try {
            tmpPackageFile = createTempPackageFile();
            if (tmpPackageFile == null) {
                res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                break main_flow;
            }
            tmpPackageFile.deleteOnExit();  // paranoia
            if (pPackageURI.getScheme().equals("file")) {
                final File srcPackageFile = new File(pPackageURI.getPath());
                // We copy the source package file to a temp file and then rename it to the
                // destination file in order to eliminate a window where the package directory
                // scanner notices the new package file but it's not completely copied yet.
                if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
                    Log.e(TAG, "Couldn't copy package file to temp file.");
                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                    break main_flow;
                }
            } else if (pPackageURI.getScheme().equals("content")) {
                ParcelFileDescriptor fd;
                try {
                    fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
                } catch (FileNotFoundException e) {
                    Log.e(TAG, "Couldn't open file descriptor from download service.");
                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                    break main_flow;
                }
                if (fd == null) {
                    Log.e(TAG, "Couldn't open file descriptor from download service (null).");
                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                    break main_flow;
                }
                if (Config.LOGV) {
                    Log.v(TAG, "Opened file descriptor from download service.");
                }
                ParcelFileDescriptor.AutoCloseInputStream
                        dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
                // We copy the source package file to a temp file and then rename it to the
                // destination file in order to eliminate a window where the package directory
                // scanner notices the new package file but it's not completely copied yet.
                if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
                    Log.e(TAG, "Couldn't copy package stream to temp file.");
                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                    break main_flow;
                }
            } else {
                Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
                res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
                break main_flow;
            }
            pkgName = PackageParser.parsePackageName(
                    tmpPackageFile.getAbsolutePath(), 0);
            if (pkgName == null) {
                Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
                res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
                break main_flow;
            }
            res.name = pkgName;
            //initialize some variables before installing pkg
            final String pkgFileName = pkgName + ".apk";
            final File destDir = ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0)
                                 ?  mDrmAppPrivateInstallDir
                                 : mAppInstallDir;
            final File destPackageFile = new File(destDir, pkgFileName);
            final String destFilePath = destPackageFile.getAbsolutePath();
            File destResourceFile;
            if ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0) {
                final String publicZipFileName = pkgName + ".zip";
                destResourceFile = new File(mAppInstallDir, publicZipFileName);
                forwardLocked = true;
            } else {
                destResourceFile = destPackageFile;
            }
            // Retrieve PackageSettings and parse package
            int parseFlags = PackageParser.PARSE_CHATTY;
            parseFlags |= mDefParseFlags;
            PackageParser pp = new PackageParser(tmpPackageFile.getPath());
            pp.setSeparateProcesses(mSeparateProcesses);
            pp.setSdkVersion(mSdkVersion);
            final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
                    destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
            if (pkg == null) {
                res.returnCode = pp.getParseError();
                break main_flow;
            }
            if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
                res.returnCode = pp.getParseError();
                break main_flow;
            }
            
            synchronized (mPackages) {
                //check if installing already existing package
                if ((pFlags&PackageManager.REPLACE_EXISTING_PACKAGE) != 0
                        && mPackages.containsKey(pkgName)) {
                    replacingExistingPackage = true;
                }
            }
            
            if(replacingExistingPackage) {
                replacePackageLI(pkgName,
                        tmpPackageFile, 
                        destFilePath, destPackageFile, destResourceFile,
                        pkg, forwardLocked, newInstall,
                        res);
            } else {
                installNewPackageLI(pkgName,
                        tmpPackageFile, 
                        destFilePath, destPackageFile, destResourceFile,
                        pkg, forwardLocked, newInstall,
                        res);
            }
        } finally {
            if (tmpPackageFile != null && tmpPackageFile.exists()) {
                tmpPackageFile.delete();
            }
        }
        return res;
    
private booleanisForwardLocked(PackageParser.Package deletedPackage)

        final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
        return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
    
private static final booleanisPackageFilename(java.lang.String name)

        return name != null && name.endsWith(".apk");
    
public booleanisSafeMode()

        return mSafeMode;
    
public static final android.content.pm.IPackageManagermain(android.content.Context context, boolean factoryTest)


            
        PackageManagerService m = new PackageManagerService(context, factoryTest);
        ServiceManager.addService("package", m);
        return m;
    
public booleanonTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)

        try {
            return super.onTransact(code, data, reply, flags);
        } catch (RuntimeException e) {
            if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
                Log.e(TAG, "Package Manager Crash", e);
            }
            throw e;
        }
    
public java.util.ListqueryContentProviders(java.lang.String processName, int uid, int flags)

        ArrayList<ProviderInfo> finalList = null;

        synchronized (mPackages) {
            Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
            while (i.hasNext()) {
                PackageParser.Provider p = i.next();
                if (p.info.authority != null
                    && (processName == null ||
                            (p.info.processName.equals(processName)
                                    && p.info.applicationInfo.uid == uid))
                    && mSettings.isEnabledLP(p.info, flags)
                    && (!mSafeMode || (p.info.applicationInfo.flags
                            &ApplicationInfo.FLAG_SYSTEM) != 0)) {
                    if (finalList == null) {
                        finalList = new ArrayList<ProviderInfo>(3);
                    }
                    finalList.add(PackageParser.generateProviderInfo(p,
                            flags));
                }
            }
        }

        if (finalList != null) {
            Collections.sort(finalList, mProviderInitOrderSorter);
        }

        return finalList;
    
public java.util.ListqueryInstrumentation(java.lang.String targetPackage, int flags)

        ArrayList<InstrumentationInfo> finalList =
            new ArrayList<InstrumentationInfo>();

        synchronized (mPackages) {
            Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
            while (i.hasNext()) {
                PackageParser.Instrumentation p = i.next();
                if (targetPackage == null
                        || targetPackage.equals(p.info.targetPackage)) {
                    finalList.add(PackageParser.generateInstrumentationInfo(p,
                            flags));
                }
            }
        }

        return finalList;
    
public java.util.ListqueryIntentActivities(android.content.Intent intent, java.lang.String resolvedType, int flags)

        ComponentName comp = intent.getComponent();
        if (comp != null) {
            List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
            ActivityInfo ai = getActivityInfo(comp, flags);
            if (ai != null) {
                ResolveInfo ri = new ResolveInfo();
                ri.activityInfo = ai;
                list.add(ri);
            }
            return list;
        }

        synchronized (mPackages) {
            return (List<ResolveInfo>)mActivities.
                queryIntent(null, intent, resolvedType, flags);
        }
    
public java.util.ListqueryIntentActivityOptions(android.content.ComponentName caller, android.content.Intent[] specifics, java.lang.String[] specificTypes, android.content.Intent intent, java.lang.String resolvedType, int flags)

        final String resultsAction = intent.getAction();

        List<ResolveInfo> results = queryIntentActivities(
            intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
        if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);

        int specificsPos = 0;
        int N;

        // todo: note that the algorithm used here is O(N^2).  This
        // isn't a problem in our current environment, but if we start running
        // into situations where we have more than 5 or 10 matches then this
        // should probably be changed to something smarter...

        // First we go through and resolve each of the specific items
        // that were supplied, taking care of removing any corresponding
        // duplicate items in the generic resolve list.
        if (specifics != null) {
            for (int i=0; i<specifics.length; i++) {
                final Intent sintent = specifics[i];
                if (sintent == null) {
                    continue;
                }

                if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
                String action = sintent.getAction();
                if (resultsAction != null && resultsAction.equals(action)) {
                    // If this action was explicitly requested, then don't
                    // remove things that have it.
                    action = null;
                }
                ComponentName comp = sintent.getComponent();
                ResolveInfo ri = null;
                ActivityInfo ai = null;
                if (comp == null) {
                    ri = resolveIntent(
                        sintent,
                        specificTypes != null ? specificTypes[i] : null,
                        flags);
                    if (ri == null) {
                        continue;
                    }
                    if (ri == mResolveInfo) {
                        // ACK!  Must do something better with this.
                    }
                    ai = ri.activityInfo;
                    comp = new ComponentName(ai.applicationInfo.packageName,
                            ai.name);
                } else {
                    ai = getActivityInfo(comp, flags);
                    if (ai == null) {
                        continue;
                    }
                }

                // Look for any generic query activities that are duplicates
                // of this specific one, and remove them from the results.
                if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
                N = results.size();
                int j;
                for (j=specificsPos; j<N; j++) {
                    ResolveInfo sri = results.get(j);
                    if ((sri.activityInfo.name.equals(comp.getClassName())
                            && sri.activityInfo.applicationInfo.packageName.equals(
                                    comp.getPackageName()))
                        || (action != null && sri.filter.matchAction(action))) {
                        results.remove(j);
                        if (Config.LOGV) Log.v(
                            TAG, "Removing duplicate item from " + j
                            + " due to specific " + specificsPos);
                        if (ri == null) {
                            ri = sri;
                        }
                        j--;
                        N--;
                    }
                }

                // Add this specific item to its proper place.
                if (ri == null) {
                    ri = new ResolveInfo();
                    ri.activityInfo = ai;
                }
                results.add(specificsPos, ri);
                ri.specificIndex = i;
                specificsPos++;
            }
        }

        // Now we go through the remaining generic results and remove any
        // duplicate actions that are found here.
        N = results.size();
        for (int i=specificsPos; i<N-1; i++) {
            final ResolveInfo rii = results.get(i);
            if (rii.filter == null) {
                continue;
            }

            // Iterate over all of the actions of this result's intent
            // filter...  typically this should be just one.
            final Iterator<String> it = rii.filter.actionsIterator();
            if (it == null) {
                continue;
            }
            while (it.hasNext()) {
                final String action = it.next();
                if (resultsAction != null && resultsAction.equals(action)) {
                    // If this action was explicitly requested, then don't
                    // remove things that have it.
                    continue;
                }
                for (int j=i+1; j<N; j++) {
                    final ResolveInfo rij = results.get(j);
                    if (rij.filter != null && rij.filter.hasAction(action)) {
                        results.remove(j);
                        if (Config.LOGV) Log.v(
                            TAG, "Removing duplicate item from " + j
                            + " due to action " + action + " at " + i);
                        j--;
                        N--;
                    }
                }
            }

            // If the caller didn't request filter information, drop it now
            // so we don't have to marshall/unmarshall it.
            if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
                rii.filter = null;
            }
        }

        // Filter out the caller activity if so requested.
        if (caller != null) {
            N = results.size();
            for (int i=0; i<N; i++) {
                ActivityInfo ainfo = results.get(i).activityInfo;
                if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
                        && caller.getClassName().equals(ainfo.name)) {
                    results.remove(i);
                    break;
                }
            }
        }

        // If the caller didn't request filter information,
        // drop them now so we don't have to
        // marshall/unmarshall it.
        if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
            N = results.size();
            for (int i=0; i<N; i++) {
                results.get(i).filter = null;
            }
        }

        if (Config.LOGV) Log.v(TAG, "Result: " + results);
        return results;
    
public java.util.ListqueryIntentReceivers(android.content.Intent intent, java.lang.String resolvedType, int flags)

        synchronized (mPackages) {
            return (List<ResolveInfo>)mReceivers.
                queryIntent(null, intent, resolvedType, flags);
        }
    
public java.util.ListqueryIntentServices(android.content.Intent intent, java.lang.String resolvedType, int flags)

        ComponentName comp = intent.getComponent();
        if (comp != null) {
            List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
            ServiceInfo si = getServiceInfo(comp, flags);
            if (si != null) {
                ResolveInfo ri = new ResolveInfo();
                ri.serviceInfo = si;
                list.add(ri);
            }
            return list;
        }

        synchronized (mPackages) {
            return (List<ResolveInfo>)mServices.
                queryIntent(null, intent, resolvedType, flags);
        }
    
public java.util.ListqueryPermissionsByGroup(java.lang.String group, int flags)

        synchronized (mPackages) {
            ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
            for (BasePermission p : mSettings.mPermissions.values()) {
                if (group == null) {
                    if (p.perm.info.group == null) {
                        out.add(PackageParser.generatePermissionInfo(p.perm, flags));
                    }
                } else {
                    if (group.equals(p.perm.info.group)) {
                        out.add(PackageParser.generatePermissionInfo(p.perm, flags));
                    }
                }
            }
            
            if (out.size() > 0) {
                return out;
            }
            return mPermissionGroups.containsKey(group) ? out : null;
        }
    
public voidquerySyncProviders(java.util.List outNames, java.util.List outInfo)

        synchronized (mPackages) {
            Iterator<Map.Entry<String, PackageParser.Provider>> i
                = mProviders.entrySet().iterator();

            while (i.hasNext()) {
                Map.Entry<String, PackageParser.Provider> entry = i.next();
                PackageParser.Provider p = entry.getValue();

                if (p.syncable
                        && (!mSafeMode || (p.info.applicationInfo.flags
                                &ApplicationInfo.FLAG_SYSTEM) != 0)) {
                    outNames.add(entry.getKey());
                    outInfo.add(PackageParser.generateProviderInfo(p, 0));
                }
            }
        }
    
voidreadPermission(org.xmlpull.v1.XmlPullParser parser, java.lang.String name)


        name = name.intern();

        BasePermission bp = mSettings.mPermissions.get(name);
        if (bp == null) {
            bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
            mSettings.mPermissions.put(name, bp);
        }
        int outerDepth = parser.getDepth();
        int type;
        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
               && (type != XmlPullParser.END_TAG
                       || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG
                    || type == XmlPullParser.TEXT) {
                continue;
            }

            String tagName = parser.getName();
            if ("group".equals(tagName)) {
                String gidStr = parser.getAttributeValue(null, "gid");
                if (gidStr != null) {
                    int gid = Process.getGidForName(gidStr);
                    bp.gids = appendInt(bp.gids, gid);
                } else {
                    Log.w(TAG, "<group> without gid at "
                            + parser.getPositionDescription());
                }
            }
            XmlUtils.skipCurrentTag(parser);
        }
    
voidreadPermissions()

        // Read permissions from .../etc/permission directory.
        File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
        if (!libraryDir.exists() || !libraryDir.isDirectory()) {
            Log.w(TAG, "No directory " + libraryDir + ", skipping");
            return;
        }
        if (!libraryDir.canRead()) {
            Log.w(TAG, "Directory " + libraryDir + " cannot be read");
            return;
        }

        // Iterate over the files in the directory and scan .xml files
        for (File f : libraryDir.listFiles()) {
            // We'll read platform.xml last
            if (f.getPath().endsWith("etc/permissions/platform.xml")) {
                continue;
            }
            
            if (!f.getPath().endsWith(".xml")) {
                Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
                continue;
            }
            if (!f.canRead()) {
                Log.w(TAG, "Permissions library file " + f + " cannot be read");
                continue;
            }

            readPermissionsFromXml(f);
        }
        
        // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
        final File permFile = new File(Environment.getRootDirectory(),
                "etc/permissions/platform.xml");
        readPermissionsFromXml(permFile);
    
private voidreadPermissionsFromXml(java.io.File permFile)

        
        FileReader permReader = null;
        try {
            permReader = new FileReader(permFile);
        } catch (FileNotFoundException e) {
            Log.w(TAG, "Couldn't find or open permissions file " + permFile);
            return;
        }

        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(permReader);

            XmlUtils.beginDocument(parser, "permissions");

            while (true) {
                XmlUtils.nextElement(parser);
                if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
                    break;
                }

                String name = parser.getName();
                if ("group".equals(name)) {
                    String gidStr = parser.getAttributeValue(null, "gid");
                    if (gidStr != null) {
                        int gid = Integer.parseInt(gidStr);
                        mGlobalGids = appendInt(mGlobalGids, gid);
                    } else {
                        Log.w(TAG, "<group> without gid at "
                                + parser.getPositionDescription());
                    }

                    XmlUtils.skipCurrentTag(parser);
                    continue;
                } else if ("permission".equals(name)) {
                    String perm = parser.getAttributeValue(null, "name");
                    if (perm == null) {
                        Log.w(TAG, "<permission> without name at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    perm = perm.intern();
                    readPermission(parser, perm);
                    
                } else if ("assign-permission".equals(name)) {
                    String perm = parser.getAttributeValue(null, "name");
                    if (perm == null) {
                        Log.w(TAG, "<assign-permission> without name at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    String uidStr = parser.getAttributeValue(null, "uid");
                    if (uidStr == null) {
                        Log.w(TAG, "<assign-permission> without uid at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    int uid = Process.getUidForName(uidStr);
                    if (uid < 0) {
                        Log.w(TAG, "<assign-permission> with unknown uid \""
                                + uidStr + "\" at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    perm = perm.intern();
                    HashSet<String> perms = mSystemPermissions.get(uid);
                    if (perms == null) {
                        perms = new HashSet<String>();
                        mSystemPermissions.put(uid, perms);
                    }
                    perms.add(perm);
                    XmlUtils.skipCurrentTag(parser);
                    
                } else if ("library".equals(name)) {
                    String lname = parser.getAttributeValue(null, "name");
                    String lfile = parser.getAttributeValue(null, "file");
                    if (lname == null) {
                        Log.w(TAG, "<library> without name at "
                                + parser.getPositionDescription());
                    } else if (lfile == null) {
                        Log.w(TAG, "<library> without file at "
                                + parser.getPositionDescription());
                    } else {
                        Log.i(TAG, "Got library " + lname + " in " + lfile);
                        this.mSharedLibraries.put(lname, lfile);
                    }
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                    
                } else {
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }

            }
        } catch (XmlPullParserException e) {
            Log.w(TAG, "Got execption parsing permissions.", e);
        } catch (IOException e) {
            Log.w(TAG, "Got execption parsing permissions.", e);
        }
    
private voidremovePackageDataLI(PackageParser.Package p, com.android.server.PackageManagerService$PackageRemovedInfo outInfo, int flags)

        String packageName = p.packageName;
        outInfo.removedPackage = packageName;
        removePackageLI(p, true);
        // Retrieve object to delete permissions for shared user later on
        PackageSetting deletedPs;
        synchronized (mPackages) {
            deletedPs = mSettings.mPackages.get(packageName);
        }
        if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
            if (mInstaller != null) {
                int retCode = mInstaller.remove(packageName);
                if (retCode < 0) {
                    Log.w(TAG, "Couldn't remove app data or cache directory for package: "
                               + packageName + ", retcode=" + retCode);
                    // we don't consider this to be a failure of the core package deletion
                }
            } else {
                //for emulator
                PackageParser.Package pkg = mPackages.get(packageName);
                File dataDir = new File(pkg.applicationInfo.dataDir);
                dataDir.delete();
            }
            synchronized (mPackages) {
                outInfo.removedUid = mSettings.removePackageLP(packageName);                
            }
        }
        synchronized (mPackages) {
            if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
                // remove permissions associated with package
                mSettings.updateSharedUserPerms (deletedPs);
            }
            // Save settings now
            mSettings.writeLP ();
        }
    
public voidremovePackageFromPreferred(java.lang.String packageName)

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);

        synchronized (mPackages) {
            PackageParser.Package p = mPackages.get(packageName);
            if (p == null) {
                return;
            }
            if (p.mPreferredOrder > 0) {
                PackageSetting ps = (PackageSetting)p.mExtras;
                if (ps != null) {
                    mSettings.mPreferredPackages.remove(ps);
                    p.mPreferredOrder = 0;
                    updatePreferredIndicesLP();
                    mSettings.writeLP();
                }
            }
        }
    
voidremovePackageLI(PackageParser.Package pkg, boolean chatty)

        if (chatty && Config.LOGD) Log.d(
            TAG, "Removing package " + pkg.applicationInfo.packageName );

        synchronized (mPackages) {
            if (pkg.mPreferredOrder > 0) {
                mSettings.mPreferredPackages.remove(pkg);
                pkg.mPreferredOrder = 0;
                updatePreferredIndicesLP();
            }
    
            clearPackagePreferredActivitiesLP(pkg.packageName);
    
            mPackages.remove(pkg.applicationInfo.packageName);
            if (pkg.mPath != null) {
                mAppDirs.remove(pkg.mPath);
            }
    
            PackageSetting ps = (PackageSetting)pkg.mExtras;
            if (ps != null && ps.sharedUser != null) {
                // XXX don't do this until the data is removed.
                if (false) {
                    ps.sharedUser.packages.remove(ps);
                    if (ps.sharedUser.packages.size() == 0) {
                        // Remove.
                    }
                }
            }
    
            int N = pkg.providers.size();
            StringBuilder r = null;
            int i;
            for (i=0; i<N; i++) {
                PackageParser.Provider p = pkg.providers.get(i);
                mProvidersByComponent.remove(new ComponentName(p.info.packageName,
                        p.info.name));
                if (p.info.authority == null) {
                    
                    /* The is another ContentProvider with this authority when
                     * this app was installed so this authority is null,
                     * Ignore it as we don't have to unregister the provider.
                     */
                    continue;
                }
                String names[] = p.info.authority.split(";");
                for (int j = 0; j < names.length; j++) {
                    if (mProviders.get(names[j]) == p) {
                        mProviders.remove(names[j]);
                        if (chatty && Config.LOGD) Log.d(
                            TAG, "Unregistered content provider: " + names[j] +
                            ", className = " + p.info.name +
                            ", isSyncable = " + p.info.isSyncable);
                    }
                }
                if (chatty) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(p.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Providers: " + r);
            }
    
            N = pkg.services.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Service s = pkg.services.get(i);
                mServices.removeService(s);
                if (chatty) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(s.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Services: " + r);
            }
    
            N = pkg.receivers.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Activity a = pkg.receivers.get(i);
                mReceivers.removeActivity(a, "receiver");
                if (chatty) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(a.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Receivers: " + r);
            }
    
            N = pkg.activities.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Activity a = pkg.activities.get(i);
                mActivities.removeActivity(a, "activity");
                if (chatty) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(a.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Activities: " + r);
            }
    
            N = pkg.permissions.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Permission p = pkg.permissions.get(i);
                boolean tree = false;
                BasePermission bp = mSettings.mPermissions.get(p.info.name);
                if (bp == null) {
                    tree = true;
                    bp = mSettings.mPermissionTrees.get(p.info.name);
                }
                if (bp != null && bp.perm == p) {
                    if (bp.type != BasePermission.TYPE_BUILTIN) {
                        if (tree) {
                            mSettings.mPermissionTrees.remove(p.info.name);
                        } else {
                            mSettings.mPermissions.remove(p.info.name);
                        }
                    } else {
                        bp.perm = null;
                    }
                    if (chatty) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ");
                        }
                        r.append(p.info.name);
                    }
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Permissions: " + r);
            }
    
            N = pkg.instrumentation.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Instrumentation a = pkg.instrumentation.get(i);
                mInstrumentation.remove(a.component);
                if (chatty) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(a.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Instrumentation: " + r);
            }
        }
    
public voidremovePermission(java.lang.String name)

        synchronized (mPackages) {
            checkPermissionTreeLP(name);
            BasePermission bp = mSettings.mPermissions.get(name);
            if (bp != null) {
                if (bp.type != BasePermission.TYPE_DYNAMIC) {
                    throw new SecurityException(
                            "Not allowed to modify non-dynamic permission "
                            + name);
                }
                mSettings.mPermissions.remove(name);
                mSettings.writeLP();
            }
        }
    
private voidreplaceNonSystemPackageLI(PackageParser.Package deletedPackage, java.io.File tmpPackageFile, java.lang.String destFilePath, java.io.File destPackageFile, java.io.File destResourceFile, PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, com.android.server.PackageManagerService$PackageInstalledInfo res)

        PackageParser.Package newPackage = null;
        String pkgName = deletedPackage.packageName;
        boolean deletedPkg = true;
        boolean updatedSettings = false;
        int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE;
        // First delete the existing package while retaining the data directory
        if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
                res.removedInfo)) {
            // If the existing package was'nt successfully deleted
            res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
            deletedPkg = false;
        } else {
            // Successfully deleted the old package. Now proceed with re-installation
            mLastScanError = PackageManager.INSTALL_SUCCEEDED;
            newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
                    destResourceFile, pkg, parseFlags,
                    SCAN_MONITOR | SCAN_FORCE_DEX
                    | SCAN_UPDATE_SIGNATURE 
                    | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
                    | (newInstall ? SCAN_NEW_INSTALL : 0));
            if (newPackage == null) {
                    Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
                if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
                    res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
                }
            } else {
                updateSettingsLI(pkgName, tmpPackageFile, 
                        destFilePath, destPackageFile,
                        destResourceFile, pkg, 
                        newPackage,
                        true,
                        forwardLocked,  
                        res);
                updatedSettings = true;
            }
        }

        if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
            // If we deleted an exisiting package, the old source and resource files that we
            // were keeping around in case we needed them (see below) can now be deleted
            final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
            final ApplicationInfo installedPackageAppInfo =
                newPackage.applicationInfo;
            if (!deletedPackageAppInfo.sourceDir
                    .equals(installedPackageAppInfo.sourceDir)) {
                new File(deletedPackageAppInfo.sourceDir).delete();
            }
            if (!deletedPackageAppInfo.publicSourceDir
                    .equals(installedPackageAppInfo.publicSourceDir)) {
                new File(deletedPackageAppInfo.publicSourceDir).delete();
            }
            //update signature on the new package setting
            //this should always succeed, since we checked the
            //signature earlier.
            synchronized(mPackages) {
                verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
                        parseFlags, true);
            }
        } else {
            // remove package from internal structures.  Note that we want deletePackageX to
            // delete the package data and cache directories that it created in
            // scanPackageLocked, unless those directories existed before we even tried to
            // install.
            if(updatedSettings) {
                deletePackageLI(
                        pkgName, true,
                        PackageManager.DONT_DELETE_DATA,
                                res.removedInfo);
            }
            // Since we failed to install the new package we need to restore the old
            // package that we deleted.
            if(deletedPkg) {
                installPackageLI(
                        Uri.fromFile(new File(deletedPackage.mPath)),
                        isForwardLocked(deletedPackage)
                        ? PackageManager.FORWARD_LOCK_PACKAGE
                                : 0, false);
            }
        }
    
private voidreplacePackageLI(java.lang.String pkgName, java.io.File tmpPackageFile, java.lang.String destFilePath, java.io.File destPackageFile, java.io.File destResourceFile, PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, com.android.server.PackageManagerService$PackageInstalledInfo res)

        PackageParser.Package deletedPackage;
        // First find the old package info and check signatures
        synchronized(mPackages) {
            deletedPackage = mPackages.get(pkgName);
            if(checkSignaturesLP(pkg, deletedPackage) != PackageManager.SIGNATURE_MATCH) {
                res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
                return;
            }
        }
        boolean sysPkg = ((deletedPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
        if(sysPkg) {
            replaceSystemPackageLI(deletedPackage, 
                    tmpPackageFile, destFilePath, 
                    destPackageFile, destResourceFile, pkg, forwardLocked,
                    newInstall, res);
        } else {
            replaceNonSystemPackageLI(deletedPackage, tmpPackageFile, destFilePath, 
                    destPackageFile, destResourceFile, pkg, forwardLocked,
                    newInstall, res);
        }
    
private voidreplaceSystemPackageLI(PackageParser.Package deletedPackage, java.io.File tmpPackageFile, java.lang.String destFilePath, java.io.File destPackageFile, java.io.File destResourceFile, PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, com.android.server.PackageManagerService$PackageInstalledInfo res)

        PackageParser.Package newPackage = null;
        boolean updatedSettings = false;
        int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE |
                PackageParser.PARSE_IS_SYSTEM;
        String packageName = deletedPackage.packageName;
        res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
        if (packageName == null) {
            Log.w(TAG, "Attempt to delete null packageName.");
            return;
        }
        PackageParser.Package oldPkg;
        PackageSetting oldPkgSetting;
        synchronized (mPackages) {
            oldPkg = mPackages.get(packageName);
            oldPkgSetting = mSettings.mPackages.get(packageName);  
            if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
                    (oldPkgSetting == null)) {
                Log.w(TAG, "Could'nt find package:"+packageName+" information");
                return;
            }
        }
        res.removedInfo.uid = oldPkg.applicationInfo.uid;
        res.removedInfo.removedPackage = packageName;
        // Remove existing system package
        removePackageLI(oldPkg, true);
        synchronized (mPackages) {
            res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
        }

        // Successfully disabled the old package. Now proceed with re-installation
        mLastScanError = PackageManager.INSTALL_SUCCEEDED;
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
        newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
                destResourceFile, pkg, parseFlags,
                SCAN_MONITOR | SCAN_FORCE_DEX
                | SCAN_UPDATE_SIGNATURE 
                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
                | (newInstall ? SCAN_NEW_INSTALL : 0));
        if (newPackage == null) {
            Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
            if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
                res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
            }
        } else {
            updateSettingsLI(packageName, tmpPackageFile, 
                    destFilePath, destPackageFile,
                    destResourceFile, pkg, 
                    newPackage,
                    true,
                    forwardLocked,  
                    res);
            updatedSettings = true;
        }

        if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
            //update signature on the new package setting
            //this should always succeed, since we checked the
            //signature earlier.
            synchronized(mPackages) {
                verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
                        parseFlags, true);
            }
        } else {
            // Re installation failed. Restore old information
            // Remove new pkg information
            removePackageLI(newPackage, true);
            // Add back the old system package
            scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath, 
                    oldPkgSetting.resourcePath,
                    oldPkg, parseFlags,
                    SCAN_MONITOR
                    | SCAN_UPDATE_SIGNATURE);
            // Restore the old system information in Settings
            synchronized(mPackages) {
                if(updatedSettings) {
                    mSettings.enableSystemPackageLP(packageName);
                }
                mSettings.writeLP();
            }
        }
    
private static voidreportSettingsProblem(int priority, java.lang.String msg)

        try {
            File dataDir = Environment.getDataDirectory();
            File systemDir = new File(dataDir, "system");
            File fname = new File(systemDir, "uiderrors.txt");
            FileOutputStream out = new FileOutputStream(fname, true);
            PrintWriter pw = new PrintWriter(out);
            pw.println(msg);
            pw.close();
            FileUtils.setPermissions(
                    fname.toString(),
                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
                    -1, -1);
        } catch (java.io.IOException e) {
        }
        Log.println(priority, TAG, msg);
    
public android.content.pm.ProviderInforesolveContentProvider(java.lang.String name, int flags)

        synchronized (mPackages) {
            final PackageParser.Provider provider = mProviders.get(name);
            return provider != null
                    && mSettings.isEnabledLP(provider.info, flags)
                    && (!mSafeMode || (provider.info.applicationInfo.flags
                            &ApplicationInfo.FLAG_SYSTEM) != 0)
                    ? PackageParser.generateProviderInfo(provider, flags)
                    : null;
        }
    
public android.content.pm.ResolveInforesolveIntent(android.content.Intent intent, java.lang.String resolvedType, int flags)

        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
        if (query != null) {
            final int N = query.size();
            if (N == 1) {
                return query.get(0);
            } else if (N > 1) {
                // If there is more than one activity with the same priority,
                // then let the user decide between them.
                ResolveInfo r0 = query.get(0);
                ResolveInfo r1 = query.get(1);
                if (false) {
                    System.out.println(r0.activityInfo.name +
                                       "=" + r0.priority + " vs " +
                                       r1.activityInfo.name +
                                       "=" + r1.priority);
                }
                // If the first activity has a higher priority, or a different
                // default, then it is always desireable to pick it.
                if (r0.priority != r1.priority
                        || r0.preferredOrder != r1.preferredOrder
                        || r0.isDefault != r1.isDefault) {
                    return query.get(0);
                }
                // If we have saved a preference for a preferred activity for
                // this Intent, use that.
                ResolveInfo ri = findPreferredActivity(intent, resolvedType,
                        flags, query, r0.priority);
                if (ri != null) {
                    return ri;
                }
                return mResolveInfo;
            }
        }
        return null;
    
public android.content.pm.ResolveInforesolveService(android.content.Intent intent, java.lang.String resolvedType, int flags)

        List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
                flags);
        if (query != null) {
            if (query.size() >= 1) {
                // If there is more than one service with the same priority,
                // just arbitrarily pick the first one.
                return query.get(0);
            }
        }
        return null;
    
private voidscanDirLI(java.io.File dir, int flags, int scanMode)

        Log.d(TAG, "Scanning app dir " + dir);

        String[] files = dir.list();

        int i;
        for (i=0; i<files.length; i++) {
            File file = new File(dir, files[i]);
            PackageParser.Package pkg = scanPackageLI(file, file, file, 
                    flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
        }
    
private PackageParser.PackagescanPackageLI(java.io.File scanFile, java.io.File destCodeFile, java.io.File destResourceFile, int parseFlags, int scanMode)

        mLastScanError = PackageManager.INSTALL_SUCCEEDED;
        parseFlags |= mDefParseFlags;
        PackageParser pp = new PackageParser(scanFile.getPath());
        pp.setSeparateProcesses(mSeparateProcesses);
        pp.setSdkVersion(mSdkVersion);
        final PackageParser.Package pkg = pp.parsePackage(scanFile,
                destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
        if (pkg == null) {
            mLastScanError = pp.getParseError();
            return null;
        }
        PackageSetting ps;
        PackageSetting updatedPkg;
        synchronized (mPackages) {
            ps = mSettings.peekPackageLP(pkg.packageName,
                    scanFile.toString());
            updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
        }
        if (updatedPkg != null) {
            // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
            parseFlags |= PackageParser.PARSE_IS_SYSTEM;
        }
        if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
            // Check for updated system applications here
            if ((updatedPkg != null) && (ps == null)) {
                // The system package has been updated and the code path does not match
                // Ignore entry. Just return
                Log.w(TAG, "Package:" + pkg.packageName + 
                        " has been updated. Ignoring the one from path:"+scanFile);
                mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
                return null;
            }
        }
        if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
            Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
            return null;
        }
        // The apk is forward locked (not public) if its code and resources
        // are kept in different files.
        if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
            scanMode |= SCAN_FORWARD_LOCKED;
        }
        // Note that we invoke the following method only if we are about to unpack an application
        return scanPackageLI(scanFile, destCodeFile, destResourceFile,
                pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
    
private PackageParser.PackagescanPackageLI(java.io.File scanFile, java.io.File destCodeFile, java.io.File destResourceFile, PackageParser.Package pkg, int parseFlags, int scanMode)


        mScanningPath = scanFile;
        if (pkg == null) {
            mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
            return null;
        }

        final String pkgName = pkg.applicationInfo.packageName;
        if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
        }

        if (pkgName.equals("android")) {
            synchronized (mPackages) {
                if (mAndroidApplication != null) {
                    Log.w(TAG, "*************************************************");
                    Log.w(TAG, "Core android package being redefined.  Skipping.");
                    Log.w(TAG, " file=" + mScanningPath);
                    Log.w(TAG, "*************************************************");
                    mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
                    return null;
                }
    
                // Set up information for our fall-back user intent resolution
                // activity.
                mPlatformPackage = pkg;
                pkg.mVersionCode = mSdkVersion;
                mAndroidApplication = pkg.applicationInfo;
                mResolveActivity.applicationInfo = mAndroidApplication;
                mResolveActivity.name = ResolverActivity.class.getName();
                mResolveActivity.packageName = mAndroidApplication.packageName;
                mResolveActivity.processName = mAndroidApplication.processName;
                mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
                mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
                mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
                mResolveActivity.exported = true;
                mResolveActivity.enabled = true;
                mResolveInfo.activityInfo = mResolveActivity;
                mResolveInfo.priority = 0;
                mResolveInfo.preferredOrder = 0;
                mResolveInfo.match = 0;
                mResolveComponentName = new ComponentName(
                        mAndroidApplication.packageName, mResolveActivity.name);
            }
        }

        if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
                TAG, "Scanning package " + pkgName);
        if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
            Log.w(TAG, "*************************************************");
            Log.w(TAG, "Application package " + pkgName
                    + " already installed.  Skipping duplicate.");
            Log.w(TAG, "*************************************************");
            mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
            return null;
        }

        SharedUserSetting suid = null;
        PackageSetting pkgSetting = null;
        
        boolean removeExisting = false;
        
        synchronized (mPackages) {
            // Check all shared libraries and map to their actual file path.
            if (pkg.usesLibraryFiles != null) {
                for (int i=0; i<pkg.usesLibraryFiles.length; i++) {
                    String file = mSharedLibraries.get(pkg.usesLibraryFiles[i]);
                    if (file == null) {
                        Log.e(TAG, "Package " + pkg.packageName
                                + " requires unavailable shared library "
                                + pkg.usesLibraryFiles[i] + "; ignoring!");
                        mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
                        return null;
                    }
                    pkg.usesLibraryFiles[i] = file;
                }
            }
            
            if (pkg.mSharedUserId != null) {
                suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
                        pkg.applicationInfo.flags, true);
                if (suid == null) {
                    Log.w(TAG, "Creating application package " + pkgName
                            + " for shared user failed");
                    mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                    return null;
                }
                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
                    Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
                            + suid.userId + "): packages=" + suid.packages);
                }
            }
    
            // Just create the setting, don't add it yet
            pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
                            destResourceFile, pkg.applicationInfo.flags, true, false);
            if (pkgSetting == null) {
                Log.w(TAG, "Creating application package " + pkgName + " failed");
                mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                return null;
            }
            if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
                pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
            }
        
            pkg.applicationInfo.uid = pkgSetting.userId;
            pkg.mExtras = pkgSetting;
    
            if (!verifySignaturesLP(pkgSetting, pkg, parseFlags, 
                    (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
                if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
                    mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
                    return null;
                }
                // The signature has changed, but this package is in the system
                // image...  let's recover!
                pkgSetting.signatures.mSignatures = pkg.mSignatures;
                // However...  if this package is part of a shared user, but it
                // doesn't match the signature of the shared user, let's fail.
                // What this means is that you can't change the signatures
                // associated with an overall shared user, which doesn't seem all
                // that unreasonable.
                if (pkgSetting.sharedUser != null) {
                    if (!pkgSetting.sharedUser.signatures.mergeSignatures(
                            pkg.mSignatures, false)) {
                        mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
                        return null;
                    }
                }
                removeExisting = true;
            }
            
            // Verify that this new package doesn't have any content providers
            // that conflict with existing packages.  Only do this if the
            // package isn't already installed, since we don't want to break
            // things that are installed.
            if ((scanMode&SCAN_NEW_INSTALL) != 0) {
                int N = pkg.providers.size();
                int i;
                for (i=0; i<N; i++) {
                    PackageParser.Provider p = pkg.providers.get(i);
                    String names[] = p.info.authority.split(";");
                    for (int j = 0; j < names.length; j++) {
                        if (mProviders.containsKey(names[j])) {
                            PackageParser.Provider other = mProviders.get(names[j]);
                            Log.w(TAG, "Can't install because provider name " + names[j] +
                                    " (in package " + pkg.applicationInfo.packageName +
                                    ") is already used by "
                                    + ((other != null && other.component != null)
                                            ? other.component.getPackageName() : "?"));
                            mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
                            return null;
                        }
                    }
                }
            }
        }

        if (removeExisting) {
            if (mInstaller != null) {
                int ret = mInstaller.remove(pkgName);
                if (ret != 0) {
                    String msg = "System package " + pkg.packageName
                            + " could not have data directory erased after signature change.";
                    reportSettingsProblem(Log.WARN, msg);
                    mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
                    return null;
                }
            }
            Log.w(TAG, "System package " + pkg.packageName
                    + " signature changed: existing data removed.");
            mLastScanError = PackageManager.INSTALL_SUCCEEDED;
        }
        
        long scanFileTime = scanFile.lastModified();
        final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
        final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
        pkg.applicationInfo.processName = fixProcessName(
                pkg.applicationInfo.packageName,
                pkg.applicationInfo.processName,
                pkg.applicationInfo.uid);
        pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString;

        File dataPath;
        if (mPlatformPackage == pkg) {
            // The system package is special.
            dataPath = new File (Environment.getDataDirectory(), "system");
            pkg.applicationInfo.dataDir = dataPath.getPath();
        } else {
            // This is a normal package, need to make its data directory.
            dataPath = new File(mAppDataDir, pkgName);
            if (dataPath.exists()) {
                mOutPermissions[1] = 0;
                FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
                if (mOutPermissions[1] == pkg.applicationInfo.uid
                        || !Process.supportsProcesses()) {
                    pkg.applicationInfo.dataDir = dataPath.getPath();
                } else {
                    boolean recovered = false;
                    if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
                        // If this is a system app, we can at least delete its
                        // current data so the application will still work.
                        if (mInstaller != null) {
                            int ret = mInstaller.remove(pkgName);
                            if(ret >= 0) {
                                // Old data gone!
                                String msg = "System package " + pkg.packageName
                                        + " has changed from uid: "
                                        + mOutPermissions[1] + " to "
                                        + pkg.applicationInfo.uid + "; old data erased";
                                reportSettingsProblem(Log.WARN, msg);
                                recovered = true;
                                
                                // And now re-install the app.
                                ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
                                        pkg.applicationInfo.uid);
                                if (ret == -1) {
                                    // Ack should not happen!
                                    msg = "System package " + pkg.packageName
                                            + " could not have data directory re-created after delete.";
                                    reportSettingsProblem(Log.WARN, msg);
                                    mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                                    return null;
                                }
                            }
                        } 
                        if (!recovered) {
                            mHasSystemUidErrors = true;
                        }
                    }
                    if (!recovered) {
                        pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
                            + pkg.applicationInfo.uid + "/fs_"
                            + mOutPermissions[1];
                        String msg = "Package " + pkg.packageName
                                + " has mismatched uid: "
                                + mOutPermissions[1] + " on disk, "
                                + pkg.applicationInfo.uid + " in settings";
                        synchronized (mPackages) {
                            if (!mReportedUidError) {
                                mReportedUidError = true;
                                msg = msg + "; read messages:\n"
                                        + mSettings.getReadMessagesLP();
                            }
                            reportSettingsProblem(Log.ERROR, msg);
                        }
                    }
                }
                pkg.applicationInfo.dataDir = dataPath.getPath();
            } else {
                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
                    Log.v(TAG, "Want this data dir: " + dataPath);
                //invoke installer to do the actual installation
                if (mInstaller != null) {
                    int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
                            pkg.applicationInfo.uid);
                    if(ret < 0) {
                        // Error from installer
                        mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                        return null;
                    }
                } else {
                    dataPath.mkdirs();
                    if (dataPath.exists()) {
                        FileUtils.setPermissions(
                            dataPath.toString(),
                            FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
                            pkg.applicationInfo.uid, pkg.applicationInfo.uid);
                    }
                }
                if (dataPath.exists()) {
                    pkg.applicationInfo.dataDir = dataPath.getPath();
                } else {
                    Log.w(TAG, "Unable to create data directory: " + dataPath);
                    pkg.applicationInfo.dataDir = null;
                }
            }
        }

        // Perform shared library installation and dex validation and
        // optimization, if this is not a system app.
        if (mInstaller != null) {
            String path = scanFile.getPath();
            if (scanFileNewer) {
                Log.i(TAG, path + " changed; unpacking");
                try {
                    cachePackageSharedLibsLI(pkg, dataPath, scanFile);
                } catch (IOException e) {
                    Log.e(TAG, "Failure extracting shared libs", e);
                    if(mInstaller != null) {
                        mInstaller.remove(pkgName);
                    } else {
                        dataPath.delete();
                    }
                    mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                    return null;
                }
            }

            if ((scanMode&SCAN_NO_DEX) == 0
                    && (pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
                int ret = 0;
                try {
                    if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
                        ret = mInstaller.dexopt(path, pkg.applicationInfo.uid, 
                                (scanMode&SCAN_FORWARD_LOCKED) == 0);
                    }
                } catch (FileNotFoundException e) {
                    Log.w(TAG, "Apk not found for dexopt: " + path);
                    ret = -1;
                } catch (IOException e) {
                    Log.w(TAG, "Exception reading apk: " + path, e);
                    ret = -1;
                }
                if (ret < 0) {
                    //error from installer
                    mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
                    return null;
                }
            }
        }
        
        if (mFactoryTest && pkg.requestedPermissions.contains(
                android.Manifest.permission.FACTORY_TEST)) {
            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
        }

        if ((scanMode&SCAN_MONITOR) != 0) {
            pkg.mPath = destCodeFile.getAbsolutePath();
            mAppDirs.put(pkg.mPath, pkg);
        }

        synchronized (mPackages) {
            // We don't expect installation to fail beyond this point
            // Add the new setting to mSettings
            mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid);
            // Add the new setting to mPackages
            mPackages.put(pkg.applicationInfo.packageName, pkg);          
            int N = pkg.providers.size();
            StringBuilder r = null;
            int i;
            for (i=0; i<N; i++) {
                PackageParser.Provider p = pkg.providers.get(i);
                p.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        p.info.processName, pkg.applicationInfo.uid);
                mProvidersByComponent.put(new ComponentName(p.info.packageName,
                        p.info.name), p);
                p.syncable = p.info.isSyncable;
                String names[] = p.info.authority.split(";");
                p.info.authority = null;
                for (int j = 0; j < names.length; j++) {
                    if (j == 1 && p.syncable) {
                        // We only want the first authority for a provider to possibly be
                        // syncable, so if we already added this provider using a different
                        // authority clear the syncable flag. We copy the provider before
                        // changing it because the mProviders object contains a reference
                        // to a provider that we don't want to change.
                        // Only do this for the second authority since the resulting provider
                        // object can be the same for all future authorities for this provider.
                        p = new PackageParser.Provider(p);
                        p.syncable = false;
                    }
                    if (!mProviders.containsKey(names[j])) {
                        mProviders.put(names[j], p);
                        if (p.info.authority == null) {
                            p.info.authority = names[j];
                        } else {
                            p.info.authority = p.info.authority + ";" + names[j];
                        }
                        if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
                            Log.d(TAG, "Registered content provider: " + names[j] +
                            ", className = " + p.info.name +
                            ", isSyncable = " + p.info.isSyncable);
                    } else {
                        PackageParser.Provider other = mProviders.get(names[j]);
                        Log.w(TAG, "Skipping provider name " + names[j] +
                              " (in package " + pkg.applicationInfo.packageName +
                              "): name already used by "
                              + ((other != null && other.component != null)
                                      ? other.component.getPackageName() : "?"));
                    }
                }
                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(p.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Providers: " + r);
            }
    
            N = pkg.services.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Service s = pkg.services.get(i);
                s.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        s.info.processName, pkg.applicationInfo.uid);
                mServices.addService(s);
                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(s.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Services: " + r);
            }
    
            N = pkg.receivers.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Activity a = pkg.receivers.get(i);
                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        a.info.processName, pkg.applicationInfo.uid);
                mReceivers.addActivity(a, "receiver");
                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(a.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Receivers: " + r);
            }
    
            N = pkg.activities.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Activity a = pkg.activities.get(i);
                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        a.info.processName, pkg.applicationInfo.uid);
                mActivities.addActivity(a, "activity");
                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(a.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Activities: " + r);
            }
    
            N = pkg.permissionGroups.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
                PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
                if (cur == null) {
                    mPermissionGroups.put(pg.info.name, pg);
                    if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ");
                        }
                        r.append(pg.info.name);
                    }
                } else {
                    Log.w(TAG, "Permission group " + pg.info.name + " from package "
                            + pg.info.packageName + " ignored: original from "
                            + cur.info.packageName);
                    if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ");
                        }
                        r.append("DUP:");
                        r.append(pg.info.name);
                    }
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Permission Groups: " + r);
            }
    
            N = pkg.permissions.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Permission p = pkg.permissions.get(i);
                HashMap<String, BasePermission> permissionMap =
                        p.tree ? mSettings.mPermissionTrees
                        : mSettings.mPermissions;
                p.group = mPermissionGroups.get(p.info.group);
                if (p.info.group == null || p.group != null) {
                    BasePermission bp = permissionMap.get(p.info.name);
                    if (bp == null) {
                        bp = new BasePermission(p.info.name, p.info.packageName,
                                BasePermission.TYPE_NORMAL);
                        permissionMap.put(p.info.name, bp);
                    }
                    if (bp.perm == null) {
                        if (bp.sourcePackage == null
                                || bp.sourcePackage.equals(p.info.packageName)) {
                            BasePermission tree = findPermissionTreeLP(p.info.name);
                            if (tree == null
                                    || tree.sourcePackage.equals(p.info.packageName)) {
                                bp.perm = p;
                                bp.uid = pkg.applicationInfo.uid;
                                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                                    if (r == null) {
                                        r = new StringBuilder(256);
                                    } else {
                                        r.append(' ");
                                    }
                                    r.append(p.info.name);
                                }
                            } else {
                                Log.w(TAG, "Permission " + p.info.name + " from package "
                                        + p.info.packageName + " ignored: base tree "
                                        + tree.name + " is from package "
                                        + tree.sourcePackage);
                            }
                        } else {
                            Log.w(TAG, "Permission " + p.info.name + " from package "
                                    + p.info.packageName + " ignored: original from "
                                    + bp.sourcePackage);
                        }
                    } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ");
                        }
                        r.append("DUP:");
                        r.append(p.info.name);
                    }
                } else {
                    Log.w(TAG, "Permission " + p.info.name + " from package "
                            + p.info.packageName + " ignored: no group "
                            + p.group);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Permissions: " + r);
            }
    
            N = pkg.instrumentation.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Instrumentation a = pkg.instrumentation.get(i);
                a.info.packageName = pkg.applicationInfo.packageName;
                a.info.sourceDir = pkg.applicationInfo.sourceDir;
                a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
                a.info.dataDir = pkg.applicationInfo.dataDir;
                mInstrumentation.put(a.component, a);
                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ");
                    }
                    r.append(a.info.name);
                }
            }
            if (r != null) {
                if (Config.LOGD) Log.d(TAG, "  Instrumentation: " + r);
            }
    
            pkgSetting.setTimeStamp(scanFileTime);
        }
        
        return pkg;
    
private static final voidsendPackageBroadcast(java.lang.String action, java.lang.String pkg, android.os.Bundle extras)


              
        IActivityManager am = ActivityManagerNative.getDefault();
        if (am != null) {
            try {
                final Intent intent = new Intent(action,
                        pkg != null ? Uri.fromParts("package", pkg, null) : null);
                if (extras != null) {
                    intent.putExtras(extras);
                }
                am.broadcastIntent(
                    null, intent,
                            null, null, 0, null, null, null, false, false);
            } catch (RemoteException ex) {
            }
        }
    
public voidsetApplicationEnabledSetting(java.lang.String appPackageName, int newState, int flags)

        setEnabledSetting(appPackageName, null, newState, flags);
    
public voidsetComponentEnabledSetting(android.content.ComponentName componentName, int newState, int flags)

        setEnabledSetting(componentName.getPackageName(),
                componentName.getClassName(), newState, flags);
    
private voidsetEnabledSetting(java.lang.String packageNameStr, java.lang.String classNameStr, int newState, int flags)

        if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
              || newState == COMPONENT_ENABLED_STATE_ENABLED
              || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
            throw new IllegalArgumentException("Invalid new component state: "
                    + newState);
        }
        PackageSetting pkgSetting;
        final int uid = Binder.getCallingUid();
        final int permission = mContext.checkCallingPermission(
                android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
        final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
        int packageUid = -1;
        synchronized (mPackages) {
            pkgSetting = mSettings.mPackages.get(packageNameStr);
            if (pkgSetting == null) {
                if (classNameStr == null) {
                    throw new IllegalArgumentException(
                            "Unknown package: " + packageNameStr);
                }
                throw new IllegalArgumentException(
                        "Unknown component: " + packageNameStr
                        + "/" + classNameStr);
            }
            if (!allowedByPermission && (uid != pkgSetting.userId)) {
                throw new SecurityException(
                        "Permission Denial: attempt to change component state from pid="
                        + Binder.getCallingPid()
                        + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
            }
            packageUid = pkgSetting.userId;
            if (classNameStr == null) {
                // We're dealing with an application/package level state change
                pkgSetting.enabled = newState;
            } else {
                // We're dealing with a component level state change
                switch (newState) {
                case COMPONENT_ENABLED_STATE_ENABLED:
                    pkgSetting.enableComponentLP(classNameStr);
                    break;
                case COMPONENT_ENABLED_STATE_DISABLED:
                    pkgSetting.disableComponentLP(classNameStr);
                    break;
                case COMPONENT_ENABLED_STATE_DEFAULT:
                    pkgSetting.restoreComponentLP(classNameStr);
                    break;
                default:
                    Log.e(TAG, "Invalid new component state: " + newState);
                }
            }
            mSettings.writeLP();
        }
        
        long callingId = Binder.clearCallingIdentity();
        try {
            Bundle extras = new Bundle(2);
            extras.putBoolean(Intent.EXTRA_DONT_KILL_APP,
                    (flags&PackageManager.DONT_KILL_APP) != 0);
            extras.putInt(Intent.EXTRA_UID, packageUid);
            sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageNameStr, extras);
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
    
private intsetPermissionsLI(java.lang.String pkgName, PackageParser.Package newPackage, java.lang.String destFilePath, java.io.File destResourceFile, boolean forwardLocked)

        int retCode;
        if (forwardLocked) {
            try {
                extractPublicFiles(newPackage, destResourceFile);
            } catch (IOException e) {
                Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
                           " forward-locked app.");
                return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
            } finally {
                //TODO clean up the extracted public files
            }
            if (mInstaller != null) {
                retCode = mInstaller.setForwardLockPerm(pkgName,
                        newPackage.applicationInfo.uid);
            } else {
                final int filePermissions =
                        FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
                retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
                                                   newPackage.applicationInfo.uid);
            }
        } else {
            final int filePermissions =
                    FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
                    |FileUtils.S_IROTH;
            retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
        }
        if (retCode != 0) {
            Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
                       + ". The return code was: " + retCode);
        }
        return PackageManager.INSTALL_SUCCEEDED;
    
static java.lang.String[]splitString(java.lang.String str, char sep)

        int count = 1;
        int i = 0;
        while ((i=str.indexOf(sep, i)) >= 0) {
            count++;
            i++;
        }
        
        String[] res = new String[count];
        i=0;
        count = 0;
        int lastI=0;
        while ((i=str.indexOf(sep, i)) >= 0) {
            res[count] = str.substring(lastI, i);
            count++;
            i++;
            lastI = i;
        }
        res[count] = str.substring(lastI, str.length());
        return res;
    
public voidsystemReady()

        mSystemReady = true;
    
private voidupdatePermissionsLP()

        // Make sure there are no dangling permission trees.
        Iterator<BasePermission> it = mSettings.mPermissionTrees
                .values().iterator();
        while (it.hasNext()) {
            BasePermission bp = it.next();
            if (bp.perm == null) {
                Log.w(TAG, "Removing dangling permission tree: " + bp.name
                        + " from package " + bp.sourcePackage);
                it.remove();
            }
        }

        // Make sure all dynamic permissions have been assigned to a package,
        // and make sure there are no dangling permissions.
        it = mSettings.mPermissions.values().iterator();
        while (it.hasNext()) {
            BasePermission bp = it.next();
            if (bp.type == BasePermission.TYPE_DYNAMIC) {
                if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
                        + bp.name + " pkg=" + bp.sourcePackage
                        + " info=" + bp.pendingInfo);
                if (bp.perm == null && bp.pendingInfo != null) {
                    BasePermission tree = findPermissionTreeLP(bp.name);
                    if (tree != null) {
                        bp.perm = new PackageParser.Permission(tree.perm.owner,
                                new PermissionInfo(bp.pendingInfo));
                        bp.perm.info.packageName = tree.perm.info.packageName;
                        bp.perm.info.name = bp.name;
                        bp.uid = tree.uid;
                    }
                }
            }
            if (bp.perm == null) {
                Log.w(TAG, "Removing dangling permission: " + bp.name
                        + " from package " + bp.sourcePackage);
                it.remove();
            }
        }

        // Now update the permissions for all packages, in particular
        // replace the granted permissions of the system packages.
        for (PackageParser.Package pkg : mPackages.values()) {
            grantPermissionsLP(pkg, false);
        }
    
private voidupdatePreferredIndicesLP()

        final ArrayList<PackageSetting> pkgs
                = mSettings.mPreferredPackages;
        final int N = pkgs.size();
        for (int i=0; i<N; i++) {
            pkgs.get(i).pkg.mPreferredOrder = N - i;
        }
    
private voidupdateSettingsLI(java.lang.String pkgName, java.io.File tmpPackageFile, java.lang.String destFilePath, java.io.File destPackageFile, java.io.File destResourceFile, PackageParser.Package pkg, PackageParser.Package newPackage, boolean replacingExistingPackage, boolean forwardLocked, com.android.server.PackageManagerService$PackageInstalledInfo res)

        synchronized (mPackages) {
            //write settings. the installStatus will be incomplete at this stage.
            //note that the new package setting would have already been
            //added to mPackages. It hasn't been persisted yet.
            mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
            mSettings.writeLP();
        }

        int retCode = 0;
        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
            retCode = mInstaller.movedex(tmpPackageFile.toString(),
                    destPackageFile.toString());
            if (retCode != 0) {
                Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
                res.returnCode =  PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                return;
            }
        }
        // XXX There are probably some big issues here: upon doing
        // the rename, we have reached the point of no return (the
        // original .apk is gone!), so we can't fail.  Yet... we can.
        if (!tmpPackageFile.renameTo(destPackageFile)) {
            Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
            res.returnCode =  PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
        } else {
            res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath, 
                    destResourceFile, 
                    forwardLocked);
            if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
                return;
            } else {
                Log.d(TAG, "New package installed in " + destPackageFile);
            }
        }
        if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
            if (mInstaller != null) {
                mInstaller.rmdex(tmpPackageFile.getPath());
            }
        }

        synchronized (mPackages) {
            grantPermissionsLP(newPackage, true);
            res.name = pkgName;
            res.uid = newPackage.applicationInfo.uid;
            res.pkg = newPackage;
            mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
            res.returnCode = PackageManager.INSTALL_SUCCEEDED;
            //to update install status
            mSettings.writeLP();
        }
    
private booleanverifySignaturesLP(com.android.server.PackageManagerService$PackageSetting pkgSetting, PackageParser.Package pkg, int parseFlags, boolean updateSignature)

        if (pkg.mSignatures != null) {
            if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
                    updateSignature)) {
                Log.e(TAG, "Package " + pkg.packageName
                        + " signatures do not match the previously installed version; ignoring!");
                mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
                return false;
            }

            if (pkgSetting.sharedUser != null) {
                if (!pkgSetting.sharedUser.signatures.mergeSignatures(
                        pkg.mSignatures, updateSignature)) {
                    Log.e(TAG, "Package " + pkg.packageName
                            + " has no signatures that match those in shared user "
                            + pkgSetting.sharedUser.name + "; ignoring!");
                    mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
                    return false;
                }
            }
        } else {
            pkg.mSignatures = pkgSetting.signatures.mSignatures;
        }
        return true;