Merge "Some small binder shell command improvements."
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 1af2034..d73deb6 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -468,6 +468,9 @@
/**
* Handle a call to {@link #shellCommand}. The default implementation simply prints
* an error message. Override and replace with your own.
+ * <p class="caution">Note: no permission checking is done before calling this method; you must
+ * apply any security checks as appropriate for the command being executed.
+ * Consider using {@link ShellCommand} to help in the implementation.</p>
* @hide
*/
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 6f12b62..54d1090 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -24,9 +24,11 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
+import java.io.OutputStream;
import java.io.PrintWriter;
/**
+ * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}.
* @hide
*/
public abstract class ShellCommand {
@@ -44,6 +46,10 @@
private int mArgPos;
private String mCurArgData;
+ private FileInputStream mFileIn;
+ private FileOutputStream mFileOut;
+ private FileOutputStream mFileErr;
+
private FastPrintWriter mOutPrintWriter;
private FastPrintWriter mErrPrintWriter;
private InputStream mInputStream;
@@ -59,8 +65,12 @@
mCmd = null;
mArgPos = firstArgPos;
mCurArgData = null;
+ mFileIn = null;
+ mFileOut = null;
+ mFileErr = null;
mOutPrintWriter = null;
mErrPrintWriter = null;
+ mInputStream = null;
}
public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
@@ -112,28 +122,65 @@
return res;
}
+ /**
+ * Return direct raw access (not buffered) to the command's output data stream.
+ */
+ public OutputStream getRawOutputStream() {
+ if (mFileOut == null) {
+ mFileOut = new FileOutputStream(mOut);
+ }
+ return mFileOut;
+ }
+
+ /**
+ * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
+ */
public PrintWriter getOutPrintWriter() {
if (mOutPrintWriter == null) {
- FileOutputStream fout = new FileOutputStream(mOut);
- mOutPrintWriter = new FastPrintWriter(fout);
+ mOutPrintWriter = new FastPrintWriter(getRawOutputStream());
}
return mOutPrintWriter;
}
+ /**
+ * Return direct raw access (not buffered) to the command's error output data stream.
+ */
+ public OutputStream getRawErrorStream() {
+ if (mFileErr == null) {
+ mFileErr = new FileOutputStream(mErr);
+ }
+ return mFileErr;
+ }
+
+ /**
+ * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
+ */
public PrintWriter getErrPrintWriter() {
if (mErr == null) {
return getOutPrintWriter();
}
if (mErrPrintWriter == null) {
- FileOutputStream fout = new FileOutputStream(mErr);
- mErrPrintWriter = new FastPrintWriter(fout);
+ mErrPrintWriter = new FastPrintWriter(getRawErrorStream());
}
return mErrPrintWriter;
}
- public InputStream getInputStream() {
+ /**
+ * Return direct raw access (not buffered) to the command's input data stream.
+ */
+ public InputStream getRawInputStream() {
+ if (mFileIn == null) {
+ mFileIn = new FileInputStream(mIn);
+ }
+ return mFileIn;
+ }
+
+ /**
+ * Return buffered access to the command's {@link #getRawInputStream()}.
+ */
+ public InputStream getBufferedInputStream() {
if (mInputStream == null) {
- mInputStream = new BufferedInputStream(new FileInputStream(mIn));
+ mInputStream = new BufferedInputStream(getRawInputStream());
}
return mInputStream;
}
@@ -214,7 +261,28 @@
return -1;
}
+ /**
+ * Implement parsing and execution of a command. If it isn't a command you understand,
+ * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
+ * User {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
+ * to process additional command line arguments. Command output can be written to
+ * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
+ *
+ * <p class="caution">Note that no permission checking has been done before entering this function,
+ * so you need to be sure to do your own security verification for any commands you
+ * are executing. The easiest way to do this is to have the ShellCommand contain
+ * only a reference to your service's aidl interface, and do all of your command
+ * implementations on top of that -- that way you can rely entirely on your executing security
+ * code behind that interface.</p>
+ *
+ * @param cmd The first command line argument representing the name of the command to execute.
+ * @return Return the command result; generally 0 or positive indicates success and
+ * negative values indicate error.
+ */
public abstract int onCommand(String cmd);
+ /**
+ * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
+ */
public abstract void onHelp();
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 901749e..43e4b84 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -863,7 +863,7 @@
if (inPath != null) {
in = new FileInputStream(inPath);
} else {
- in = new SizedInputStream(getInputStream(), sizeBytes);
+ in = new SizedInputStream(getRawInputStream(), sizeBytes);
}
out = session.openWrite(splitName, 0, sizeBytes);