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

Commit 82aff709 authored by Jakob Schneider's avatar Jakob Schneider
Browse files

Clear archive state when the deletion is not successful.

Test: tested manually
Bug: 282952870
Change-Id: Ie0e0e62c275e922d2fe8bb30494b4296c79aa89c
parent 8f8d7272
Loading
Loading
Loading
Loading
+4 −3
Original line number Original line Diff line number Diff line
@@ -697,7 +697,7 @@ final class InstallPackageHelper {
                    pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId);
                    pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId);
                    pkgSetting.setFirstInstallTime(System.currentTimeMillis(), userId);
                    pkgSetting.setFirstInstallTime(System.currentTimeMillis(), userId);
                    // Clear any existing archive state.
                    // Clear any existing archive state.
                    pkgSetting.setArchiveState(null, userId);
                    mPm.mInstallerService.mPackageArchiver.clearArchiveState(packageName, userId);
                    mPm.mSettings.writePackageRestrictionsLPr(userId);
                    mPm.mSettings.writePackageRestrictionsLPr(userId);
                    mPm.mSettings.writeKernelMappingLPr(pkgSetting);
                    mPm.mSettings.writeKernelMappingLPr(pkgSetting);
                    installed = true;
                    installed = true;
@@ -2279,7 +2279,7 @@ final class InstallPackageHelper {
                                installerPackageName);
                                installerPackageName);
                    }
                    }
                    // Clear any existing archive state.
                    // Clear any existing archive state.
                    ps.setArchiveState(null, userId);
                    mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgName, userId);
                } else if (allUsers != null) {
                } else if (allUsers != null) {
                    // The caller explicitly specified INSTALL_ALL_USERS flag.
                    // The caller explicitly specified INSTALL_ALL_USERS flag.
                    // Thus, updating the settings to install the app for all users.
                    // Thus, updating the settings to install the app for all users.
@@ -2303,7 +2303,8 @@ final class InstallPackageHelper {
                                        installerPackageName);
                                        installerPackageName);
                            }
                            }
                            // Clear any existing archive state.
                            // Clear any existing archive state.
                            ps.setArchiveState(null, currentUserId);
                            mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgName,
                                    currentUserId);
                        } else {
                        } else {
                            ps.setInstalled(false, currentUserId);
                            ps.setInstalled(false, currentUserId);
                        }
                        }
+48 −12
Original line number Original line Diff line number Diff line
@@ -71,6 +71,7 @@ import android.graphics.drawable.LayerDrawable;
import android.os.Binder;
import android.os.Binder;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Environment;
import android.os.Environment;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.IBinder;
import android.os.ParcelableException;
import android.os.ParcelableException;
import android.os.Process;
import android.os.Process;
@@ -309,6 +310,26 @@ public class PackageArchiver {
        return false;
        return false;
    }
    }


    void clearArchiveState(String packageName, int userId) {
        synchronized (mPm.mLock) {
            PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
            if (ps != null) {
                ps.setArchiveState(/* archiveState= */ null, userId);
            }
        }
        mPm.mBackgroundHandler.post(
                () -> {
                    File iconsDir = getIconsDir(packageName, userId);
                    if (!iconsDir.exists()) {
                        return;
                    }
                    // TODO(b/319238030) Move this into installd.
                    if (!FileUtils.deleteContentsAndDir(iconsDir)) {
                        Slog.e(TAG, "Failed to clean up archive files for " + packageName);
                    }
                });
    }

    @Nullable
    @Nullable
    private String getCurrentLauncherPackageName(int userId) {
    private String getCurrentLauncherPackageName(int userId) {
        ComponentName defaultLauncherComponent = mPm.snapshotComputer().getDefaultHomeActivity(
        ComponentName defaultLauncherComponent = mPm.snapshotComputer().getDefaultHomeActivity(
@@ -437,8 +458,8 @@ public class PackageArchiver {
        if (mainActivity.iconBitmap == null) {
        if (mainActivity.iconBitmap == null) {
            return null;
            return null;
        }
        }
        File iconsDir = createIconsDir(userId);
        File iconsDir = createIconsDir(packageName, userId);
        File iconFile = new File(iconsDir, packageName + "-" + index + ".png");
        File iconFile = new File(iconsDir, index + ".png");
        try (FileOutputStream out = new FileOutputStream(iconFile)) {
        try (FileOutputStream out = new FileOutputStream(iconFile)) {
            out.write(mainActivity.iconBitmap);
            out.write(mainActivity.iconBitmap);
            out.flush();
            out.flush();
@@ -454,14 +475,14 @@ public class PackageArchiver {
            // The app doesn't define an icon. No need to store anything.
            // The app doesn't define an icon. No need to store anything.
            return null;
            return null;
        }
        }
        File iconsDir = createIconsDir(userId);
        File iconsDir = createIconsDir(packageName, userId);
        File iconFile = new File(iconsDir, packageName + "-" + index + ".png");
        File iconFile = new File(iconsDir, index + ".png");
        Bitmap icon = drawableToBitmap(mainActivity.getIcon(/* density= */ 0), iconSize);
        Bitmap icon = drawableToBitmap(mainActivity.getIcon(/* density= */ 0), iconSize);
        try (FileOutputStream out = new FileOutputStream(iconFile)) {
        try (FileOutputStream out = new FileOutputStream(iconFile)) {
            // Note: Quality is ignored for PNGs.
            // Note: Quality is ignored for PNGs.
            if (!icon.compress(Bitmap.CompressFormat.PNG, /* quality= */ 100, out)) {
            if (!icon.compress(Bitmap.CompressFormat.PNG, /* quality= */ 100, out)) {
                throw new IOException(TextUtils.formatSimple("Failure to store icon file %s",
                throw new IOException(TextUtils.formatSimple("Failure to store icon file %s",
                        iconFile.getName()));
                        iconFile.getAbsolutePath()));
            }
            }
            out.flush();
            out.flush();
        }
        }
@@ -793,8 +814,20 @@ public class PackageArchiver {
    }
    }


    @VisibleForTesting
    @VisibleForTesting
    Bitmap decodeIcon(ArchiveActivityInfo archiveActivityInfo) {
    @Nullable
        return BitmapFactory.decodeFile(archiveActivityInfo.getIconBitmap().toString());
    Bitmap decodeIcon(ArchiveActivityInfo activityInfo) {
        Path iconBitmap = activityInfo.getIconBitmap();
        if (iconBitmap == null) {
            return null;
        }
        Bitmap bitmap = BitmapFactory.decodeFile(iconBitmap.toString());
        // TODO(b/278553670) We should throw here after some time. Failing graciously now because
        // we've just changed the place where we store icons.
        if (bitmap == null) {
            Slog.e(TAG, "Archived icon cannot be decoded " + iconBitmap.toAbsolutePath());
            return null;
        }
        return bitmap;
    }
    }


    Bitmap includeCloudOverlay(Bitmap bitmap) {
    Bitmap includeCloudOverlay(Bitmap bitmap) {
@@ -1075,8 +1108,9 @@ public class PackageArchiver {
        }
        }
    }
    }


    private static File createIconsDir(@UserIdInt int userId) throws IOException {
    private static File createIconsDir(String packageName, @UserIdInt int userId)
        File iconsDir = getIconsDir(userId);
            throws IOException {
        File iconsDir = getIconsDir(packageName, userId);
        if (!iconsDir.isDirectory()) {
        if (!iconsDir.isDirectory()) {
            iconsDir.delete();
            iconsDir.delete();
            iconsDir.mkdirs();
            iconsDir.mkdirs();
@@ -1088,8 +1122,10 @@ public class PackageArchiver {
        return iconsDir;
        return iconsDir;
    }
    }


    private static File getIconsDir(int userId) {
    private static File getIconsDir(String packageName, int userId) {
        return new File(Environment.getDataSystemCeDirectory(userId), ARCHIVE_ICONS_DIR);
        return new File(
                new File(Environment.getDataSystemCeDirectory(userId), ARCHIVE_ICONS_DIR),
                packageName);
    }
    }


    private static byte[] bytesFromBitmapFile(Path path) throws IOException {
    private static byte[] bytesFromBitmapFile(Path path) throws IOException {
+26 −3
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_NO_CONNECTIVI
import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED;
import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED;
import static android.content.pm.PackageInstaller.UNARCHIVAL_GENERIC_ERROR;
import static android.content.pm.PackageInstaller.UNARCHIVAL_GENERIC_ERROR;
import static android.content.pm.PackageInstaller.UNARCHIVAL_OK;
import static android.content.pm.PackageInstaller.UNARCHIVAL_OK;
import static android.content.pm.PackageManager.DELETE_ARCHIVE;
import static android.content.pm.PackageManager.INSTALL_UNARCHIVE_DRAFT;
import static android.content.pm.PackageManager.INSTALL_UNARCHIVE_DRAFT;
import static android.os.Process.INVALID_UID;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.SYSTEM_UID;
@@ -1402,7 +1403,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements


        final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
        final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
                statusReceiver, versionedPackage.getPackageName(),
                statusReceiver, versionedPackage.getPackageName(),
                canSilentlyInstallPackage, userId);
                canSilentlyInstallPackage, userId, mPackageArchiver, flags);
        final boolean shouldShowConfirmationDialog =
        final boolean shouldShowConfirmationDialog =
                (flags & PackageManager.DELETE_SHOW_DIALOG) != 0;
                (flags & PackageManager.DELETE_SHOW_DIALOG) != 0;
        if (!shouldShowConfirmationDialog
        if (!shouldShowConfirmationDialog
@@ -1756,7 +1757,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
                        binderUid, unarchiveId));
                        binderUid, unarchiveId));
            }
            }


            session.reportUnarchivalStatus(unarchiveId, status, requiredStorageBytes,
            session.reportUnarchivalStatus(status, unarchiveId, requiredStorageBytes,
                    userActionIntent);
                    userActionIntent);
        }
        }
    }
    }
@@ -1825,9 +1826,23 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
        private final IntentSender mTarget;
        private final IntentSender mTarget;
        private final String mPackageName;
        private final String mPackageName;
        private final Notification mNotification;
        private final Notification mNotification;
        private final int mUserId;


        public PackageDeleteObserverAdapter(Context context, IntentSender target,
        @DeleteFlags
        private final int mFlags;

        @Nullable
        private final PackageArchiver mPackageArchiver;

        PackageDeleteObserverAdapter(Context context, IntentSender target,
                String packageName, boolean showNotification, int userId) {
                String packageName, boolean showNotification, int userId) {
            this(context, target, packageName, showNotification, userId,
                    /* packageArchiver= */ null, /* flags= */ 0);
        }

        PackageDeleteObserverAdapter(Context context, IntentSender target,
                String packageName, boolean showNotification, int userId,
                PackageArchiver packageArchiver, @DeleteFlags int flags) {
            mContext = context;
            mContext = context;
            mTarget = target;
            mTarget = target;
            mPackageName = packageName;
            mPackageName = packageName;
@@ -1839,6 +1854,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
            } else {
            } else {
                mNotification = null;
                mNotification = null;
            }
            }
            mUserId = userId;
            mPackageArchiver = packageArchiver;
            mFlags = flags;
        }
        }


        private String getDeviceOwnerDeletedPackageMsg() {
        private String getDeviceOwnerDeletedPackageMsg() {
@@ -1880,6 +1898,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
                        SystemMessage.NOTE_PACKAGE_STATE,
                        SystemMessage.NOTE_PACKAGE_STATE,
                        mNotification);
                        mNotification);
            }
            }
            if (mPackageArchiver != null
                    && PackageManager.DELETE_SUCCEEDED != returnCode
                    && (mFlags & DELETE_ARCHIVE) != 0) {
                mPackageArchiver.clearArchiveState(mPackageName, mUserId);
            }
            if (mTarget == null) {
            if (mTarget == null) {
                return;
                return;
            }
            }