Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 809cb8e5 authored by Steve Kondik's avatar Steve Kondik
Browse files

Apps2SD fixes.

Better recovery after a data wipe.

* Prune stale dex files from /sd-ext/dalvik-cache
* Reset permissions on forward-locked packages when no data directory
  exists (the "fix_permissions" use case)

This does not address the case where a user has protected packages on
sd, and the uids of the package files on disk do not match existing
data directories. This situation is more difficult to get into, but
still needs consideration.
parent 63f7cf38
Loading
Loading
Loading
Loading
+62 −20
Original line number Diff line number Diff line
@@ -185,6 +185,8 @@ class PackageManagerService extends IPackageManager.Stub {
    final File mSystemAppDir;
    final File mAppInstallDir;
    final File mSdExtInstallDir;
    final File mDalvikCacheDir;
    final File mSdExtDalvikCacheDir;
    
    // Whether or not we are installing on the EXT partition.
    boolean mExtInstall;
@@ -407,8 +409,11 @@ class PackageManagerService extends IPackageManager.Stub {
            final HashSet<String> libFiles = new HashSet<String>();
            
            mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
            mDalvikCacheDir = new File(dataDir, "dalvik-cache");
            mSdExtDalvikCacheDir = new File(sdExtDir, "dalvik-cache");
            
            if (mInstaller != null) {
                boolean didDexOpt = false;
                /**
                 * Out of paranoia, ensure that everything in the boot class
                 * path has been dexed.
@@ -421,6 +426,7 @@ class PackageManagerService extends IPackageManager.Stub {
                            if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
                                libFiles.add(paths[i]);
                                mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
                                didDexOpt = true;
                            }
                        } catch (FileNotFoundException e) {
                            Log.w(TAG, "Boot class path not found: " + paths[i]);
@@ -443,6 +449,7 @@ class PackageManagerService extends IPackageManager.Stub {
                            if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
                                libFiles.add(lib);
                                mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
                                didDexOpt = true;
                            }
                        } catch (FileNotFoundException e) {
                            Log.w(TAG, "Library not found: " + lib);
@@ -477,6 +484,7 @@ class PackageManagerService extends IPackageManager.Stub {
                        try {
                            if (dalvik.system.DexFile.isDexOptNeeded(path)) {
                                mInstaller.dexopt(path, Process.SYSTEM_UID, true);
                                didDexOpt = true;
                            }
                        } catch (FileNotFoundException e) {
                            Log.w(TAG, "Jar not found: " + path);
@@ -485,6 +493,38 @@ class PackageManagerService extends IPackageManager.Stub {
                        }
                    }
                }
                
                if (didDexOpt) {
                    // If we had to do a dexopt of one of the previous
                    // things, then something on the system has changed.
                    // Consider this significant, and wipe away all other
                    // existing dexopt files to ensure we don't leave any
                    // dangling around.
                    String[] files = mDalvikCacheDir.list();
                    if (files != null) {
                        for (int i=0; i<files.length; i++) {
                            String fn = files[i];
                            if (fn.startsWith("data@app@")
                                    || fn.startsWith("data@app-private@")) {
                                Log.i(TAG, "Pruning dalvik file: " + fn);
                                (new File(mDalvikCacheDir, fn)).delete();
                            }
                        }
                    }
                    if (isA2SDActive()) {
                        files = mSdExtDalvikCacheDir.list();
                        if (files != null) {
                            for (int i=0; i<files.length; i++) {
                                String fn = files[i];
                                if (fn.startsWith("sd-ext@app@")
                                        || fn.startsWith("sd-ext@app-private@")) {
                                    Log.i(TAG, "Pruning dalvik file: " + fn);
                                    (new File(mSdExtDalvikCacheDir, fn)).delete();
                                }
                            }
                        }
                    }
                }
            }
            
            mFrameworkInstallObserver = new AppDirObserver(
@@ -2360,6 +2400,19 @@ class PackageManagerService extends IPackageManager.Stub {
                        mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                        return null;
                    }
                    if (pkg.mForwardLocked) {
                        // We found a package that should be forward locked, but no
                        // data dir. This happens after a data wipe when apps are on
                        // external storage.  Fix it.
                        Log.i(TAG, "Fixing forward-locked package permissions: " + pkgName 
                                + " uid: " + pkg.applicationInfo.uid);
                        ret = mInstaller.setForwardLockPerm(pkgName, pkg.applicationInfo.uid,
                                scanFile.getAbsolutePath().startsWith(Environment.getSdExtDirectory().getAbsolutePath()));
                        if (ret < 0) {
                            mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                            return null;
                        }
                    }
                } else {
                    dataPath.mkdirs();
                    if (dataPath.exists()) {
@@ -3554,6 +3607,11 @@ class PackageManagerService extends IPackageManager.Stub {
        private final boolean mIsRom;
    }

    private boolean isA2SDActive() {
        return SystemProperties.getBoolean("cm.a2sd.active", false) ||
               SystemProperties.getBoolean("cm.a2sd.force", false)  ;        
    }
    
    /* Called when a downloaded package installation has been confirmed by the user */
    public void installPackage(
            final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
@@ -3562,26 +3620,10 @@ class PackageManagerService extends IPackageManager.Stub {
    
    /* Called when a downloaded package installation is completed (usually by the Market) */
    public void installPackage(final Uri packageURI, final IPackageInstallObserver observer, final int flags, final String installerPackageName) {
    	Boolean a2sd = Settings.Secure.getInt(
            mContext.getContentResolver(),Settings.Secure.APPS2SD, 0) > 0;

        /* Do not allow a2sd if cm.a2sd.active is false */
        if (!SystemProperties.getBoolean("cm.a2sd.active", false)) {
            a2sd = false;
        }
    	boolean a2sd = Settings.Secure.getInt(
            mContext.getContentResolver(),Settings.Secure.APPS2SD, 0) > 0 && isA2SDActive();
    	
        /* Force A2SD if cm.a2sd.force is true */
        if (SystemProperties.getBoolean("cm.ap2sd.force", false)) {
            a2sd = true;
        }
    	
    	if (a2sd) { 		
    	    installPackageExt(packageURI, observer, flags, installerPackageName, true);
    	} else {
    	    installPackageExt(packageURI, observer, flags, installerPackageName, false);
    	}

    	return;
    	installPackageExt(packageURI, observer, flags, installerPackageName, a2sd);
    }

    public void installPackageExt(final Uri packageURI, final IPackageInstallObserver observer, final int flags, final String installerPackageName, boolean extInstall) {