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

Commit acee6e91 authored by Christopher Tate's avatar Christopher Tate
Browse files

Maintain restrictions when downgrading system apps

When an upgraded system-bundled app is reverted to the factory
version, we now maintain restricted profiles' access policies
w.r.t. that app.

Bug 8905395

Change-Id: I3f230ac3f70a77fb14c0180b44c9b42fc49250a2
parent 1965b447
Loading
Loading
Loading
Loading
+112 −23
Original line number Original line Diff line number Diff line
@@ -3502,7 +3502,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
            if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
                    != PackageManager.SIGNATURE_MATCH) {
                    != PackageManager.SIGNATURE_MATCH) {
                if (DEBUG_INSTALL) Slog.d(TAG, "Signature mismatch!");
                if (DEBUG_INSTALL) Slog.d(TAG, "Signature mismatch!");
                deletePackageLI(pkg.packageName, null, true, 0, null, false);
                deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
                ps = null;
                ps = null;
            } else {
            } else {
                /*
                /*
@@ -8079,6 +8079,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        } else {
        } else {
            updateSettingsLI(newPackage,
            updateSettingsLI(newPackage,
                    installerPackageName,
                    installerPackageName,
                    null, null,
                    res);
                    res);
            // delete the partially installed application. the data directory will have to be
            // delete the partially installed application. the data directory will have to be
            // restored if it was already existing
            // restored if it was already existing
@@ -8087,7 +8088,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                // delete the package data and cache directories that it created in
                // delete the package data and cache directories that it created in
                // scanPackageLocked, unless those directories existed before we even tried to
                // scanPackageLocked, unless those directories existed before we even tried to
                // install.
                // install.
                deletePackageLI(pkgName, UserHandle.ALL, false,
                deletePackageLI(pkgName, UserHandle.ALL, false, null, null,
                        dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
                        dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
                                res.removedInfo, true);
                                res.removedInfo, true);
            }
            }
@@ -8100,6 +8101,9 @@ public class PackageManagerService extends IPackageManager.Stub {


        PackageParser.Package oldPackage;
        PackageParser.Package oldPackage;
        String pkgName = pkg.packageName;
        String pkgName = pkg.packageName;
        int[] allUsers;
        boolean[] perUserInstalled;

        // First find the old package info and check signatures
        // First find the old package info and check signatures
        synchronized(mPackages) {
        synchronized(mPackages) {
            oldPackage = mPackages.get(pkgName);
            oldPackage = mPackages.get(pkgName);
@@ -8110,19 +8114,28 @@ public class PackageManagerService extends IPackageManager.Stub {
                res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
                res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
                return;
                return;
            }
            }

            // In case of rollback, remember per-user/profile install state
            PackageSetting ps = mSettings.mPackages.get(pkgName);
            allUsers = sUserManager.getUserIds();
            perUserInstalled = new boolean[allUsers.length];
            for (int i = 0; i < allUsers.length; i++) {
                perUserInstalled[i] = ps.getInstalled(allUsers[i]);
            }
        }
        }
        boolean sysPkg = (isSystemApp(oldPackage));
        boolean sysPkg = (isSystemApp(oldPackage));
        if (sysPkg) {
        if (sysPkg) {
            replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
            replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
                    user, installerPackageName, res);
                    user, allUsers, perUserInstalled, installerPackageName, res);
        } else {
        } else {
            replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
            replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
                    user, installerPackageName, res);
                    user, allUsers, perUserInstalled, installerPackageName, res);
        }
        }
    }
    }


    private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
    private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
            PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
            PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
            int[] allUsers, boolean[] perUserInstalled,
            String installerPackageName, PackageInstalledInfo res) {
            String installerPackageName, PackageInstalledInfo res) {
        PackageParser.Package newPackage = null;
        PackageParser.Package newPackage = null;
        String pkgName = deletedPackage.packageName;
        String pkgName = deletedPackage.packageName;
@@ -8139,7 +8152,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
        }


        // First delete the existing package while retaining the data directory
        // First delete the existing package while retaining the data directory
        if (!deletePackageLI(pkgName, null, true, PackageManager.DELETE_KEEP_DATA,
        if (!deletePackageLI(pkgName, null, true, null, null, PackageManager.DELETE_KEEP_DATA,
                res.removedInfo, true)) {
                res.removedInfo, true)) {
            // If the existing package wasn't successfully deleted
            // If the existing package wasn't successfully deleted
            res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
            res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
@@ -8157,6 +8170,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            } else {
            } else {
                updateSettingsLI(newPackage,
                updateSettingsLI(newPackage,
                        installerPackageName,
                        installerPackageName,
                        allUsers, perUserInstalled,
                        res);
                        res);
                updatedSettings = true;
                updatedSettings = true;
            }
            }
@@ -8170,7 +8184,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            if(updatedSettings) {
            if(updatedSettings) {
                if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);
                if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);
                deletePackageLI(
                deletePackageLI(
                        pkgName, null, true,
                        pkgName, null, true, allUsers, perUserInstalled,
                        PackageManager.DELETE_KEEP_DATA,
                        PackageManager.DELETE_KEEP_DATA,
                                res.removedInfo, true);
                                res.removedInfo, true);
            }
            }
@@ -8206,6 +8220,7 @@ public class PackageManagerService extends IPackageManager.Stub {


    private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
    private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
            PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
            PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
            int[] allUsers, boolean[] perUserInstalled,
            String installerPackageName, PackageInstalledInfo res) {
            String installerPackageName, PackageInstalledInfo res) {
        if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
        if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
                + ", old=" + deletedPackage);
                + ", old=" + deletedPackage);
@@ -8268,7 +8283,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
                newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
                newPkgSetting.lastUpdateTime = System.currentTimeMillis();
                newPkgSetting.lastUpdateTime = System.currentTimeMillis();
            }
            }
            updateSettingsLI(newPackage, installerPackageName, res);
            updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
            updatedSettings = true;
            updatedSettings = true;
        }
        }


@@ -8314,8 +8329,9 @@ public class PackageManagerService extends IPackageManager.Stub {
        return PackageManager.INSTALL_SUCCEEDED;
        return PackageManager.INSTALL_SUCCEEDED;
    }
    }


    private void updateSettingsLI(PackageParser.Package newPackage,
    private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
            String installerPackageName, PackageInstalledInfo res) {
            int[] allUsers, boolean[] perUserInstalled,
            PackageInstalledInfo res) {
        String pkgName = newPackage.packageName;
        String pkgName = newPackage.packageName;
        synchronized (mPackages) {
        synchronized (mPackages) {
            //write settings. the installStatus will be incomplete at this stage.
            //write settings. the installStatus will be incomplete at this stage.
@@ -8353,6 +8369,18 @@ public class PackageManagerService extends IPackageManager.Stub {
                                    userHandle, installerPackageName);
                                    userHandle, installerPackageName);
                        }
                        }
                    }
                    }
                    // Also convey the prior install/uninstall state
                    if (allUsers != null && perUserInstalled != null) {
                        for (int i = 0; i < allUsers.length; i++) {
                            if (DEBUG_INSTALL) {
                                Slog.d(TAG, "    user " + allUsers[i]
                                        + " => " + perUserInstalled[i]);
                            }
                            ps.setInstalled(perUserInstalled[i], allUsers[i]);
                        }
                        // these install state changes will be persisted in the
                        // upcoming call to mSettings.writeLPr().
                    }
                }
                }
            }
            }
            res.name = pkgName;
            res.name = pkgName;
@@ -8651,12 +8679,27 @@ public class PackageManagerService extends IPackageManager.Stub {


        boolean removedForAllUsers = false;
        boolean removedForAllUsers = false;
        boolean systemUpdate = false;
        boolean systemUpdate = false;

        // for the uninstall-updates case and restricted profiles, remember the per-
        // userhandle installed state
        int[] allUsers;
        boolean[] perUserInstalled;
        synchronized (mPackages) {
            PackageSetting ps = mSettings.mPackages.get(packageName);
            allUsers = sUserManager.getUserIds();
            perUserInstalled = new boolean[allUsers.length];
            for (int i = 0; i < allUsers.length; i++) {
                perUserInstalled[i] = ps.getInstalled(allUsers[i]);
            }
        }

        synchronized (mInstallLock) {
        synchronized (mInstallLock) {
            if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
            if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
            res = deletePackageLI(packageName,
            res = deletePackageLI(packageName,
                    (flags & PackageManager.DELETE_ALL_USERS) != 0
                    (flags & PackageManager.DELETE_ALL_USERS) != 0
                            ? UserHandle.ALL : new UserHandle(userId),
                            ? UserHandle.ALL : new UserHandle(userId),
                    true, flags | REMOVE_CHATTY, info, true);
                    true, allUsers, perUserInstalled,
                    flags | REMOVE_CHATTY, info, true);
            systemUpdate = info.isRemovedPackageSystemUpdate;
            systemUpdate = info.isRemovedPackageSystemUpdate;
            if (res && !systemUpdate && mPackages.get(packageName) == null) {
            if (res && !systemUpdate && mPackages.get(packageName) == null) {
                removedForAllUsers = true;
                removedForAllUsers = true;
@@ -8735,8 +8778,9 @@ public class PackageManagerService extends IPackageManager.Stub {
     * make sure this flag is set for partially installed apps. If not its meaningless to
     * make sure this flag is set for partially installed apps. If not its meaningless to
     * delete a partially installed application.
     * delete a partially installed application.
     */
     */
    private void removePackageDataLI(PackageSetting ps, PackageRemovedInfo outInfo,
    private void removePackageDataLI(PackageSetting ps,
            int flags, boolean writeSettings) {
            int[] allUserHandles, boolean[] perUserInstalled,
            PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
        String packageName = ps.name;
        String packageName = ps.name;
        if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
        if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
        removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
        removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
@@ -8772,6 +8816,20 @@ public class PackageManagerService extends IPackageManager.Stub {
                    }
                    }
                    clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
                    clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
                }
                }
                // make sure to preserve per-user disabled state if this removal was just
                // a downgrade of a system app to the factory package
                if (allUserHandles != null && perUserInstalled != null) {
                    if (DEBUG_REMOVE) {
                        Slog.d(TAG, "Propagating install state across downgrade");
                    }
                    for (int i = 0; i < allUserHandles.length; i++) {
                        if (DEBUG_REMOVE) {
                            Slog.d(TAG, "    user " + allUserHandles[i]
                                    + " => " + perUserInstalled[i]);
                        }
                        ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
                    }
                }
            }
            }
            // can downgrade to reader
            // can downgrade to reader
            if (writeSettings) {
            if (writeSettings) {
@@ -8790,7 +8848,10 @@ public class PackageManagerService extends IPackageManager.Stub {
     * Tries to delete system package.
     * Tries to delete system package.
     */
     */
    private boolean deleteSystemPackageLI(PackageSetting newPs,
    private boolean deleteSystemPackageLI(PackageSetting newPs,
            int[] allUserHandles, boolean[] perUserInstalled,
            int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
            int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
        final boolean applyUserRestrictions
                = (allUserHandles != null) && (perUserInstalled != null);
        PackageSetting disabledPs = null;
        PackageSetting disabledPs = null;
        // Confirm if the system package has been updated
        // Confirm if the system package has been updated
        // An updated system app can be deleted. This will also have to restore
        // An updated system app can be deleted. This will also have to restore
@@ -8807,6 +8868,14 @@ public class PackageManagerService extends IPackageManager.Stub {
        } else if (DEBUG_REMOVE) {
        } else if (DEBUG_REMOVE) {
            Slog.d(TAG, "Deleting system pkg from data partition");
            Slog.d(TAG, "Deleting system pkg from data partition");
        }
        }
        if (DEBUG_REMOVE) {
            if (applyUserRestrictions) {
                Slog.d(TAG, "Remembering install states:");
                for (int i = 0; i < allUserHandles.length; i++) {
                    Slog.d(TAG, "   u=" + allUserHandles[i] + " inst=" + perUserInstalled[i]);
                }
            }
        }
        // Delete the updated package
        // Delete the updated package
        outInfo.isRemovedPackageSystemUpdate = true;
        outInfo.isRemovedPackageSystemUpdate = true;
        if (disabledPs.versionCode < newPs.versionCode) {
        if (disabledPs.versionCode < newPs.versionCode) {
@@ -8816,8 +8885,8 @@ public class PackageManagerService extends IPackageManager.Stub {
            // Preserve data by setting flag
            // Preserve data by setting flag
            flags |= PackageManager.DELETE_KEEP_DATA;
            flags |= PackageManager.DELETE_KEEP_DATA;
        }
        }
        boolean ret = deleteInstalledPackageLI(newPs, true, flags, outInfo,
        boolean ret = deleteInstalledPackageLI(newPs, true, flags,
                writeSettings);
                allUserHandles, perUserInstalled, outInfo, writeSettings);
        if (!ret) {
        if (!ret) {
            return false;
            return false;
        }
        }
@@ -8843,6 +8912,22 @@ public class PackageManagerService extends IPackageManager.Stub {
        synchronized (mPackages) {
        synchronized (mPackages) {
            updatePermissionsLPw(newPkg.packageName, newPkg,
            updatePermissionsLPw(newPkg.packageName, newPkg,
                    UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
                    UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
            if (applyUserRestrictions) {
                if (DEBUG_REMOVE) {
                    Slog.d(TAG, "Propagating install state across reinstall");
                }
                PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
                for (int i = 0; i < allUserHandles.length; i++) {
                    if (DEBUG_REMOVE) {
                        Slog.d(TAG, "    user " + allUserHandles[i]
                                + " => " + perUserInstalled[i]);
                    }
                    ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
                }
                // Regardless of writeSettings we need to ensure that this restriction
                // state propagation is persisted
                mSettings.writeAllUsersPackageRestrictionsLPr();
            }
            // can downgrade to reader here
            // can downgrade to reader here
            if (writeSettings) {
            if (writeSettings) {
                mSettings.writeLPr();
                mSettings.writeLPr();
@@ -8852,14 +8937,15 @@ public class PackageManagerService extends IPackageManager.Stub {
    }
    }


    private boolean deleteInstalledPackageLI(PackageSetting ps,
    private boolean deleteInstalledPackageLI(PackageSetting ps,
            boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
            boolean deleteCodeAndResources, int flags,
            boolean writeSettings) {
            int[] allUserHandles, boolean[] perUserInstalled,
            PackageRemovedInfo outInfo, boolean writeSettings) {
        if (outInfo != null) {
        if (outInfo != null) {
            outInfo.uid = ps.appId;
            outInfo.uid = ps.appId;
        }
        }


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


        // Delete application code and resources
        // Delete application code and resources
        if (deleteCodeAndResources && (outInfo != null)) {
        if (deleteCodeAndResources && (outInfo != null)) {
@@ -8873,7 +8959,8 @@ public class PackageManagerService extends IPackageManager.Stub {
     * This method handles package deletion in general
     * This method handles package deletion in general
     */
     */
    private boolean deletePackageLI(String packageName, UserHandle user,
    private boolean deletePackageLI(String packageName, UserHandle user,
            boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
            boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,
            int flags, PackageRemovedInfo outInfo,
            boolean writeSettings) {
            boolean writeSettings) {
        if (packageName == null) {
        if (packageName == null) {
            Slog.w(TAG, "Attempt to delete null packageName.");
            Slog.w(TAG, "Attempt to delete null packageName.");
@@ -8950,7 +9037,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        if (dataOnly) {
        if (dataOnly) {
            // Delete application data first
            // Delete application data first
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only");
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only");
            removePackageDataLI(ps, outInfo, flags, writeSettings);
            removePackageDataLI(ps, null, null, outInfo, flags, writeSettings);
            return true;
            return true;
        }
        }
        boolean ret = false;
        boolean ret = false;
@@ -8958,13 +9045,15 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name);
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name);
            // When an updated system application is deleted we delete the existing resources as well and
            // When an updated system application is deleted we delete the existing resources as well and
            // fall back to existing code in system partition
            // fall back to existing code in system partition
            ret = deleteSystemPackageLI(ps, flags, outInfo, writeSettings);
            ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,
                    flags, outInfo, writeSettings);
        } else {
        } else {
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name);
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name);
            // Kill application pre-emptively especially for apps on sd.
            // Kill application pre-emptively especially for apps on sd.
            killApplication(packageName, ps.appId);
            killApplication(packageName, ps.appId);
            ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, outInfo,
            ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags,
                    writeSettings);
                    allUserHandles, perUserInstalled,
                    outInfo, writeSettings);
        }
        }
        return ret;
        return ret;
    }
    }
@@ -10493,7 +10582,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            // Delete package internally
            // Delete package internally
            PackageRemovedInfo outInfo = new PackageRemovedInfo();
            PackageRemovedInfo outInfo = new PackageRemovedInfo();
            synchronized (mInstallLock) {
            synchronized (mInstallLock) {
                boolean res = deletePackageLI(pkgName, null, false,
                boolean res = deletePackageLI(pkgName, null, false, null, null,
                        PackageManager.DELETE_KEEP_DATA, outInfo, false);
                        PackageManager.DELETE_KEEP_DATA, outInfo, false);
                if (res) {
                if (res) {
                    pkgList.add(pkgName);
                    pkgList.add(pkgName);