Loading services/core/java/com/android/server/pm/PackageManagerShellCommand.java +77 −31 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; Loading Loading @@ -438,8 +439,14 @@ class PackageManagerShellCommand extends ShellCommand { } } private void setParamsSize(InstallParams params, String inPath) { if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) { private void setParamsSize(InstallParams params, List<String> inPaths) { if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) { return; } long sessionSize = 0; for (String inPath : inPaths) { final ParcelFileDescriptor fd = openFileForSystem(inPath, "r"); if (fd == null) { getErrPrintWriter().println("Error: Can't open file: " + inPath); Loading @@ -449,8 +456,8 @@ class PackageManagerShellCommand extends ShellCommand { ApkLite baseApk = PackageParser.parseApkLite(fd.getFileDescriptor(), inPath, 0); PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null, null, null); params.sessionParams.setSize(PackageHelper.calculateInstalledSize( pkgLite, params.sessionParams.abiOverride, fd.getFileDescriptor())); sessionSize += PackageHelper.calculateInstalledSize(pkgLite, params.sessionParams.abiOverride, fd.getFileDescriptor()); } catch (PackageParserException | IOException e) { getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath); throw new IllegalArgumentException( Loading @@ -462,6 +469,7 @@ class PackageManagerShellCommand extends ShellCommand { } } } params.sessionParams.setSize(sessionSize); } /** * Displays the package file for a package. Loading Loading @@ -1148,24 +1156,45 @@ class PackageManagerShellCommand extends ShellCommand { private int runInstall() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final InstallParams params = makeInstallParams(); final String inPath = getNextArg(); setParamsSize(params, inPath); final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { if (inPath == null && params.sessionParams.sizeBytes == -1) { ArrayList<String> inPaths = getRemainingArgs(); if (inPaths.isEmpty()) { inPaths.add(STDIN_PATH); } final boolean hasSplits = inPaths.size() > 1; 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) { 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; String splitName = "base." + (isApex ? "apex" : "apk"); if (isApex && hasSplits) { pw.println("Error: can't specify SPLIT(s) for APEX"); return 1; } setParamsSize(params, inPaths); final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { for (String inPath : inPaths) { String splitName = hasSplits ? (new File(inPath)).getName() : "base." + (isApex ? "apex" : "apk"); if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } } if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; Loading Loading @@ -1283,12 +1312,12 @@ class PackageManagerShellCommand extends ShellCommand { final int sessionId = Integer.parseInt(getNextArg()); final String splitName = getNextArg(); if (splitName == null) { ArrayList<String> splitNames = getRemainingArgs(); if (splitNames.isEmpty()) { pw.println("Error: split name not specified"); return 1; } return doRemoveSplit(sessionId, splitName, true /*logSuccess*/); return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/); } private int runInstallExisting() throws RemoteException { Loading Loading @@ -1731,6 +1760,15 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } private ArrayList<String> getRemainingArgs() { ArrayList<String> args = new ArrayList<>(); String arg; while ((arg = getNextArg()) != null) { args.add(arg); } return args; } private static class SnapshotRuntimeProfileCallback extends ISnapshotRuntimeProfileCallback.Stub { private boolean mSuccess = false; Loading Loading @@ -1802,9 +1840,9 @@ class PackageManagerShellCommand extends ShellCommand { } // if a split is specified, just remove it and not the whole package final String splitName = getNextArg(); if (splitName != null) { return runRemoveSplit(packageName, splitName); ArrayList<String> splitNames = getRemainingArgs(); if (!splitNames.isEmpty()) { return runRemoveSplits(packageName, splitNames); } userId = translateUserId(userId, true /*allowAll*/, "runUninstall"); Loading Loading @@ -1852,7 +1890,8 @@ class PackageManagerShellCommand extends ShellCommand { } } private int runRemoveSplit(String packageName, String splitName) throws RemoteException { private int runRemoveSplits(String packageName, Collection<String> splitNames) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; Loading @@ -1861,7 +1900,7 @@ class PackageManagerShellCommand extends ShellCommand { doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL); boolean abandonSession = true; try { if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/) if (doRemoveSplits(sessionId, splitNames, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } Loading Loading @@ -2945,14 +2984,17 @@ class PackageManagerShellCommand extends ShellCommand { } } private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess) private int doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); PackageInstaller.Session session = null; try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); for (String splitName : splitNames) { session.removeSplit(splitName); } if (logSuccess) { pw.println("Success"); Loading Loading @@ -3237,9 +3279,9 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" [--enable-rollback]"); pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]"); pw.println(" [--apex] [--wait TIMEOUT]"); pw.println(" [PATH|-]"); pw.println(" Install an application. Must provide the apk data to install, either as a"); pw.println(" file path or '-' to read from stdin. Options are:"); pw.println(" [PATH [SPLIT...]|-]"); pw.println(" Install an application. Must provide the apk data to install, either as"); pw.println(" file path(s) or '-' to read from stdin. Options are:"); pw.println(" -R: disallow replacement of existing application"); pw.println(" -t: allow test packages"); pw.println(" -i: specify package name of installer owning the app"); Loading Loading @@ -3293,6 +3335,9 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" will be read from stdin. Options are:"); pw.println(" -S: size in bytes of package, required for stdin"); pw.println(""); pw.println(" install-remove SESSION_ID SPLIT..."); pw.println(" Mark SPLIT(s) as removed in the given install session."); pw.println(""); pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs"); pw.println(" Add one or more session IDs to a multi-package session."); pw.println(""); Loading @@ -3317,9 +3362,10 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(""); pw.println(" move-primary-storage [internal|UUID]"); pw.println(""); pw.println(" pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE [SPLIT]"); pw.println(" uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]"); pw.println(" PACKAGE [SPLIT...]"); pw.println(" Remove the given package name from the system. May remove an entire app"); pw.println(" if no SPLIT name is specified, otherwise will remove only the split of the"); pw.println(" if no SPLIT names specified, otherwise will remove only the splits of the"); pw.println(" given app. Options are:"); pw.println(" -k: keep the data and cache directories around after package removal."); pw.println(" --user: remove the app from the given user."); Loading Loading
services/core/java/com/android/server/pm/PackageManagerShellCommand.java +77 −31 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; Loading Loading @@ -438,8 +439,14 @@ class PackageManagerShellCommand extends ShellCommand { } } private void setParamsSize(InstallParams params, String inPath) { if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) { private void setParamsSize(InstallParams params, List<String> inPaths) { if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) { return; } long sessionSize = 0; for (String inPath : inPaths) { final ParcelFileDescriptor fd = openFileForSystem(inPath, "r"); if (fd == null) { getErrPrintWriter().println("Error: Can't open file: " + inPath); Loading @@ -449,8 +456,8 @@ class PackageManagerShellCommand extends ShellCommand { ApkLite baseApk = PackageParser.parseApkLite(fd.getFileDescriptor(), inPath, 0); PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null, null, null); params.sessionParams.setSize(PackageHelper.calculateInstalledSize( pkgLite, params.sessionParams.abiOverride, fd.getFileDescriptor())); sessionSize += PackageHelper.calculateInstalledSize(pkgLite, params.sessionParams.abiOverride, fd.getFileDescriptor()); } catch (PackageParserException | IOException e) { getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath); throw new IllegalArgumentException( Loading @@ -462,6 +469,7 @@ class PackageManagerShellCommand extends ShellCommand { } } } params.sessionParams.setSize(sessionSize); } /** * Displays the package file for a package. Loading Loading @@ -1148,24 +1156,45 @@ class PackageManagerShellCommand extends ShellCommand { private int runInstall() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final InstallParams params = makeInstallParams(); final String inPath = getNextArg(); setParamsSize(params, inPath); final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { if (inPath == null && params.sessionParams.sizeBytes == -1) { ArrayList<String> inPaths = getRemainingArgs(); if (inPaths.isEmpty()) { inPaths.add(STDIN_PATH); } final boolean hasSplits = inPaths.size() > 1; 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) { 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; String splitName = "base." + (isApex ? "apex" : "apk"); if (isApex && hasSplits) { pw.println("Error: can't specify SPLIT(s) for APEX"); return 1; } setParamsSize(params, inPaths); final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { for (String inPath : inPaths) { String splitName = hasSplits ? (new File(inPath)).getName() : "base." + (isApex ? "apex" : "apk"); if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } } if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; Loading Loading @@ -1283,12 +1312,12 @@ class PackageManagerShellCommand extends ShellCommand { final int sessionId = Integer.parseInt(getNextArg()); final String splitName = getNextArg(); if (splitName == null) { ArrayList<String> splitNames = getRemainingArgs(); if (splitNames.isEmpty()) { pw.println("Error: split name not specified"); return 1; } return doRemoveSplit(sessionId, splitName, true /*logSuccess*/); return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/); } private int runInstallExisting() throws RemoteException { Loading Loading @@ -1731,6 +1760,15 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } private ArrayList<String> getRemainingArgs() { ArrayList<String> args = new ArrayList<>(); String arg; while ((arg = getNextArg()) != null) { args.add(arg); } return args; } private static class SnapshotRuntimeProfileCallback extends ISnapshotRuntimeProfileCallback.Stub { private boolean mSuccess = false; Loading Loading @@ -1802,9 +1840,9 @@ class PackageManagerShellCommand extends ShellCommand { } // if a split is specified, just remove it and not the whole package final String splitName = getNextArg(); if (splitName != null) { return runRemoveSplit(packageName, splitName); ArrayList<String> splitNames = getRemainingArgs(); if (!splitNames.isEmpty()) { return runRemoveSplits(packageName, splitNames); } userId = translateUserId(userId, true /*allowAll*/, "runUninstall"); Loading Loading @@ -1852,7 +1890,8 @@ class PackageManagerShellCommand extends ShellCommand { } } private int runRemoveSplit(String packageName, String splitName) throws RemoteException { private int runRemoveSplits(String packageName, Collection<String> splitNames) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; Loading @@ -1861,7 +1900,7 @@ class PackageManagerShellCommand extends ShellCommand { doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL); boolean abandonSession = true; try { if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/) if (doRemoveSplits(sessionId, splitNames, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } Loading Loading @@ -2945,14 +2984,17 @@ class PackageManagerShellCommand extends ShellCommand { } } private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess) private int doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); PackageInstaller.Session session = null; try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); for (String splitName : splitNames) { session.removeSplit(splitName); } if (logSuccess) { pw.println("Success"); Loading Loading @@ -3237,9 +3279,9 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" [--enable-rollback]"); pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]"); pw.println(" [--apex] [--wait TIMEOUT]"); pw.println(" [PATH|-]"); pw.println(" Install an application. Must provide the apk data to install, either as a"); pw.println(" file path or '-' to read from stdin. Options are:"); pw.println(" [PATH [SPLIT...]|-]"); pw.println(" Install an application. Must provide the apk data to install, either as"); pw.println(" file path(s) or '-' to read from stdin. Options are:"); pw.println(" -R: disallow replacement of existing application"); pw.println(" -t: allow test packages"); pw.println(" -i: specify package name of installer owning the app"); Loading Loading @@ -3293,6 +3335,9 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" will be read from stdin. Options are:"); pw.println(" -S: size in bytes of package, required for stdin"); pw.println(""); pw.println(" install-remove SESSION_ID SPLIT..."); pw.println(" Mark SPLIT(s) as removed in the given install session."); pw.println(""); pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs"); pw.println(" Add one or more session IDs to a multi-package session."); pw.println(""); Loading @@ -3317,9 +3362,10 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(""); pw.println(" move-primary-storage [internal|UUID]"); pw.println(""); pw.println(" pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE [SPLIT]"); pw.println(" uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]"); pw.println(" PACKAGE [SPLIT...]"); pw.println(" Remove the given package name from the system. May remove an entire app"); pw.println(" if no SPLIT name is specified, otherwise will remove only the split of the"); pw.println(" if no SPLIT names specified, otherwise will remove only the splits of the"); pw.println(" given app. Options are:"); pw.println(" -k: keep the data and cache directories around after package removal."); pw.println(" --user: remove the app from the given user."); Loading