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

Commit 6f527bff authored by Alex Buynytskyy's avatar Alex Buynytskyy Committed by Android (Google) Code Review
Browse files

Merge "Streaming Installation API update."

parents 795168a1 e0697871
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -2153,11 +2153,16 @@ package android.content.pm {
    field public static final int DATA_LOADER_TYPE_NONE = 0; // 0x0
    field public static final int DATA_LOADER_TYPE_STREAMING = 1; // 0x1
    field public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
    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_OBB = 1; // 0x1
  }
  public static class PackageInstaller.Session implements java.io.Closeable {
    method public void addFile(@NonNull String, long, @NonNull byte[]);
    method public void addFile(int, @NonNull String, long, @NonNull byte[], @Nullable byte[]);
    method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void commitTransferred(@NonNull android.content.IntentSender);
    method @Nullable public android.content.pm.DataLoaderParams getDataLoaderParams();
    method public void removeFile(int, @NonNull String);
  }
  public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
+4 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.content.pm;

import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.IPackageInstallObserver2;
import android.content.IntentSender;
import android.os.ParcelFileDescriptor;
@@ -39,8 +40,9 @@ interface IPackageInstallerSession {
    void transfer(in String packageName);
    void abandon();

    void addFile(String name, long lengthBytes, in byte[] metadata);
    void removeFile(String name);
    DataLoaderParamsParcel getDataLoaderParams();
    void addFile(int location, String name, long lengthBytes, in byte[] metadata, in byte[] signature);
    void removeFile(int location, String name);

    boolean isMultiPackage();
    int[] getChildSessionIds();
+70 −4
Original line number Diff line number Diff line
@@ -365,6 +365,41 @@ public class PackageInstaller {
    @SystemApi
    public static final int DATA_LOADER_TYPE_INCREMENTAL = DataLoaderType.INCREMENTAL;

    /**
     * Target location for the file in installation session is /data/app/<packageName>-<id>.
     * This is the intended location for APKs.
     * Requires permission to install packages.
     * {@hide}
     */
    @SystemApi
    public static final int LOCATION_DATA_APP = 0;

    /**
     * Target location for the file in installation session is
     * /data/media/<userid>/Android/obb/<packageName>. This is the intended location for OBBs.
     * {@hide}
     */
    @SystemApi
    public static final int LOCATION_MEDIA_OBB = 1;

    /**
     * Target location for the file in installation session is
     * /data/media/<userid>/Android/data/<packageName>.
     * This is the intended location for application data.
     * Can only be used by an app itself running under specific user.
     * {@hide}
     */
    @SystemApi
    public static final int LOCATION_MEDIA_DATA = 2;

    /** @hide */
    @IntDef(prefix = { "LOCATION_" }, value = {
            LOCATION_DATA_APP,
            LOCATION_MEDIA_OBB,
            LOCATION_MEDIA_DATA})
    @Retention(RetentionPolicy.SOURCE)
    public @interface FileLocation{}

    private final IPackageInstaller mInstaller;
    private final int mUserId;
    private final String mInstallerPackageName;
@@ -1071,10 +1106,33 @@ public class PackageInstaller {
            }
        }

        /**
         * @return data loader params or null if the session is not using one.
         *
         * WARNING: This is a system API to aid internal development.
         * Use at your own risk. It will change or be removed without warning.
         * {@hide}
         */
        @SystemApi
        public @Nullable DataLoaderParams getDataLoaderParams() {
            try {
                DataLoaderParamsParcel data = mSession.getDataLoaderParams();
                if (data == null) {
                    return null;
                }
                return new DataLoaderParams(data);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        /**
         * Adds a file to session. On commit this file will be pulled from dataLoader.
         *
         * @param location target location for the file. Possible values:
         *            {@link #LOCATION_DATA_APP},
         *            {@link #LOCATION_MEDIA_OBB},
         *            {@link #LOCATION_MEDIA_DATA}.
         * @param name arbitrary, unique name of your choosing to identify the
         *            APK being written. You can open a file again for
         *            additional writes (such as after a reboot) by using the
@@ -1084,6 +1142,8 @@ public class PackageInstaller {
         *            The system may clear various caches as needed to allocate
         *            this space.
         * @param metadata additional info use by dataLoader to pull data for the file.
         * @param signature additional file signature, e.g.
         *                  <a href="https://source.android.com/security/apksigning/v4.html">APK Signature Scheme v4</a>
         * @throws SecurityException if called after the session has been
         *             sealed or abandoned
         * @throws IllegalStateException if called for non-callback session
@@ -1093,9 +1153,10 @@ public class PackageInstaller {
         * {@hide}
         */
        @SystemApi
        public void addFile(@NonNull String name, long lengthBytes, @NonNull byte[] metadata) {
        public void addFile(@FileLocation int location, @NonNull String name, long lengthBytes,
                @NonNull byte[] metadata, @Nullable byte[] signature) {
            try {
                mSession.addFile(name, lengthBytes, metadata);
                mSession.addFile(location, name, lengthBytes, metadata, signature);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
@@ -1104,15 +1165,20 @@ public class PackageInstaller {
        /**
         * Removes a file.
         *
         * @param location target location for the file. Possible values:
         *            {@link #LOCATION_DATA_APP},
         *            {@link #LOCATION_MEDIA_OBB},
         *            {@link #LOCATION_MEDIA_DATA}.
         * @param name name of a file, e.g. split.
         * @throws SecurityException if called after the session has been
         *             sealed or abandoned
         * @throws IllegalStateException if called for non-callback session
         * {@hide}
         */
        public void removeFile(@NonNull String name) {
        @SystemApi
        public void removeFile(@FileLocation int location, @NonNull String name) {
            try {
                mSession.removeFile(name);
                mSession.removeFile(location, name);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
+7 −1
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.server.incremental;

import static android.content.pm.InstallationFile.FILE_TYPE_OBB;
import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
import static android.content.pm.PackageInstaller.LOCATION_MEDIA_OBB;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -171,7 +175,9 @@ public final class IncrementalManagerShellCommand extends ShellCommand {
            session = packageInstaller.openSession(sessionId);
            for (int i = 0; i < numFiles; i++) {
                InstallationFile file = installationFiles.get(i);
                session.addFile(file.getName(), file.getSize(), file.getMetadata());
                final int location = file.getFileType() == FILE_TYPE_OBB ? LOCATION_MEDIA_OBB
                        : LOCATION_DATA_APP;
                session.addFile(location, file.getName(), file.getSize(), file.getMetadata(), null);
            }
            session.commit(localReceiver.getIntentSender());
            final Intent result = localReceiver.getResult();
+37 −11
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.pm;

import static android.content.pm.DataLoaderType.INCREMENTAL;
import static android.content.pm.DataLoaderType.STREAMING;
import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -60,6 +61,7 @@ import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.DataLoaderManager;
import android.content.pm.DataLoaderParams;
import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderStatusListener;
@@ -203,8 +205,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private static final String ATTR_DATALOADER_PACKAGE_NAME = "dataLoaderPackageName";
    private static final String ATTR_DATALOADER_CLASS_NAME = "dataLoaderClassName";
    private static final String ATTR_DATALOADER_ARGUMENTS = "dataLoaderArguments";
    private static final String ATTR_LOCATION = "location";
    private static final String ATTR_LENGTH_BYTES = "lengthBytes";
    private static final String ATTR_METADATA = "metadata";
    private static final String ATTR_SIGNATURE = "signature";

    private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
    private static final int[] EMPTY_CHILD_SESSION_ARRAY = {};
@@ -303,22 +307,27 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private int mParentSessionId;

    static class FileInfo {
        public final int location;
        public final String name;
        public final Long lengthBytes;
        public final byte[] metadata;
        public final byte[] signature;

        public static FileInfo added(String name, Long lengthBytes, byte[] metadata) {
            return new FileInfo(name, lengthBytes, metadata);
        public static FileInfo added(int location, String name, Long lengthBytes, byte[] metadata,
                byte[] signature) {
            return new FileInfo(location, name, lengthBytes, metadata, signature);
        }

        public static FileInfo removed(String name) {
            return new FileInfo(name, -1L, null);
        public static FileInfo removed(int location, String name) {
            return new FileInfo(location, name, -1L, null, null);
        }

        FileInfo(String name, Long lengthBytes, byte[] metadata) {
        FileInfo(int location, String name, Long lengthBytes, byte[] metadata, byte[] signature) {
            this.location = location;
            this.name = name;
            this.lengthBytes = lengthBytes;
            this.metadata = metadata;
            this.signature = signature;
        }
    }

@@ -2326,11 +2335,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    }

    @Override
    public void addFile(String name, long lengthBytes, byte[] metadata) {
    public DataLoaderParamsParcel getDataLoaderParams() {
        return params.dataLoaderParams != null ? params.dataLoaderParams.getData() : null;
    }

    @Override
    public void addFile(int location, String name, long lengthBytes, byte[] metadata,
            byte[] signature) {
        if (!isDataLoaderInstallation()) {
            throw new IllegalStateException(
                    "Cannot add files to non-data loader installation session.");
        }
        if (!isIncrementalInstallation()) {
            if (location != LOCATION_DATA_APP) {
                throw new IllegalArgumentException(
                        "Non-incremental installation only supports /data/app placement: " + name);
            }
        }
        // Use installer provided name for now; we always rename later
        if (!FileUtils.isValidExtFilename(name)) {
            throw new IllegalArgumentException("Invalid name: " + name);
@@ -2339,12 +2360,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        synchronized (mLock) {
            assertCallerIsOwnerOrRootLocked();
            assertPreparedAndNotSealedLocked("addFile");
            mFiles.add(FileInfo.added(name, lengthBytes, metadata));
            mFiles.add(FileInfo.added(location, name, lengthBytes, metadata, signature));
        }
    }

    @Override
    public void removeFile(String name) {
    public void removeFile(int location, String name) {
        if (!isDataLoaderInstallation()) {
            throw new IllegalStateException(
                    "Cannot add files to non-data loader installation session.");
@@ -2357,7 +2378,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            assertCallerIsOwnerOrRootLocked();
            assertPreparedAndNotSealedLocked("removeFile");

            mFiles.add(FileInfo.removed(getRemoveMarkerName(name)));
            mFiles.add(FileInfo.removed(location, getRemoveMarkerName(name)));
        }
    }

@@ -2892,9 +2913,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            }
            for (FileInfo fileInfo : mFiles) {
                out.startTag(null, TAG_SESSION_FILE);
                writeIntAttribute(out, ATTR_LOCATION, fileInfo.location);
                writeStringAttribute(out, ATTR_NAME, fileInfo.name);
                writeLongAttribute(out, ATTR_LENGTH_BYTES, fileInfo.lengthBytes);
                writeByteArrayAttribute(out, ATTR_METADATA, fileInfo.metadata);
                writeByteArrayAttribute(out, ATTR_SIGNATURE, fileInfo.signature);
                out.endTag(null, TAG_SESSION_FILE);
            }
        }
@@ -3025,9 +3048,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                childSessionIds.add(readIntAttribute(in, ATTR_SESSION_ID, SessionInfo.INVALID_ID));
            }
            if (TAG_SESSION_FILE.equals(in.getName())) {
                files.add(new FileInfo(readStringAttribute(in, ATTR_NAME),
                files.add(new FileInfo(
                        readIntAttribute(in, ATTR_LOCATION, 0),
                        readStringAttribute(in, ATTR_NAME),
                        readLongAttribute(in, ATTR_LENGTH_BYTES, -1),
                        readByteArrayAttribute(in, ATTR_METADATA)));
                        readByteArrayAttribute(in, ATTR_METADATA),
                        readByteArrayAttribute(in, ATTR_SIGNATURE)));
            }
        }

Loading