summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java267
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java38
-rw-r--r--core/java/android/os/Binder.java16
-rw-r--r--core/java/android/os/IBinder.java4
-rw-r--r--core/java/android/os/ShellCallback.java114
-rw-r--r--core/java/android/os/ShellCommand.java17
-rw-r--r--core/java/com/android/internal/os/BaseCommand.java12
-rw-r--r--core/java/com/android/internal/os/IShellCallback.aidl24
-rw-r--r--services/core/java/com/android/server/AppOpsService.java6
-rw-r--r--services/core/java/com/android/server/BatteryService.java8
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java8
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java9
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java295
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java2
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java12
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java7
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java6
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java6
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java8
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateService.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java2
-rw-r--r--tests/VoiceInteraction/AndroidManifest.xml2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java3
27 files changed, 617 insertions, 274 deletions
diff --git a/Android.mk b/Android.mk
index 121a38efd587..e352bc70d085 100644
--- a/Android.mk
+++ b/Android.mk
@@ -332,6 +332,7 @@ LOCAL_SRC_FILES += \
core/java/com/android/internal/os/IDropBoxManagerService.aidl \
core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl \
core/java/com/android/internal/os/IResultReceiver.aidl \
+ core/java/com/android/internal/os/IShellCallback.aidl \
core/java/com/android/internal/statusbar/IStatusBar.aidl \
core/java/com/android/internal/statusbar/IStatusBarService.aidl \
core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 91334bd87296..3759de2e7197 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -26,7 +26,6 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerNative;
-import android.app.ActivityOptions;
import android.app.IActivityContainer;
import android.app.IActivityController;
import android.app.IActivityManager;
@@ -46,7 +45,6 @@ import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.ParceledListSlice;
-import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -55,10 +53,11 @@ import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.SELinux;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.ShellCommand;
-import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -72,6 +71,7 @@ import com.android.internal.util.Preconditions;
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -96,6 +96,7 @@ public class Am extends BaseCommand {
// Amount we reduce the stack size by when testing a task re-size.
private static final int STACK_BOUNDS_INSET = 10;
+ public static final String NO_CLASS_ERROR_CODE = "Error type 3";
private IActivityManager mAm;
private IPackageManager mPm;
@@ -198,7 +199,7 @@ public class Am extends BaseCommand {
" --track-allocation: enable tracking of object allocations\n" +
" --user <USER_ID> | current: Specify which user to run as; if not\n" +
" specified then run as the current user.\n" +
- " --stack <STACK_ID>: Specify into which stack should the activity be put." +
+ " --stack <STACK_ID>: Specify into which stack should the activity be put.\n" +
"\n" +
"am startservice: start a Service. Options are:\n" +
" --user <USER_ID> | current: Specify which user to run as; if not\n" +
@@ -385,17 +386,13 @@ public class Am extends BaseCommand {
String op = nextArgRequired();
if (op.equals("start")) {
- runStart();
+ runAmCmd(getRawArgs());
} else if (op.equals("startservice")) {
runStartService();
} else if (op.equals("stopservice")) {
runStopService();
- } else if (op.equals("force-stop")) {
- runForceStop();
- } else if (op.equals("kill")) {
- runKill();
- } else if (op.equals("kill-all")) {
- runKillAll();
+ } else if (op.equals("force-stop") || op.equals("kill") || op.equals("kill-all")) {
+ runAmCmd(getRawArgs());
} else if (op.equals("instrument")) {
runInstrument();
} else if (op.equals("trace-ipc")) {
@@ -475,6 +472,49 @@ public class Am extends BaseCommand {
return userId;
}
+ static final class MyShellCallback extends ShellCallback {
+ @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
+ File file = new File(path);
+ //System.err.println("Opening file: " + file.getAbsolutePath());
+ //Log.i("Am", "Opening file: " + file.getAbsolutePath());
+ final ParcelFileDescriptor fd;
+ try {
+ fd = ParcelFileDescriptor.open(file,
+ ParcelFileDescriptor.MODE_CREATE |
+ ParcelFileDescriptor.MODE_TRUNCATE |
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
+ } catch (FileNotFoundException e) {
+ String msg = "Unable to open file " + path + ": " + e;
+ System.err.println(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (seLinuxContext != null) {
+ final String tcon = SELinux.getFileContext(file.getAbsolutePath());
+ if (!SELinux.checkSELinuxAccess(seLinuxContext, tcon, "file", "write")) {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ }
+ String msg = "System server has no access to file context " + tcon;
+ System.err.println(msg + " (from path " + file.getAbsolutePath()
+ + ", context " + seLinuxContext + ")");
+ throw new IllegalArgumentException(msg);
+ }
+ }
+ return fd;
+ }
+ }
+
+ void runAmCmd(String[] args) throws AndroidException {
+ try {
+ mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ args, new MyShellCallback(), new ResultReceiver(null) { });
+ } catch (RemoteException e) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException("Can't call activity manager; is the system running?");
+ }
+ }
+
private Intent makeIntent(int defUser) throws URISyntaxException {
mStartFlags = 0;
mWaitOption = false;
@@ -558,211 +598,6 @@ public class Am extends BaseCommand {
}
}
- private void runStart() throws Exception {
- Intent intent = makeIntent(UserHandle.USER_CURRENT);
-
- if (mUserId == UserHandle.USER_ALL) {
- System.err.println("Error: Can't start service with user 'all'");
- return;
- }
-
- String mimeType = intent.getType();
- if (mimeType == null && intent.getData() != null
- && "content".equals(intent.getData().getScheme())) {
- mimeType = mAm.getProviderMimeType(intent.getData(), mUserId);
- }
-
-
- do {
- if (mStopOption) {
- String packageName;
- if (intent.getComponent() != null) {
- packageName = intent.getComponent().getPackageName();
- } else {
- List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
- mUserId).getList();
- if (activities == null || activities.size() <= 0) {
- System.err.println("Error: Intent does not match any activities: "
- + intent);
- return;
- } else if (activities.size() > 1) {
- System.err.println("Error: Intent matches multiple activities; can't stop: "
- + intent);
- return;
- }
- packageName = activities.get(0).activityInfo.packageName;
- }
- System.out.println("Stopping: " + packageName);
- mAm.forceStopPackage(packageName, mUserId);
- Thread.sleep(250);
- }
-
- System.out.println("Starting: " + intent);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- ParcelFileDescriptor fd = null;
- ProfilerInfo profilerInfo = null;
-
- if (mProfileFile != null) {
- try {
- fd = openForSystemServer(
- new File(mProfileFile),
- ParcelFileDescriptor.MODE_CREATE |
- ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_WRITE_ONLY);
- } catch (FileNotFoundException e) {
- System.err.println("Error: Unable to open file: " + mProfileFile);
- System.err.println("Consider using a file under /data/local/tmp/");
- return;
- }
- profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop);
- }
-
- IActivityManager.WaitResult result = null;
- int res;
- final long startTime = SystemClock.uptimeMillis();
- ActivityOptions options = null;
- if (mStackId != INVALID_STACK_ID) {
- options = ActivityOptions.makeBasic();
- options.setLaunchStackId(mStackId);
- }
- if (mWaitOption) {
- result = mAm.startActivityAndWait(null, null, intent, mimeType,
- null, null, 0, mStartFlags, profilerInfo,
- options != null ? options.toBundle() : null, mUserId);
- res = result.result;
- } else {
- res = mAm.startActivityAsUser(null, null, intent, mimeType,
- null, null, 0, mStartFlags, profilerInfo,
- options != null ? options.toBundle() : null, mUserId);
- }
- final long endTime = SystemClock.uptimeMillis();
- PrintStream out = mWaitOption ? System.out : System.err;
- boolean launched = false;
- switch (res) {
- case ActivityManager.START_SUCCESS:
- launched = true;
- break;
- case ActivityManager.START_SWITCHES_CANCELED:
- launched = true;
- out.println(
- "Warning: Activity not started because the "
- + " current activity is being kept for the user.");
- break;
- case ActivityManager.START_DELIVERED_TO_TOP:
- launched = true;
- out.println(
- "Warning: Activity not started, intent has "
- + "been delivered to currently running "
- + "top-most instance.");
- break;
- case ActivityManager.START_RETURN_INTENT_TO_CALLER:
- launched = true;
- out.println(
- "Warning: Activity not started because intent "
- + "should be handled by the caller");
- break;
- case ActivityManager.START_TASK_TO_FRONT:
- launched = true;
- out.println(
- "Warning: Activity not started, its current "
- + "task has been brought to the front");
- break;
- case ActivityManager.START_INTENT_NOT_RESOLVED:
- out.println(
- "Error: Activity not started, unable to "
- + "resolve " + intent.toString());
- break;
- case ActivityManager.START_CLASS_NOT_FOUND:
- out.println(NO_CLASS_ERROR_CODE);
- out.println("Error: Activity class " +
- intent.getComponent().toShortString()
- + " does not exist.");
- break;
- case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
- out.println(
- "Error: Activity not started, you requested to "
- + "both forward and receive its result");
- break;
- case ActivityManager.START_PERMISSION_DENIED:
- out.println(
- "Error: Activity not started, you do not "
- + "have permission to access it.");
- break;
- case ActivityManager.START_NOT_VOICE_COMPATIBLE:
- out.println(
- "Error: Activity not started, voice control not allowed for: "
- + intent);
- break;
- case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
- out.println(
- "Error: Not allowed to start background user activity"
- + " that shouldn't be displayed for all users.");
- break;
- default:
- out.println(
- "Error: Activity not started, unknown error code " + res);
- break;
- }
- if (mWaitOption && launched) {
- if (result == null) {
- result = new IActivityManager.WaitResult();
- result.who = intent.getComponent();
- }
- System.out.println("Status: " + (result.timeout ? "timeout" : "ok"));
- if (result.who != null) {
- System.out.println("Activity: " + result.who.flattenToShortString());
- }
- if (result.thisTime >= 0) {
- System.out.println("ThisTime: " + result.thisTime);
- }
- if (result.totalTime >= 0) {
- System.out.println("TotalTime: " + result.totalTime);
- }
- System.out.println("WaitTime: " + (endTime-startTime));
- System.out.println("Complete");
- }
- mRepeat--;
- if (mRepeat > 0) {
- mAm.unhandledBack();
- }
- } while (mRepeat > 0);
- }
-
- private void runForceStop() throws Exception {
- int userId = UserHandle.USER_ALL;
-
- String opt;
- while ((opt=nextOption()) != null) {
- if (opt.equals("--user")) {
- userId = parseUserArg(nextArgRequired());
- } else {
- System.err.println("Error: Unknown option: " + opt);
- return;
- }
- }
- mAm.forceStopPackage(nextArgRequired(), userId);
- }
-
- private void runKill() throws Exception {
- int userId = UserHandle.USER_ALL;
-
- String opt;
- while ((opt=nextOption()) != null) {
- if (opt.equals("--user")) {
- userId = parseUserArg(nextArgRequired());
- } else {
- System.err.println("Error: Unknown option: " + opt);
- return;
- }
- }
- mAm.killBackgroundProcesses(nextArgRequired(), userId);
- }
-
- private void runKillAll() throws Exception {
- mAm.killAllBackgroundProcesses();
- }
-
private void sendBroadcast() throws Exception {
Intent intent = makeIntent(UserHandle.USER_CURRENT);
IntentReceiver receiver = new IntentReceiver();
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 32a8088e9c4e..ace4e3284930 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -49,9 +49,12 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IUserManager;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.SELinux;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
@@ -68,6 +71,7 @@ import libcore.io.IoUtils;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -284,13 +288,45 @@ public final class Pm {
}
}
+ static final class MyShellCallback extends ShellCallback {
+ @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
+ File file = new File(path);
+ final ParcelFileDescriptor fd;
+ try {
+ fd = ParcelFileDescriptor.open(file,
+ ParcelFileDescriptor.MODE_CREATE |
+ ParcelFileDescriptor.MODE_TRUNCATE |
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
+ } catch (FileNotFoundException e) {
+ String msg = "Unable to open file " + path + ": " + e;
+ System.err.println(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (seLinuxContext != null) {
+ final String tcon = SELinux.getFileContext(file.getAbsolutePath());
+ if (!SELinux.checkSELinuxAccess(seLinuxContext, tcon, "file", "write")) {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ }
+ String msg = "System server has no access to file context " + tcon;
+ System.err.println(msg + " (from path " + file.getAbsolutePath()
+ + ", context " + seLinuxContext + ")");
+ throw new IllegalArgumentException(msg);
+ }
+ }
+ return fd;
+ }
+ }
+
private int runShellCommand(String serviceName, String[] args) {
final HandlerThread handlerThread = new HandlerThread("results");
handlerThread.start();
try {
ServiceManager.getService(serviceName).shellCommand(
FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
- args, new ResultReceiver(new Handler(handlerThread.getLooper())));
+ args, new MyShellCallback(),
+ new ResultReceiver(new Handler(handlerThread.getLooper())));
return 0;
} catch (RemoteException e) {
e.printStackTrace();
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ea8ba2f1e6df..cf77567540f0 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -23,7 +23,6 @@ import libcore.io.IoUtils;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Modifier;
@@ -361,13 +360,14 @@ public class Binder implements IBinder {
ParcelFileDescriptor out = data.readFileDescriptor();
ParcelFileDescriptor err = data.readFileDescriptor();
String[] args = data.readStringArray();
+ ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
try {
if (out != null) {
shellCommand(in != null ? in.getFileDescriptor() : null,
out.getFileDescriptor(),
err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
- args, resultReceiver);
+ args, shellCallback, resultReceiver);
}
} finally {
IoUtils.closeQuietly(in);
@@ -459,13 +459,15 @@ public class Binder implements IBinder {
* @param out The raw file descriptor that normal command messages should be written to.
* @param err The raw file descriptor that command error messages should be written to.
* @param args Command-line arguments.
+ * @param callback Callback through which to interact with the invoking shell.
* @param resultReceiver Called when the command has finished executing, with the result code.
* @throws RemoteException
* @hide
*/
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException {
- onShellCommand(in, out, err, args, resultReceiver);
+ String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) throws RemoteException {
+ onShellCommand(in, out, err, args, callback, resultReceiver);
}
/**
@@ -477,7 +479,7 @@ public class Binder implements IBinder {
* @hide
*/
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException {
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException {
FileOutputStream fout = new FileOutputStream(err != null ? err : out);
PrintWriter pw = new FastPrintWriter(fout);
pw.println("No shell command implementation.");
@@ -650,13 +652,15 @@ final class BinderProxy implements IBinder {
}
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException {
+ String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeFileDescriptor(in);
data.writeFileDescriptor(out);
data.writeFileDescriptor(err);
data.writeStringArray(args);
+ ShellCallback.writeToParcel(callback, data);
resultReceiver.writeToParcel(data, 0);
try {
transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 0fa87509a77a..f762a052cb41 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -220,11 +220,13 @@ public interface IBinder {
* @param out The raw file descriptor that normal command messages should be written to.
* @param err The raw file descriptor that command error messages should be written to.
* @param args Command-line arguments.
+ * @param shellCallback Optional callback to the caller's shell to perform operations in it.
* @param resultReceiver Called when the command has finished executing, with the result code.
* @hide
*/
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException;
+ String[] args, ShellCallback shellCallback,
+ ResultReceiver resultReceiver) throws RemoteException;
/**
* Perform a generic operation with the object.
diff --git a/core/java/android/os/ShellCallback.java b/core/java/android/os/ShellCallback.java
new file mode 100644
index 000000000000..e7fe697f9c54
--- /dev/null
+++ b/core/java/android/os/ShellCallback.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.util.Log;
+
+import com.android.internal.os.IShellCallback;
+
+/**
+ * Special-purpose API for use with {@link IBinder#shellCommand IBinder.shellCommand} for
+ * performing operations back on the invoking shell.
+ * @hide
+ */
+public class ShellCallback implements Parcelable {
+ final static String TAG = "ShellCallback";
+
+ final static boolean DEBUG = false;
+
+ final boolean mLocal;
+
+ IShellCallback mShellCallback;
+
+ class MyShellCallback extends IShellCallback.Stub {
+ public ParcelFileDescriptor openOutputFile(String path, String seLinuxContext) {
+ return onOpenOutputFile(path, seLinuxContext);
+ }
+ }
+
+ /**
+ * Create a new ShellCallback to receive requests.
+ */
+ public ShellCallback() {
+ mLocal = true;
+ }
+
+ /**
+ * Ask the shell to open a file for writing. This will truncate the file if it
+ * already exists. It will create the file if it doesn't exist.
+ * @param path Path of the file to be opened/created.
+ * @param seLinuxContext Optional SELinux context that must be allowed to have
+ * access to the file; if null, nothing is required.
+ */
+ public ParcelFileDescriptor openOutputFile(String path, String seLinuxContext) {
+ if (DEBUG) Log.d(TAG, "openOutputFile " + this + ": mLocal=" + mLocal
+ + " mShellCallback=" + mShellCallback);
+
+ if (mLocal) {
+ return onOpenOutputFile(path, seLinuxContext);
+ }
+
+ if (mShellCallback != null) {
+ try {
+ return mShellCallback.openOutputFile(path, seLinuxContext);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failure opening " + path, e);
+ }
+ }
+ return null;
+ }
+
+ public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
+ return null;
+ }
+
+ public static void writeToParcel(ShellCallback callback, Parcel out) {
+ if (callback == null) {
+ out.writeStrongBinder(null);
+ } else {
+ callback.writeToParcel(out, 0);
+ }
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ synchronized (this) {
+ if (mShellCallback == null) {
+ mShellCallback = new MyShellCallback();
+ }
+ out.writeStrongBinder(mShellCallback.asBinder());
+ }
+ }
+
+ ShellCallback(Parcel in) {
+ mLocal = false;
+ mShellCallback = IShellCallback.Stub.asInterface(in.readStrongBinder());
+ }
+
+ public static final Parcelable.Creator<ShellCallback> CREATOR
+ = new Parcelable.Creator<ShellCallback>() {
+ public ShellCallback createFromParcel(Parcel in) {
+ return new ShellCallback(in);
+ }
+ public ShellCallback[] newArray(int size) {
+ return new ShellCallback[size];
+ }
+ };
+}
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index fc804e592148..831c9b27ac45 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -40,6 +40,7 @@ public abstract class ShellCommand {
private FileDescriptor mOut;
private FileDescriptor mErr;
private String[] mArgs;
+ private ShellCallback mShellCallback;
private ResultReceiver mResultReceiver;
private String mCmd;
@@ -55,12 +56,13 @@ public abstract class ShellCommand {
private InputStream mInputStream;
public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, int firstArgPos) {
+ String[] args, ShellCallback callback, int firstArgPos) {
mTarget = target;
mIn = in;
mOut = out;
mErr = err;
mArgs = args;
+ mShellCallback = callback;
mResultReceiver = null;
mCmd = null;
mArgPos = firstArgPos;
@@ -74,7 +76,7 @@ public abstract class ShellCommand {
}
public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) {
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
String cmd;
int start;
if (args != null && args.length > 0) {
@@ -84,7 +86,7 @@ public abstract class ShellCommand {
cmd = null;
start = 0;
}
- init(target, in, out, err, args, start);
+ init(target, in, out, err, args, callback, start);
mCmd = cmd;
mResultReceiver = resultReceiver;
@@ -105,7 +107,7 @@ public abstract class ShellCommand {
// go.
PrintWriter eout = getErrPrintWriter();
eout.println();
- eout.println("Exception occurred while dumping:");
+ eout.println("Exception occurred while executing:");
e.printStackTrace(eout);
} finally {
if (DEBUG) Slog.d(TAG, "Flushing output streams on " + mTarget);
@@ -257,6 +259,13 @@ public abstract class ShellCommand {
return arg;
}
+ /**
+ * Return the {@link ShellCallback} for communicating back with the calling shell.
+ */
+ public ShellCallback getShellCallback() {
+ return mShellCallback;
+ }
+
public int handleDefaultCommands(String cmd) {
if ("dump".equals(cmd)) {
String[] newArgs = new String[mArgs.length-1];
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
index c067da7e1dec..3baccee049b0 100644
--- a/core/java/com/android/internal/os/BaseCommand.java
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -36,6 +36,8 @@ public abstract class BaseCommand {
public static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
public static final String NO_CLASS_ERROR_CODE = "Error type 3";
+ private String[] mRawArgs;
+
/**
* Call to run the command.
*/
@@ -45,7 +47,8 @@ public abstract class BaseCommand {
return;
}
- mArgs.init(null, null, null, null, args, 0);
+ mRawArgs = args;
+ mArgs.init(null, null, null, null, args, null, 0);
try {
onRun();
@@ -109,4 +112,11 @@ public abstract class BaseCommand {
public String nextArgRequired() {
return mArgs.getNextArgRequired();
}
+
+ /**
+ * Return the original raw argument list supplied to the command.
+ */
+ public String[] getRawArgs() {
+ return mRawArgs;
+ }
}
diff --git a/core/java/com/android/internal/os/IShellCallback.aidl b/core/java/com/android/internal/os/IShellCallback.aidl
new file mode 100644
index 000000000000..57d67890d840
--- /dev/null
+++ b/core/java/com/android/internal/os/IShellCallback.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.ParcelFileDescriptor;
+
+/** @hide */
+interface IShellCallback {
+ ParcelFileDescriptor openOutputFile(String path, String seLinuxContext);
+}
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 238bf927c43e..7c2eea3f68aa 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -51,6 +51,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.os.storage.MountServiceInternal;
@@ -1787,8 +1788,9 @@ public class AppOpsService extends IAppOpsService.Stub {
}
@Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
- (new Shell(this, this)).exec(this, in, out, err, args, resultReceiver);
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver);
}
static void dumpCommandHelp(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 6b517210ef31..d2cfb6d51002 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -20,6 +20,7 @@ import android.database.ContentObserver;
import android.os.BatteryStats;
import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.ShellCommand;
import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;
@@ -789,7 +790,7 @@ public final class BatteryService extends SystemService {
pw.println(" technology: " + mBatteryProps.batteryTechnology);
} else {
Shell shell = new Shell();
- shell.exec(mBinderService, null, fd, null, args, new ResultReceiver(null));
+ shell.exec(mBinderService, null, fd, null, args, null, new ResultReceiver(null));
}
}
}
@@ -875,8 +876,9 @@ public final class BatteryService extends SystemService {
}
@Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
- (new Shell()).exec(this, in, out, err, args, resultReceiver);
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
}
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 6b73fec8c920..dbc1f31a9348 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -60,6 +60,7 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -1232,8 +1233,8 @@ public class DeviceIdleController extends SystemService
}
@Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
- (new Shell()).exec(this, in, out, err, args, resultReceiver);
+ FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+ (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
}
}
@@ -2838,7 +2839,8 @@ public class DeviceIdleController extends SystemService
shell.userId = userId;
String[] newArgs = new String[args.length-i];
System.arraycopy(args, i, newArgs, 0, args.length-i);
- shell.exec(mBinderService, null, fd, null, newArgs, new ResultReceiver(null));
+ shell.exec(mBinderService, null, fd, null, newArgs, null,
+ new ResultReceiver(null));
return;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e5b611ca3231..03610868d04b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -182,6 +182,7 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -14024,9 +14025,10 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
(new ActivityManagerShellCommand(this, false)).exec(
- this, in, out, err, args, resultReceiver);
+ this, in, out, err, args, callback, resultReceiver);
}
@Override
@@ -14249,7 +14251,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// Dumping a single activity?
if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll, dumpVisibleStacks)) {
ActivityManagerShellCommand shell = new ActivityManagerShellCommand(this, true);
- int res = shell.exec(this, null, fd, null, args, new ResultReceiver(null));
+ int res = shell.exec(this, null, fd, null, args, null,
+ new ResultReceiver(null));
if (res < 0) {
pw.println("Bad activity command, or no activities match: " + cmd);
pw.println("Use -h for help.");
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index adf6d3670af3..aed9fa4435fd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -17,26 +17,57 @@
package com.android.server.am;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.AppGlobals;
import android.app.IActivityManager;
+import android.app.ProfilerInfo;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ShellCommand;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.DebugUtils;
import java.io.PrintWriter;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
class ActivityManagerShellCommand extends ShellCommand {
+ public static final String NO_CLASS_ERROR_CODE = "Error type 3";
+
// IPC interface to activity manager -- don't need to do additional security checks.
final IActivityManager mInterface;
// Internal service impl -- must perform security checks before touching.
final ActivityManagerService mInternal;
+ // Convenience for interacting with package manager.
+ final IPackageManager mPm;
+
+ private int mStartFlags = 0;
+ private boolean mWaitOption = false;
+ private boolean mStopOption = false;
+
+ private int mRepeat = 0;
+ private int mUserId;
+ private String mReceiverPermission;
+
+ private String mProfileFile;
+ private int mSamplingInterval;
+ private boolean mAutoStop;
+ private int mStackId;
+
final boolean mDumping;
ActivityManagerShellCommand(ActivityManagerService service, boolean dumping) {
mInterface = service;
mInternal = service;
+ mPm = AppGlobals.getPackageManager();
mDumping = dumping;
}
@@ -48,6 +79,15 @@ class ActivityManagerShellCommand extends ShellCommand {
PrintWriter pw = getOutPrintWriter();
try {
switch (cmd) {
+ case "start":
+ case "start-activity":
+ return runStartActivity(pw);
+ case "startservice":
+ case "start-service":
+ return 1; //runStartService(pw);
+ case "stopservice":
+ case "stop-service":
+ return 1; //runStopService(pw);
case "force-stop":
return runForceStop(pw);
case "kill":
@@ -75,6 +115,241 @@ class ActivityManagerShellCommand extends ShellCommand {
return -1;
}
+ private Intent makeIntent(int defUser) throws URISyntaxException {
+ mStartFlags = 0;
+ mWaitOption = false;
+ mStopOption = false;
+ mRepeat = 0;
+ mProfileFile = null;
+ mSamplingInterval = 0;
+ mAutoStop = false;
+ mUserId = defUser;
+ mStackId = INVALID_STACK_ID;
+
+ return Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
+ @Override
+ public boolean handleOption(String opt, ShellCommand cmd) {
+ if (opt.equals("-D")) {
+ mStartFlags |= ActivityManager.START_FLAG_DEBUG;
+ } else if (opt.equals("-N")) {
+ mStartFlags |= ActivityManager.START_FLAG_NATIVE_DEBUGGING;
+ } else if (opt.equals("-W")) {
+ mWaitOption = true;
+ } else if (opt.equals("-P")) {
+ mProfileFile = getNextArgRequired();
+ mAutoStop = true;
+ } else if (opt.equals("--start-profiler")) {
+ mProfileFile = getNextArgRequired();
+ mAutoStop = false;
+ } else if (opt.equals("--sampling")) {
+ mSamplingInterval = Integer.parseInt(getNextArgRequired());
+ } else if (opt.equals("-R")) {
+ mRepeat = Integer.parseInt(getNextArgRequired());
+ } else if (opt.equals("-S")) {
+ mStopOption = true;
+ } else if (opt.equals("--track-allocation")) {
+ mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION;
+ } else if (opt.equals("--user")) {
+ mUserId = UserHandle.parseUserArg(getNextArgRequired());
+ } else if (opt.equals("--receiver-permission")) {
+ mReceiverPermission = getNextArgRequired();
+ } else if (opt.equals("--stack")) {
+ mStackId = Integer.parseInt(getNextArgRequired());
+ } else {
+ return false;
+ }
+ return true;
+ }
+ });
+ }
+
+ ParcelFileDescriptor openOutputFile(String path) {
+ try {
+ ParcelFileDescriptor pfd = getShellCallback().openOutputFile(path,
+ "u:r:system_server:s0");
+ if (pfd != null) {
+ return pfd;
+ }
+ } catch (RuntimeException e) {
+ getErrPrintWriter().println("Failure opening file: " + e.getMessage());
+ }
+ getErrPrintWriter().println("Error: Unable to open file: " + path);
+ getErrPrintWriter().println("Consider using a file under /data/local/tmp/");
+ return null;
+ }
+
+ int runStartActivity(PrintWriter pw) throws RemoteException {
+ Intent intent;
+ try {
+ intent = makeIntent(UserHandle.USER_CURRENT);
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+
+ if (mUserId == UserHandle.USER_ALL) {
+ getErrPrintWriter().println("Error: Can't start service with user 'all'");
+ return 1;
+ }
+
+ String mimeType = intent.getType();
+ if (mimeType == null && intent.getData() != null
+ && "content".equals(intent.getData().getScheme())) {
+ mimeType = mInterface.getProviderMimeType(intent.getData(), mUserId);
+ }
+
+ do {
+ if (mStopOption) {
+ String packageName;
+ if (intent.getComponent() != null) {
+ packageName = intent.getComponent().getPackageName();
+ } else {
+ List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
+ mUserId).getList();
+ if (activities == null || activities.size() <= 0) {
+ getErrPrintWriter().println("Error: Intent does not match any activities: "
+ + intent);
+ return 1;
+ } else if (activities.size() > 1) {
+ getErrPrintWriter().println(
+ "Error: Intent matches multiple activities; can't stop: "
+ + intent);
+ return 1;
+ }
+ packageName = activities.get(0).activityInfo.packageName;
+ }
+ pw.println("Stopping: " + packageName);
+ mInterface.forceStopPackage(packageName, mUserId);
+ try {
+ Thread.sleep(250);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ ProfilerInfo profilerInfo = null;
+
+ if (mProfileFile != null) {
+ ParcelFileDescriptor fd = openOutputFile(mProfileFile);
+ if (fd == null) {
+ return 1;
+ }
+ profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop);
+ }
+
+ pw.println("Starting: " + intent);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ IActivityManager.WaitResult result = null;
+ int res;
+ final long startTime = SystemClock.uptimeMillis();
+ ActivityOptions options = null;
+ if (mStackId != INVALID_STACK_ID) {
+ options = ActivityOptions.makeBasic();
+ options.setLaunchStackId(mStackId);
+ }
+ if (mWaitOption) {
+ result = mInterface.startActivityAndWait(null, null, intent, mimeType,
+ null, null, 0, mStartFlags, profilerInfo,
+ options != null ? options.toBundle() : null, mUserId);
+ res = result.result;
+ } else {
+ res = mInterface.startActivityAsUser(null, null, intent, mimeType,
+ null, null, 0, mStartFlags, profilerInfo,
+ options != null ? options.toBundle() : null, mUserId);
+ }
+ final long endTime = SystemClock.uptimeMillis();
+ PrintWriter out = mWaitOption ? pw : getErrPrintWriter();
+ boolean launched = false;
+ switch (res) {
+ case ActivityManager.START_SUCCESS:
+ launched = true;
+ break;
+ case ActivityManager.START_SWITCHES_CANCELED:
+ launched = true;
+ out.println(
+ "Warning: Activity not started because the "
+ + " current activity is being kept for the user.");
+ break;
+ case ActivityManager.START_DELIVERED_TO_TOP:
+ launched = true;
+ out.println(
+ "Warning: Activity not started, intent has "
+ + "been delivered to currently running "
+ + "top-most instance.");
+ break;
+ case ActivityManager.START_RETURN_INTENT_TO_CALLER:
+ launched = true;
+ out.println(
+ "Warning: Activity not started because intent "
+ + "should be handled by the caller");
+ break;
+ case ActivityManager.START_TASK_TO_FRONT:
+ launched = true;
+ out.println(
+ "Warning: Activity not started, its current "
+ + "task has been brought to the front");
+ break;
+ case ActivityManager.START_INTENT_NOT_RESOLVED:
+ out.println(
+ "Error: Activity not started, unable to "
+ + "resolve " + intent.toString());
+ break;
+ case ActivityManager.START_CLASS_NOT_FOUND:
+ out.println(NO_CLASS_ERROR_CODE);
+ out.println("Error: Activity class " +
+ intent.getComponent().toShortString()
+ + " does not exist.");
+ break;
+ case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
+ out.println(
+ "Error: Activity not started, you requested to "
+ + "both forward and receive its result");
+ break;
+ case ActivityManager.START_PERMISSION_DENIED:
+ out.println(
+ "Error: Activity not started, you do not "
+ + "have permission to access it.");
+ break;
+ case ActivityManager.START_NOT_VOICE_COMPATIBLE:
+ out.println(
+ "Error: Activity not started, voice control not allowed for: "
+ + intent);
+ break;
+ case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
+ out.println(
+ "Error: Not allowed to start background user activity"
+ + " that shouldn't be displayed for all users.");
+ break;
+ default:
+ out.println(
+ "Error: Activity not started, unknown error code " + res);
+ break;
+ }
+ if (mWaitOption && launched) {
+ if (result == null) {
+ result = new IActivityManager.WaitResult();
+ result.who = intent.getComponent();
+ }
+ pw.println("Status: " + (result.timeout ? "timeout" : "ok"));
+ if (result.who != null) {
+ pw.println("Activity: " + result.who.flattenToShortString());
+ }
+ if (result.thisTime >= 0) {
+ pw.println("ThisTime: " + result.thisTime);
+ }
+ if (result.totalTime >= 0) {
+ pw.println("TotalTime: " + result.totalTime);
+ }
+ pw.println("WaitTime: " + (endTime-startTime));
+ pw.println("Complete");
+ }
+ mRepeat--;
+ if (mRepeat > 0) {
+ mInterface.unhandledBack();
+ }
+ } while (mRepeat > 0);
+ return 0;
+ }
+
int runIsUserStopped(PrintWriter pw) {
int userId = UserHandle.parseUserArg(getNextArgRequired());
boolean stopped = mInternal.isUserStopped(userId);
@@ -223,6 +498,24 @@ class ActivityManagerShellCommand extends ShellCommand {
pw.println("Activity manager (activity) commands:");
pw.println(" help");
pw.println(" Print this help text.");
+ pw.println(" start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
+ pw.println(" [--sampling INTERVAL] [-R COUNT] [-S]");
+ pw.println(" [--track-allocation] [--user <USER_ID> | current] <INTENT>");
+ pw.println(" Start an Activity. Options are:");
+ pw.println(" -D: enable debugging");
+ pw.println(" -N: enable native debugging");
+ pw.println(" -W: wait for launch to complete");
+ pw.println(" --start-profiler <FILE>: start profiler and send results to <FILE>");
+ pw.println(" --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
+ pw.println(" between samples (use with --start-profiler)");
+ pw.println(" -P <FILE>: like above, but profiling stops when app goes idle");
+ pw.println(" -R: repeat the activity launch <COUNT> times. Prior to each repeat,");
+ pw.println(" the top activity will be finished.");
+ pw.println(" -S: force stop the target app before starting the activity");
+ pw.println(" --track-allocation: enable tracking of object allocations");
+ pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
+ pw.println(" specified then run as the current user.");
+ pw.println(" --stack <STACK_ID>: Specify into which stack should the activity be put.");
pw.println(" force-stop [--user <USER_ID> | all | current] <PACKAGE>");
pw.println(" Completely stop the given application package.");
pw.println(" kill [--user <USER_ID> | all | current] <PACKAGE>");
@@ -241,6 +534,8 @@ class ActivityManagerShellCommand extends ShellCommand {
pw.println(" Optionally controls lenient background check mode, returns current mode.");
pw.println(" get-uid-state <UID>");
pw.println(" Gets the process state of an app given its <UID>.");
+ pw.println();
+ Intent.printIntentArgsHelp(pw, "");
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 7708b0205074..6b00c86bf699 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -5029,7 +5029,7 @@ final class ActivityStack {
if (top >= 0) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
int activityTop = activities.size() - 1;
- if (activityTop > 0) {
+ if (activityTop >= 0) {
finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
"unhandled-back", true);
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 74095acca16a..87f4030a9049 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -18,8 +18,8 @@ package com.android.server.input;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Build;
import android.os.LocaleList;
+import android.os.ShellCallback;
import android.util.Log;
import android.view.Display;
import com.android.internal.inputmethod.InputMethodSubtypeHandle;
@@ -91,10 +91,8 @@ import android.view.PointerIcon;
import android.view.Surface;
import android.view.ViewConfiguration;
import android.view.WindowManagerPolicy;
-import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
-import android.widget.Toast;
import java.io.File;
import java.io.FileDescriptor;
@@ -103,11 +101,8 @@ import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -1739,8 +1734,9 @@ public class InputManagerService extends IInputManager.Stub
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
- (new Shell()).exec(this, in, out, err, args, resultReceiver);
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
}
public int onShellCommand(Shell shell, String cmd) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 9d931467d914..fe3a02d193f6 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -44,9 +44,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -62,6 +60,7 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -1718,9 +1717,9 @@ public final class JobSchedulerService extends com.android.server.SystemService
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException {
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
(new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
- this, in, out, err, args, resultReceiver);
+ this, in, out, err, args, callback, resultReceiver);
}
};
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 6381aa747022..547cc51e9a05 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -123,7 +123,6 @@ import android.net.LinkProperties;
import android.net.NetworkIdentity;
import android.net.NetworkInfo;
import android.net.NetworkPolicy;
-import android.net.NetworkPolicyManager;
import android.net.NetworkQuotaInfo;
import android.net.NetworkState;
import android.net.NetworkTemplate;
@@ -144,6 +143,7 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
@@ -2386,9 +2386,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException {
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
(new NetworkPolicyManagerShellCommand(mContext, this)).exec(
- this, in, out, err, args, resultReceiver);
+ this, in, out, err, args, callback, resultReceiver);
}
@Override
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 689917cd670a..f777aaebdd14 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -28,6 +28,7 @@ import android.os.Environment;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.storage.StorageManager;
import android.util.Log;
import android.util.Slog;
@@ -107,9 +108,9 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException {
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
(new OtaDexoptShellCommand(this)).exec(
- this, in, out, err, args, resultReceiver);
+ this, in, out, err, args, callback, resultReceiver);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c76302c1053c..13428b2e2c8a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -185,6 +185,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SELinux;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
@@ -18397,9 +18398,10 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
(new PackageManagerShellCommand(this)).exec(
- this, in, out, err, args, resultReceiver);
+ this, in, out, err, args, callback, resultReceiver);
}
@Override
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 13f558e3dd13..19bf751417ce 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -67,6 +67,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SELinux;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -3366,13 +3367,14 @@ public class ShortcutService extends IShortcutService.Stub {
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException {
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
enforceShell();
final long token = injectClearCallingIdentity();
try {
- final int status = (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
+ final int status = (new MyShellCommand()).exec(this, in, out, err, args, callback,
+ resultReceiver);
resultReceiver.send(status, null);
} finally {
injectRestoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c1cb032ce97f..c6b09d190bff 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -62,6 +62,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SELinux;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.os.UserManager;
@@ -3209,8 +3210,9 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
- (new Shell()).exec(this, in, out, err, args, resultReceiver);
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
}
int onShellCommand(Shell shell, String cmd) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 552803f47652..7b7db0e1440b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -28,23 +28,21 @@ import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Slog;
-import android.view.KeyEvent;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.util.FastPrintWriter;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationDelegate;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
-import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -849,9 +847,9 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) throws RemoteException {
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
(new StatusBarShellCommand(this)).exec(
- this, in, out, err, args, resultReceiver);
+ this, in, out, err, args, callback, resultReceiver);
}
// ================================================================================
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 846169cbf9c3..43cdf5978068 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -25,10 +25,10 @@ import android.os.Binder;
import android.os.PatternMatcher;
import android.os.Process;
import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.UserHandle;
import android.util.Slog;
import android.webkit.IWebViewUpdateService;
-import android.webkit.WebViewFactory;
import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewProviderResponse;
@@ -140,9 +140,10 @@ public class WebViewUpdateService extends SystemService {
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
(new WebViewUpdateServiceShellCommand(this)).exec(
- this, in, out, err, args, resultReceiver);
+ this, in, out, err, args, callback, resultReceiver);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
index 3c99174142cb..25f9100d9252 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
@@ -68,7 +68,7 @@ public class ShortcutManagerTest7 extends BaseShortcutManagerTest {
/* fdin*/ null,
/* fdout*/ fd.getFileDescriptor(),
/* fderr*/ fd.getFileDescriptor(),
- args, rr);
+ args, null, rr);
}
return readAll(out);
} finally {
diff --git a/tests/VoiceInteraction/AndroidManifest.xml b/tests/VoiceInteraction/AndroidManifest.xml
index cbc6c76aa934..5fdf0dd3992c 100644
--- a/tests/VoiceInteraction/AndroidManifest.xml
+++ b/tests/VoiceInteraction/AndroidManifest.xml
@@ -1,6 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.voiceinteraction">
+ <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="25" />
+
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.READ_LOGS" />
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 8d93b7f32100..a0b297701869 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -76,6 +76,7 @@ import android.os.Parcel;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -1180,7 +1181,7 @@ public final class BridgeContext extends Context {
@Override
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ResultReceiver resultReceiver) {
+ String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) {
}
};
}