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

Commit 9b2d26b6 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Consistent clean up of failed installs.

Instead of remembering to add clean-up logic to every install scan
failure case, rely on the fact that we're now throwing for all errors
and use a finally clause to delete data directory when requested.

When clearing data for a package, always try deleting the app data
directories, even if no record of the package exists.  This helps
users recover from UID mismatches without resorting to a full data
wipe.

Bug: 17005516
Change-Id: I352863ef4e468c576ecf136549e21cceae2650d5
parent c9d71506
Loading
Loading
Loading
Loading
+54 −55
Original line number Diff line number Diff line
@@ -1792,19 +1792,17 @@ public class PackageManagerService extends IPackageManager.Stub {
    void cleanupInstallFailedPackage(PackageSetting ps) {
        Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
        removeDataDirsLI(ps.name);
        // TODO: try cleaning up codePath directory contents first, since it
        // might be a cluster
        if (ps.codePath != null) {
            if (!ps.codePath.delete()) {
                Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
            if (ps.codePath.isDirectory()) {
                FileUtils.deleteContents(ps.codePath);
            }
            ps.codePath.delete();
        }
        if (ps.resourcePath != null) {
            if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
                Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
        if (ps.resourcePath != null && !ps.resourcePath.equals(ps.codePath)) {
            if (ps.resourcePath.isDirectory()) {
                FileUtils.deleteContents(ps.resourcePath);
            }
            ps.resourcePath.delete();
        }
        mSettings.removePackageLPw(ps.name);
    }
@@ -5030,6 +5028,21 @@ public class PackageManagerService extends IPackageManager.Stub {
    private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
        boolean success = false;
        try {
            final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,
                    currentTime, user);
            success = true;
            return res;
        } finally {
            if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
                removeDataDirsLI(pkg.packageName);
            }
        }
    }
    private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
        final File scanFile = new File(pkg.codePath);
        if (pkg.applicationInfo.getCodePath() == null ||
                pkg.applicationInfo.getResourcePath() == null) {
@@ -5337,6 +5350,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        if (mPlatformPackage == pkg) {
            // The system package is special.
            dataPath = new File(Environment.getDataDirectory(), "system");
            pkg.applicationInfo.dataDir = dataPath.getPath();
        } else {
@@ -5344,7 +5358,6 @@ public class PackageManagerService extends IPackageManager.Stub {
            dataPath = getDataPathForPackage(pkg.packageName, 0);
            boolean uidError = false;
            if (dataPath.exists()) {
                int currentUid = 0;
                try {
@@ -5672,12 +5685,8 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
        if ((scanFlags & SCAN_NO_DEX) == 0) {
            if (performDexOptLI(pkg, null /* instruction sets */, forceDex, (scanFlags&SCAN_DEFER_DEX) != 0, false)
                    == DEX_OPT_FAILED) {
                if ((scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
                    removeDataDirsLI(pkg.packageName);
                }
            if (performDexOptLI(pkg, null /* instruction sets */, forceDex,
                    (scanFlags & SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) {
                throw new PackageManagerException(INSTALL_FAILED_DEXOPT, "scanPackageLI");
            }
        }
@@ -5751,13 +5760,8 @@ public class PackageManagerService extends IPackageManager.Stub {
            if ((scanFlags & SCAN_NO_DEX) == 0) {
                for (int i = 0; i < clientLibPkgs.size(); i++) {
                    PackageParser.Package clientPkg = clientLibPkgs.get(i);
                    if (performDexOptLI(clientPkg, null /* instruction sets */,
                            forceDex, (scanFlags&SCAN_DEFER_DEX) != 0, false)
                            == DEX_OPT_FAILED) {
                        if ((scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
                            removeDataDirsLI(pkg.packageName);
                        }
                    if (performDexOptLI(clientPkg, null /* instruction sets */, forceDex,
                            (scanFlags & SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) {
                        throw new PackageManagerException(INSTALL_FAILED_DEXOPT,
                                "scanPackageLI failed to dexopt clientLibPkgs");
                    }
@@ -11085,45 +11089,40 @@ public class PackageManagerService extends IPackageManager.Stub {
            Slog.w(TAG, "Attempt to delete null packageName.");
            return false;
        }
        // Try finding details about the requested package
        PackageParser.Package pkg;
        boolean dataOnly = false;
        final int appId;
        synchronized (mPackages) {
            pkg = mPackages.get(packageName);
            if (pkg == null) {
                dataOnly = true;
                PackageSetting ps = mSettings.mPackages.get(packageName);
                if ((ps == null) || (ps.pkg == null)) {
                    Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
                    return false;
                }
                final PackageSetting ps = mSettings.mPackages.get(packageName);
                if (ps != null) {
                    pkg = ps.pkg;
                }
            if (!dataOnly) {
                // need to check this only for fully installed applications
                if (pkg == null) {
                    Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
                    return false;
            }
                final ApplicationInfo applicationInfo = pkg.applicationInfo;
                if (applicationInfo == null) {
                    Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
                    return false;
                }
            }
            if (pkg != null && pkg.applicationInfo != null) {
                appId = pkg.applicationInfo.uid;
            } else {
                appId = -1;
        }
        if (pkg == null) {
            Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
        }
        // Always delete data directories for package, even if we found no other
        // record of app. This helps users recover from UID mismatches without
        // resorting to a full data wipe.
        int retCode = mInstaller.clearUserData(packageName, userId);
        if (retCode < 0) {
            Slog.w(TAG, "Couldn't remove cache files for package: "
                    + packageName);
            Slog.w(TAG, "Couldn't remove cache files for package: " + packageName);
            return false;
        }
        if (pkg == null) {
            return false;
        }
        if (pkg != null && pkg.applicationInfo != null) {
            final int appId = pkg.applicationInfo.uid;
            removeKeystoreDataIfNeeded(userId, appId);
        }
        // Create a native library symlink only if we have native libraries
        // and if the native libraries are 32 bit libraries. We do not provide