Loading services/core/java/com/android/server/pm/PackageManagerShellCommand.java +86 −41 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ import java.util.concurrent.TimeUnit; class PackageManagerShellCommand extends ShellCommand { /** Path for streaming APK content */ private static final String STDIN_PATH = "-"; private static final byte[] STDIN_PATH_BYTES = "-".getBytes(StandardCharsets.UTF_8); /** 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; Loading Loading @@ -472,6 +473,7 @@ class PackageManagerShellCommand extends ShellCommand { } } } params.sessionParams.setSize(sessionSize); } /** Loading Loading @@ -1170,59 +1172,54 @@ class PackageManagerShellCommand extends ShellCommand { private int doRunInstall(final InstallParams params) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final boolean streaming = params.sessionParams.dataLoaderParams != null; ArrayList<String> inPaths = getRemainingArgs(); if (inPaths.isEmpty()) { inPaths.add(STDIN_PATH); } final boolean isStreaming = params.sessionParams.dataLoaderParams != null; final boolean isApex = (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0; final boolean hasSplits = inPaths.size() > 1; ArrayList<String> args = getRemainingArgs(); if (STDIN_PATH.equals(inPaths.get(0))) { if (hasSplits) { pw.println("Error: can't specify SPLIT(s) along with STDIN"); return 1; } if (params.sessionParams.sizeBytes == -1) { final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0)); final boolean hasSplits = args.size() > 1; if (fromStdIn && params.sessionParams.sizeBytes == -1) { pw.println("Error: must either specify a package size or an APK file"); return 1; } } final boolean isApex = (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0; if (isApex && hasSplits) { pw.println("Error: can't specify SPLIT(s) for APEX"); return 1; } if (!streaming) { setParamsSize(params, inPaths); if (!isStreaming) { if (fromStdIn && hasSplits) { pw.println("Error: can't specify SPLIT(s) along with STDIN"); return 1; } if (args.isEmpty()) { args.add(STDIN_PATH); } else { setParamsSize(params, args); } } final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { for (String inPath : inPaths) { if (streaming) { String name = new File(inPath).getName(); byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8); if (doAddFile(sessionId, name, params.sessionParams.sizeBytes, metadata, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { if (isStreaming) { if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex) != PackageInstaller.STATUS_SUCCESS) { return 1; } } else { String splitName = hasSplits ? new File(inPath).getName() : "base." + (isApex ? "apex" : "apk"); if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex) != PackageInstaller.STATUS_SUCCESS) { return 1; } } } if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; Loading Loading @@ -2956,23 +2953,71 @@ class PackageManagerShellCommand extends ShellCommand { return sessionId; } private int doAddFile(int sessionId, String name, long sizeBytes, byte[] metadata, boolean logSuccess) throws RemoteException { private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes, boolean isApex) throws RemoteException { PackageInstaller.Session session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); try { session.addFile(name, sizeBytes, metadata); // 1. Single file from stdin. if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) { String name = "base." + (isApex ? "apex" : "apk"); session.addFile(name, sessionSizeBytes, STDIN_PATH_BYTES); return 0; } if (logSuccess) { getOutPrintWriter().println("Success"); for (String arg : args) { final int delimLocation = arg.indexOf(':'); // 2. File with specified size read from stdin. if (delimLocation != -1) { String name = arg.substring(0, delimLocation); String sizeStr = arg.substring(delimLocation + 1); long sizeBytes; if (TextUtils.isEmpty(name)) { getErrPrintWriter().println("Empty file name in: " + arg); return 1; } try { sizeBytes = Long.parseUnsignedLong(sizeStr); } catch (NumberFormatException e) { getErrPrintWriter().println("Unable to parse size from: " + arg); return 1; } session.addFile(name, sizeBytes, STDIN_PATH_BYTES); continue; } // 3. Local file. final String inPath = arg; String name = new File(inPath).getName(); byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8); session.addFile(name, -1, metadata); } return 0; } finally { IoUtils.closeQuietly(session); } } private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes, boolean isApex) throws RemoteException { final boolean multipleSplits = splitPaths.size() > 1; for (String splitPath : splitPaths) { String splitName = multipleSplits ? new File(splitPath).getName() : "base." + (isApex ? "apex" : "apk"); if (doWriteSplit(sessionId, splitPath, sessionSizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } } return 0; } private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess) throws RemoteException { PackageInstaller.Session session = null; Loading Loading
services/core/java/com/android/server/pm/PackageManagerShellCommand.java +86 −41 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ import java.util.concurrent.TimeUnit; class PackageManagerShellCommand extends ShellCommand { /** Path for streaming APK content */ private static final String STDIN_PATH = "-"; private static final byte[] STDIN_PATH_BYTES = "-".getBytes(StandardCharsets.UTF_8); /** 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; Loading Loading @@ -472,6 +473,7 @@ class PackageManagerShellCommand extends ShellCommand { } } } params.sessionParams.setSize(sessionSize); } /** Loading Loading @@ -1170,59 +1172,54 @@ class PackageManagerShellCommand extends ShellCommand { private int doRunInstall(final InstallParams params) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final boolean streaming = params.sessionParams.dataLoaderParams != null; ArrayList<String> inPaths = getRemainingArgs(); if (inPaths.isEmpty()) { inPaths.add(STDIN_PATH); } final boolean isStreaming = params.sessionParams.dataLoaderParams != null; final boolean isApex = (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0; final boolean hasSplits = inPaths.size() > 1; ArrayList<String> args = getRemainingArgs(); if (STDIN_PATH.equals(inPaths.get(0))) { if (hasSplits) { pw.println("Error: can't specify SPLIT(s) along with STDIN"); return 1; } if (params.sessionParams.sizeBytes == -1) { final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0)); final boolean hasSplits = args.size() > 1; if (fromStdIn && params.sessionParams.sizeBytes == -1) { pw.println("Error: must either specify a package size or an APK file"); return 1; } } final boolean isApex = (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0; if (isApex && hasSplits) { pw.println("Error: can't specify SPLIT(s) for APEX"); return 1; } if (!streaming) { setParamsSize(params, inPaths); if (!isStreaming) { if (fromStdIn && hasSplits) { pw.println("Error: can't specify SPLIT(s) along with STDIN"); return 1; } if (args.isEmpty()) { args.add(STDIN_PATH); } else { setParamsSize(params, args); } } final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { for (String inPath : inPaths) { if (streaming) { String name = new File(inPath).getName(); byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8); if (doAddFile(sessionId, name, params.sessionParams.sizeBytes, metadata, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { if (isStreaming) { if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex) != PackageInstaller.STATUS_SUCCESS) { return 1; } } else { String splitName = hasSplits ? new File(inPath).getName() : "base." + (isApex ? "apex" : "apk"); if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex) != PackageInstaller.STATUS_SUCCESS) { return 1; } } } if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; Loading Loading @@ -2956,23 +2953,71 @@ class PackageManagerShellCommand extends ShellCommand { return sessionId; } private int doAddFile(int sessionId, String name, long sizeBytes, byte[] metadata, boolean logSuccess) throws RemoteException { private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes, boolean isApex) throws RemoteException { PackageInstaller.Session session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); try { session.addFile(name, sizeBytes, metadata); // 1. Single file from stdin. if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) { String name = "base." + (isApex ? "apex" : "apk"); session.addFile(name, sessionSizeBytes, STDIN_PATH_BYTES); return 0; } if (logSuccess) { getOutPrintWriter().println("Success"); for (String arg : args) { final int delimLocation = arg.indexOf(':'); // 2. File with specified size read from stdin. if (delimLocation != -1) { String name = arg.substring(0, delimLocation); String sizeStr = arg.substring(delimLocation + 1); long sizeBytes; if (TextUtils.isEmpty(name)) { getErrPrintWriter().println("Empty file name in: " + arg); return 1; } try { sizeBytes = Long.parseUnsignedLong(sizeStr); } catch (NumberFormatException e) { getErrPrintWriter().println("Unable to parse size from: " + arg); return 1; } session.addFile(name, sizeBytes, STDIN_PATH_BYTES); continue; } // 3. Local file. final String inPath = arg; String name = new File(inPath).getName(); byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8); session.addFile(name, -1, metadata); } return 0; } finally { IoUtils.closeQuietly(session); } } private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes, boolean isApex) throws RemoteException { final boolean multipleSplits = splitPaths.size() > 1; for (String splitPath : splitPaths) { String splitName = multipleSplits ? new File(splitPath).getName() : "base." + (isApex ? "apex" : "apk"); if (doWriteSplit(sessionId, splitPath, sessionSizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } } return 0; } private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess) throws RemoteException { PackageInstaller.Session session = null; Loading