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

Commit e0697871 authored by Alex Buynytskyy's avatar Alex Buynytskyy
Browse files

Streaming Installation API update.

- location and streaming signature,
- obtain data loader params.

Test: atest PackageManagerShellCommandTest SplitTests
Bug: b/136132412 b/133435829

Change-Id: I08a06e827aaf8f0eab40fe1d59f5c9826ce6e78b
parent 8c0289cc
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -2145,11 +2145,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;
        }
    }

@@ -2325,11 +2334,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);
@@ -2338,12 +2359,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.");
@@ -2356,7 +2377,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            assertCallerIsOwnerOrRootLocked();
            assertPreparedAndNotSealedLocked("removeFile");

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

@@ -2891,9 +2912,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);
            }
        }
@@ -3024,9 +3047,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