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

Commit 19710509 authored by Songchun Fan's avatar Songchun Fan Committed by Android (Google) Code Review
Browse files

Merge changes from topic "fix-steaming-splits"

* changes:
  use shell to open v4 signature file
  fix streaming installation for splits
parents 25bd6d86 cdbcb34c
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -16,12 +16,12 @@

package android.os.incremental;

import android.os.ParcelFileDescriptor;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
@@ -41,11 +41,12 @@ public class V4Signature {
    /**
     * Construct a V4Signature from .idsig file.
     */
    public static V4Signature readFrom(File file) {
        try (DataInputStream stream = new DataInputStream(new FileInputStream(file))) {
    public static V4Signature readFrom(ParcelFileDescriptor pfd) throws IOException {
        final ParcelFileDescriptor dupedFd = pfd.dup();
        final ParcelFileDescriptor.AutoCloseInputStream fdInputStream =
                new ParcelFileDescriptor.AutoCloseInputStream(dupedFd);
        try (DataInputStream stream = new DataInputStream(fdInputStream)) {
            return readFrom(stream);
        } catch (IOException e) {
            return null;
        }
    }

+83 −63
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.content.PackageHelper;
@@ -139,6 +140,7 @@ class PackageManagerShellCommand extends ShellCommand {
    /** Path where ART profiles snapshots are dumped for the shell user */
    private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
    private static final int DEFAULT_WAIT_MS = 60 * 1000;
    private static final String TAG = "PackageManagerShellCommand";

    final IPackageManager mInterface;
    final IPermissionManager mPermissionManager;
@@ -2998,25 +3000,39 @@ class PackageManagerShellCommand extends ShellCommand {
            for (String arg : args) {
                final int delimLocation = arg.indexOf(':');

                // 2. File with specified size read from stdin.
                if (delimLocation != -1) {
                    // 2. File with specified size read from stdin.
                    if (processArgForStdin(arg, session) != 0) {
                        return 1;
                    }
                } else {
                    // 3. Local file.
                    processArgForLocalFile(arg, session);
                }
            }
            return 0;
        } finally {
            IoUtils.closeQuietly(session);
        }
    }

    private int processArgForStdin(String arg, PackageInstaller.Session session) {
        final String[] fileDesc = arg.split(":");
                    String name = null;
                    long sizeBytes = -1;
                    String metadata;
        String name, metadata;
        long sizeBytes;
        byte[] signature = null;

        try {
                        if (fileDesc.length > 0) {
                            name = fileDesc[0];
            if (fileDesc.length < 2) {
                getErrPrintWriter().println("Must specify file name and size");
                return 1;
            }
                        if (fileDesc.length > 1) {
            name = fileDesc[0];
            sizeBytes = Long.parseUnsignedLong(fileDesc[1]);
                        }
            metadata = name;

            if (fileDesc.length > 2 && !TextUtils.isEmpty(fileDesc[2])) {
                metadata = fileDesc[2];
                        } else {
                            metadata = name;
            }
            if (fileDesc.length > 3) {
                signature = Base64.getDecoder().decode(fileDesc[3]);
@@ -3035,27 +3051,27 @@ class PackageManagerShellCommand extends ShellCommand {
        if (signature != null) {
            // Streaming/adb mode.
            metadata = "+" + metadata;
                    } else {
                        // Singleshot read from stdin.
                        metadata = "-" + metadata;
                    }

            try {
                if (V4Signature.readFrom(signature) == null) {
                    getErrPrintWriter().println("V4 signature is invalid in: " + arg);
                    return 1;
                }
            } catch (Exception e) {
                        getErrPrintWriter().println("V4 signature is invalid: " + e + " in " + arg);
                getErrPrintWriter().println(
                        "V4 signature is invalid: " + e + " in " + arg);
                return 1;
            }
        } else {
            // Single-shot read from stdin.
            metadata = "-" + metadata;
        }

        session.addFile(LOCATION_DATA_APP, name, sizeBytes,
                metadata.getBytes(StandardCharsets.UTF_8), signature);
                    continue;
        return 0;
    }

                // 3. Local file.
    private void processArgForLocalFile(String arg, PackageInstaller.Session session) {
        final String inPath = arg;

        final File file = new File(inPath);
@@ -3063,18 +3079,22 @@ class PackageManagerShellCommand extends ShellCommand {
        final long size = file.length();
        final byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8);

                // Try to load a v4 signature for the APK.
                final V4Signature v4signature = V4Signature.readFrom(
                        new File(inPath + V4Signature.EXT));
                final byte[] v4signatureBytes =
                        (v4signature != null) ? v4signature.toByteArray() : null;

                session.addFile(LOCATION_DATA_APP, name, size, metadata, v4signatureBytes);
            }
            return 0;
        byte[] v4signatureBytes = null;
        // Try to load the v4 signature file for the APK; it might not exist.
        final String v4SignaturePath = inPath + V4Signature.EXT;
        final ParcelFileDescriptor pfd = openFileForSystem(v4SignaturePath, "r");
        if (pfd != null) {
            try {
                final V4Signature v4signature = V4Signature.readFrom(pfd);
                v4signatureBytes = v4signature.toByteArray();
            } catch (IOException ex) {
                Slog.e(TAG, "V4 signature file exists but failed to be parsed.", ex);
            } finally {
            IoUtils.closeQuietly(session);
                IoUtils.closeQuietly(pfd);
            }
        }

        session.addFile(LOCATION_DATA_APP, name, size, metadata, v4signatureBytes);
    }

    private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes,