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

Commit a712057a authored by Jakob Schneider's avatar Jakob Schneider
Browse files

Add an intentSender to the unarchival API and add onUnarchivalStatus API

with failure handling.

Also add some missing permission checks.

Bug: 308150552
Test: PackageInstallerArchiveTest
Change-Id: I755fe01fd25d5cc405fb30be62e6a9b94ea1d3a3
parent c02a454c
Loading
Loading
Loading
Loading
+10 −1
Original line number Original line Diff line number Diff line
@@ -3868,8 +3868,9 @@ package android.content.pm {
  public class PackageInstaller {
  public class PackageInstaller {
    method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull java.io.File, int) throws android.content.pm.PackageInstaller.PackageParsingException;
    method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull java.io.File, int) throws android.content.pm.PackageInstaller.PackageParsingException;
    method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull android.os.ParcelFileDescriptor, @Nullable String, int) throws android.content.pm.PackageInstaller.PackageParsingException;
    method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull android.os.ParcelFileDescriptor, @Nullable String, int) throws android.content.pm.PackageInstaller.PackageParsingException;
    method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void reportUnarchivalStatus(int, int, long, @Nullable android.app.PendingIntent) throws android.content.pm.PackageManager.NameNotFoundException;
    method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException;
    method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException;
    method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void requestUnarchive(@NonNull String) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
    method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void requestUnarchive(@NonNull String, @NonNull android.content.IntentSender) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
    method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean);
    method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean);
    field public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
    field public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
    field public static final String ACTION_CONFIRM_PRE_APPROVAL = "android.content.pm.action.CONFIRM_PRE_APPROVAL";
    field public static final String ACTION_CONFIRM_PRE_APPROVAL = "android.content.pm.action.CONFIRM_PRE_APPROVAL";
@@ -3883,12 +3884,20 @@ package android.content.pm {
    field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_ALL_USERS = "android.content.pm.extra.UNARCHIVE_ALL_USERS";
    field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_ALL_USERS = "android.content.pm.extra.UNARCHIVE_ALL_USERS";
    field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_ID = "android.content.pm.extra.UNARCHIVE_ID";
    field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_ID = "android.content.pm.extra.UNARCHIVE_ID";
    field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_PACKAGE_NAME = "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME";
    field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_PACKAGE_NAME = "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME";
    field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_STATUS = "android.content.pm.extra.UNARCHIVE_STATUS";
    field public static final int LOCATION_DATA_APP = 0; // 0x0
    field public static final int LOCATION_DATA_APP = 0; // 0x0
    field public static final int LOCATION_MEDIA_DATA = 2; // 0x2
    field public static final int LOCATION_MEDIA_DATA = 2; // 0x2
    field public static final int LOCATION_MEDIA_OBB = 1; // 0x1
    field public static final int LOCATION_MEDIA_OBB = 1; // 0x1
    field public static final int REASON_CONFIRM_PACKAGE_CHANGE = 0; // 0x0
    field public static final int REASON_CONFIRM_PACKAGE_CHANGE = 0; // 0x0
    field public static final int REASON_OWNERSHIP_CHANGED = 1; // 0x1
    field public static final int REASON_OWNERSHIP_CHANGED = 1; // 0x1
    field public static final int REASON_REMIND_OWNERSHIP = 2; // 0x2
    field public static final int REASON_REMIND_OWNERSHIP = 2; // 0x2
    field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSTALLER_DISABLED = 4; // 0x4
    field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED = 5; // 0x5
    field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE = 2; // 0x2
    field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_NO_CONNECTIVITY = 3; // 0x3
    field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_USER_ACTION_NEEDED = 1; // 0x1
    field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_GENERIC_ERROR = 100; // 0x64
    field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_OK = 0; // 0x0
  }
  }
  public static class PackageInstaller.InstallInfo {
  public static class PackageInstaller.InstallInfo {
+4 −1
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package android.content.pm;
package android.content.pm;


import android.app.PendingIntent;
import android.content.pm.ArchivedPackageParcel;
import android.content.pm.ArchivedPackageParcel;
import android.content.pm.IPackageDeleteObserver2;
import android.content.pm.IPackageDeleteObserver2;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerCallback;
@@ -82,7 +83,7 @@ interface IPackageInstaller {
    void requestArchive(String packageName, String callerPackageName, in IntentSender statusReceiver, in UserHandle userHandle);
    void requestArchive(String packageName, String callerPackageName, in IntentSender statusReceiver, in UserHandle userHandle);


    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES,android.Manifest.permission.REQUEST_INSTALL_PACKAGES})")
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES,android.Manifest.permission.REQUEST_INSTALL_PACKAGES})")
    void requestUnarchive(String packageName, String callerPackageName, in UserHandle userHandle);
    void requestUnarchive(String packageName, String callerPackageName, in IntentSender statusReceiver, in UserHandle userHandle);


    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)")
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)")
    void installPackageArchived(in ArchivedPackageParcel archivedPackageParcel,
    void installPackageArchived(in ArchivedPackageParcel archivedPackageParcel,
@@ -90,4 +91,6 @@ interface IPackageInstaller {
            in IntentSender statusReceiver,
            in IntentSender statusReceiver,
            String installerPackageName, in UserHandle userHandle);
            String installerPackageName, in UserHandle userHandle);


    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES,android.Manifest.permission.REQUEST_INSTALL_PACKAGES})")
    void reportUnarchivalStatus(int unarchiveId, int status, long requiredStorageBytes, in PendingIntent userActionIntent, in UserHandle userHandle);
}
}
+161 −4
Original line number Original line Diff line number Diff line
@@ -386,6 +386,24 @@ public class PackageInstaller {
    public static final String EXTRA_UNARCHIVE_ALL_USERS =
    public static final String EXTRA_UNARCHIVE_ALL_USERS =
            "android.content.pm.extra.UNARCHIVE_ALL_USERS";
            "android.content.pm.extra.UNARCHIVE_ALL_USERS";


    /**
     * Current status of an unarchive operation. Will be one of
     * {@link #UNARCHIVAL_OK}, {@link #UNARCHIVAL_ERROR_USER_ACTION_NEEDED},
     * {@link #UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE}, {@link #UNARCHIVAL_ERROR_NO_CONNECTIVITY},
     * {@link #UNARCHIVAL_GENERIC_ERROR}, {@link #UNARCHIVAL_ERROR_INSTALLER_DISABLED} or
     * {@link #UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED}.
     *
     * <p> If the status is not {@link #UNARCHIVAL_OK}, then {@link Intent#EXTRA_INTENT} will be set
     * with an intent for a corresponding follow-up action (e.g. storage clearing dialog) or a
     * failure dialog.
     *
     * @see #requestUnarchive
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public static final String EXTRA_UNARCHIVE_STATUS = "android.content.pm.extra.UNARCHIVE_STATUS";

    /**
    /**
     * A list of warnings that occurred during installation.
     * A list of warnings that occurred during installation.
     *
     *
@@ -652,6 +670,102 @@ public class PackageInstaller {
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    public @interface UserActionReason {}
    public @interface UserActionReason {}


    /**
     * The unarchival is possible and will commence.
     *
     * <p> Note that this does not mean that the unarchival has completed. This status should be
     * sent before any longer asynchronous action (e.g. app download) is started.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public static final int UNARCHIVAL_OK = 0;

    /**
     * The user needs to interact with the installer to enable the installation.
     *
     * <p> An example use case for this could be that the user needs to login to allow the
     * download for a paid app.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public static final int UNARCHIVAL_ERROR_USER_ACTION_NEEDED = 1;

    /**
     * Not enough storage to unarchive the application.
     *
     * <p> The installer can optionally provide a {@code userActionIntent} for a space-clearing
     * dialog. If no action is provided, then a generic intent
     * {@link android.os.storage.StorageManager#ACTION_MANAGE_STORAGE} is started instead.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public static final int UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE = 2;

    /**
     * The device is not connected to the internet
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public static final int UNARCHIVAL_ERROR_NO_CONNECTIVITY = 3;

    /**
     * The installer responsible for the unarchival is disabled.
     *
     * <p> Should only be used by the system.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public static final int UNARCHIVAL_ERROR_INSTALLER_DISABLED = 4;

    /**
     * The installer responsible for the unarchival has been uninstalled
     *
     * <p> Should only be used by the system.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public static final int UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED = 5;

    /**
     * Generic error: The app cannot be unarchived.
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public static final int UNARCHIVAL_GENERIC_ERROR = 100;

    /**
     * The set of error types that can be set for
     * {@link #reportUnarchivalStatus(int, int, PendingIntent)}.
     *
     * @hide
     */
    @IntDef(value = {
            UNARCHIVAL_OK,
            UNARCHIVAL_ERROR_USER_ACTION_NEEDED,
            UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE,
            UNARCHIVAL_ERROR_NO_CONNECTIVITY,
            UNARCHIVAL_ERROR_INSTALLER_DISABLED,
            UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED,
            UNARCHIVAL_GENERIC_ERROR,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface UnarchivalStatus {}


    /** Default set of checksums - includes all available checksums.
    /** Default set of checksums - includes all available checksums.
     * @see Session#requestChecksums  */
     * @see Session#requestChecksums  */
    private static final int DEFAULT_CHECKSUMS =
    private static final int DEFAULT_CHECKSUMS =
@@ -2238,8 +2352,8 @@ public class PackageInstaller {
     * Requests to archive a package which is currently installed.
     * Requests to archive a package which is currently installed.
     *
     *
     * <p> During the archival process, the apps APKs and cache are removed from the device while
     * <p> During the archival process, the apps APKs and cache are removed from the device while
     * the user data is kept. Through the {@link #requestUnarchive(String)} call, apps can be
     * the user data is kept. Through the {@link #requestUnarchive} call, apps
     * restored again through their responsible installer.
     * can be restored again through their responsible installer.
     *
     *
     * <p> Archived apps are returned as displayable apps through the {@link LauncherApps} APIs and
     * <p> Archived apps are returned as displayable apps through the {@link LauncherApps} APIs and
     * will be displayed to users with UI treatment to highlight that said apps are archived. If
     * will be displayed to users with UI treatment to highlight that said apps are archived. If
@@ -2278,6 +2392,10 @@ public class PackageInstaller {
     * <p> The installation will happen asynchronously and can be observed through
     * <p> The installation will happen asynchronously and can be observed through
     * {@link android.content.Intent#ACTION_PACKAGE_ADDED}.
     * {@link android.content.Intent#ACTION_PACKAGE_ADDED}.
     *
     *
     * @param statusReceiver Callback used to notify whether the installer has accepted the
     *                       unarchival request or an error has occurred. The status update will be
     *                       sent though {@link EXTRA_UNARCHIVE_STATUS}. Only one status will be
     *                       sent.
     * @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not
     * @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not
     *                                              visible to the caller or if the package has no
     *                                              visible to the caller or if the package has no
     *                                              installer on the device anymore to unarchive it.
     *                                              installer on the device anymore to unarchive it.
@@ -2290,10 +2408,10 @@ public class PackageInstaller {
            Manifest.permission.REQUEST_INSTALL_PACKAGES})
            Manifest.permission.REQUEST_INSTALL_PACKAGES})
    @SystemApi
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public void requestUnarchive(@NonNull String packageName)
    public void requestUnarchive(@NonNull String packageName, @NonNull IntentSender statusReceiver)
            throws IOException, PackageManager.NameNotFoundException {
            throws IOException, PackageManager.NameNotFoundException {
        try {
        try {
            mInstaller.requestUnarchive(packageName, mInstallerPackageName,
            mInstaller.requestUnarchive(packageName, mInstallerPackageName, statusReceiver,
                    new UserHandle(mUserId));
                    new UserHandle(mUserId));
        } catch (ParcelableException e) {
        } catch (ParcelableException e) {
            e.maybeRethrow(IOException.class);
            e.maybeRethrow(IOException.class);
@@ -2303,6 +2421,39 @@ public class PackageInstaller {
        }
        }
    }
    }


    /**
     * Reports the status of an unarchival to the system.
     *
     * @param unarchiveId          the ID provided by the system as part of the
     *                             intent.action.UNARCHIVE broadcast with EXTRA_UNARCHIVE_ID.
     * @param status               is used for the system to provide the user with necessary
     *                             follow-up steps or errors.
     * @param requiredStorageBytes If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field
     *                             should be set to specify how many additional bytes of storage
     *                             are required to unarchive the app.
     * @param userActionIntent     Optional intent to start a follow up action required to
     *                             facilitate the unarchival flow (e.g. user needs to log in).
     * @throws PackageManager.NameNotFoundException if no unarchival with {@code unarchiveId} exists
     * @hide
     */
    @RequiresPermission(anyOf = {
            Manifest.permission.INSTALL_PACKAGES,
            Manifest.permission.REQUEST_INSTALL_PACKAGES})
    @SystemApi
    @FlaggedApi(Flags.FLAG_ARCHIVING)
    public void reportUnarchivalStatus(int unarchiveId, @UnarchivalStatus int status,
            long requiredStorageBytes, @Nullable PendingIntent userActionIntent)
            throws PackageManager.NameNotFoundException {
        try {
            mInstaller.reportUnarchivalStatus(unarchiveId, status, requiredStorageBytes,
                    userActionIntent, new UserHandle(mUserId));
        } catch (ParcelableException e) {
            e.maybeRethrow(PackageManager.NameNotFoundException.class);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    // (b/239722738) This class serves as a bridge between the PackageLite class, which
    // (b/239722738) This class serves as a bridge between the PackageLite class, which
    // is a hidden class, and the consumers of this class. (e.g. InstallInstalling.java)
    // is a hidden class, and the consumers of this class. (e.g. InstallInstalling.java)
    // This is a part of an effort to remove dependency on hidden APIs and use SystemAPIs or
    // This is a part of an effort to remove dependency on hidden APIs and use SystemAPIs or
@@ -2566,6 +2717,8 @@ public class PackageInstaller {
        public int developmentInstallFlags = 0;
        public int developmentInstallFlags = 0;
        /** {@hide} */
        /** {@hide} */
        public int unarchiveId = -1;
        public int unarchiveId = -1;
        /** {@hide} */
        public IntentSender unarchiveIntentSender;


        private final ArrayMap<String, Integer> mPermissionStates;
        private final ArrayMap<String, Integer> mPermissionStates;


@@ -2618,6 +2771,7 @@ public class PackageInstaller {
            applicationEnabledSettingPersistent = source.readBoolean();
            applicationEnabledSettingPersistent = source.readBoolean();
            developmentInstallFlags = source.readInt();
            developmentInstallFlags = source.readInt();
            unarchiveId = source.readInt();
            unarchiveId = source.readInt();
            unarchiveIntentSender = source.readParcelable(null, IntentSender.class);
        }
        }


        /** {@hide} */
        /** {@hide} */
@@ -2652,6 +2806,7 @@ public class PackageInstaller {
            ret.applicationEnabledSettingPersistent = applicationEnabledSettingPersistent;
            ret.applicationEnabledSettingPersistent = applicationEnabledSettingPersistent;
            ret.developmentInstallFlags = developmentInstallFlags;
            ret.developmentInstallFlags = developmentInstallFlags;
            ret.unarchiveId = unarchiveId;
            ret.unarchiveId = unarchiveId;
            ret.unarchiveIntentSender = unarchiveIntentSender;
            return ret;
            return ret;
        }
        }


@@ -3364,6 +3519,7 @@ public class PackageInstaller {
                    applicationEnabledSettingPersistent);
                    applicationEnabledSettingPersistent);
            pw.printHexPair("developmentInstallFlags", developmentInstallFlags);
            pw.printHexPair("developmentInstallFlags", developmentInstallFlags);
            pw.printPair("unarchiveId", unarchiveId);
            pw.printPair("unarchiveId", unarchiveId);
            pw.printPair("unarchiveIntentSender", unarchiveIntentSender);
            pw.println();
            pw.println();
        }
        }


@@ -3408,6 +3564,7 @@ public class PackageInstaller {
            dest.writeBoolean(applicationEnabledSettingPersistent);
            dest.writeBoolean(applicationEnabledSettingPersistent);
            dest.writeInt(developmentInstallFlags);
            dest.writeInt(developmentInstallFlags);
            dest.writeInt(unarchiveId);
            dest.writeInt(unarchiveId);
            dest.writeParcelable(unarchiveIntentSender, flags);
        }
        }


        public static final Parcelable.Creator<SessionParams>
        public static final Parcelable.Creator<SessionParams>
+36 −2
Original line number Original line Diff line number Diff line
@@ -140,6 +140,8 @@ public class PackageArchiver {
        }
        }
        snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
        snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
                "archiveApp");
                "archiveApp");
        verifyUninstallPermissions();

        CompletableFuture<ArchiveState> archiveStateFuture;
        CompletableFuture<ArchiveState> archiveStateFuture;
        try {
        try {
            archiveStateFuture = createArchiveState(packageName, userId);
            archiveStateFuture = createArchiveState(packageName, userId);
@@ -372,9 +374,11 @@ public class PackageArchiver {
    void requestUnarchive(
    void requestUnarchive(
            @NonNull String packageName,
            @NonNull String packageName,
            @NonNull String callerPackageName,
            @NonNull String callerPackageName,
            @NonNull IntentSender statusReceiver,
            @NonNull UserHandle userHandle) {
            @NonNull UserHandle userHandle) {
        Objects.requireNonNull(packageName);
        Objects.requireNonNull(packageName);
        Objects.requireNonNull(callerPackageName);
        Objects.requireNonNull(callerPackageName);
        Objects.requireNonNull(statusReceiver);
        Objects.requireNonNull(userHandle);
        Objects.requireNonNull(userHandle);


        Computer snapshot = mPm.snapshotComputer();
        Computer snapshot = mPm.snapshotComputer();
@@ -385,6 +389,8 @@ public class PackageArchiver {
        }
        }
        snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
        snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
                "unarchiveApp");
                "unarchiveApp");
        verifyInstallPermissions();

        PackageStateInternal ps;
        PackageStateInternal ps;
        try {
        try {
            ps = getPackageState(packageName, snapshot, binderUid, userId);
            ps = getPackageState(packageName, snapshot, binderUid, userId);
@@ -400,9 +406,12 @@ public class PackageArchiver {
                                    packageName)));
                                    packageName)));
        }
        }


        // TODO(b/305902395) Introduce a confirmation dialog if the requestor only holds
        // REQUEST_INSTALL permission.
        int draftSessionId;
        int draftSessionId;
        try {
        try {
            draftSessionId = createDraftSession(packageName, installerPackage, userId);
            draftSessionId = createDraftSession(packageName, installerPackage, statusReceiver,
                    userId);
        } catch (RuntimeException e) {
        } catch (RuntimeException e) {
            if (e.getCause() instanceof IOException) {
            if (e.getCause() instanceof IOException) {
                throw ExceptionUtils.wrap((IOException) e.getCause());
                throw ExceptionUtils.wrap((IOException) e.getCause());
@@ -415,11 +424,36 @@ public class PackageArchiver {
                () -> unarchiveInternal(packageName, userHandle, installerPackage, draftSessionId));
                () -> unarchiveInternal(packageName, userHandle, installerPackage, draftSessionId));
    }
    }


    private int createDraftSession(String packageName, String installerPackage, int userId) {
    private void verifyInstallPermissions() {
        if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)
                != PackageManager.PERMISSION_GRANTED && mContext.checkCallingOrSelfPermission(
                Manifest.permission.REQUEST_INSTALL_PACKAGES)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("You need the com.android.permission.INSTALL_PACKAGES "
                    + "or com.android.permission.REQUEST_INSTALL_PACKAGES permission to request "
                    + "an unarchival.");
        }
    }

    private void verifyUninstallPermissions() {
        if (mContext.checkCallingOrSelfPermission(Manifest.permission.DELETE_PACKAGES)
                != PackageManager.PERMISSION_GRANTED && mContext.checkCallingOrSelfPermission(
                Manifest.permission.REQUEST_DELETE_PACKAGES)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("You need the com.android.permission.DELETE_PACKAGES "
                    + "or com.android.permission.REQUEST_DELETE_PACKAGES permission to request "
                    + "an archival.");
        }
    }

    private int createDraftSession(String packageName, String installerPackage,
            IntentSender statusReceiver, int userId) {
        PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(
        PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(
                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
        sessionParams.setAppPackageName(packageName);
        sessionParams.setAppPackageName(packageName);
        sessionParams.installFlags = INSTALL_UNARCHIVE_DRAFT;
        sessionParams.installFlags = INSTALL_UNARCHIVE_DRAFT;
        sessionParams.unarchiveIntentSender = statusReceiver;

        int installerUid = mPm.snapshotComputer().getPackageUid(installerPackage, 0, userId);
        int installerUid = mPm.snapshotComputer().getPackageUid(installerPackage, 0, userId);
        // Handles case of repeated unarchival calls for the same package.
        // Handles case of repeated unarchival calls for the same package.
        int existingSessionId = mPm.mInstallerService.getExistingDraftSessionId(installerUid,
        int existingSessionId = mPm.mInstallerService.getExistingDraftSessionId(installerUid,
+108 −1

File changed.

Preview size limit exceeded, changes collapsed.

Loading