diff options
| author | 2016-10-27 17:04:57 +0000 | |
|---|---|---|
| committer | 2016-10-27 17:04:57 +0000 | |
| commit | bd2688f4c3e7a94594c439fdcca976932080932d (patch) | |
| tree | 3302e3611521aaa50393cb2fbb0185e05c66ae6b | |
| parent | d19524f4f2cc3c0dc34559254b537db37fc3376b (diff) | |
| parent | 1ab879be90a0d58219fca206e556349709fdfda0 (diff) | |
Merge "Adding "attach-agent" to ActivityManagerShellCommand"
6 files changed, 79 insertions, 1 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 83dab164aef7..c1b37e6d2623 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -965,6 +965,10 @@ public final class ActivityThread { sendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0, 0, true /*async*/); } + public void attachAgent(String agent) { + sendMessage(H.ATTACH_AGENT, agent); + } + public void setSchedulingGroup(int group) { // Note: do this immediately, since going into the foreground // should happen regardless of what pending work we have to do @@ -1388,6 +1392,7 @@ public final class ActivityThread { public static final int MULTI_WINDOW_MODE_CHANGED = 152; public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153; public static final int LOCAL_VOICE_INTERACTION_STARTED = 154; + public static final int ATTACH_AGENT = 155; String codeToString(int code) { if (DEBUG_MESSAGES) { @@ -1444,6 +1449,7 @@ public final class ActivityThread { case MULTI_WINDOW_MODE_CHANGED: return "MULTI_WINDOW_MODE_CHANGED"; case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED"; case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED"; + case ATTACH_AGENT: return "ATTACH_AGENT"; } } return Integer.toString(code); @@ -1696,6 +1702,8 @@ public final class ActivityThread { case LOCAL_VOICE_INTERACTION_STARTED: handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1, (IVoiceInteractor) ((SomeArgs) msg.obj).arg2); + case ATTACH_AGENT: + handleAttachAgent((String) msg.obj); break; } Object obj = msg.obj; @@ -2955,6 +2963,14 @@ public final class ActivityThread { } } + static final void handleAttachAgent(String agent) { + try { + VMDebug.attachAgent(agent); + } catch (IOException e) { + Slog.e(TAG, "Attaching agent failed: " + agent); + } + } + private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>(); /** diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index d6da3f44f4a0..a8313d152422 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -501,6 +501,14 @@ public abstract class ApplicationThreadNative extends Binder return true; } + case ATTACH_AGENT_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + String agent = data.readString(); + attachAgent(agent); + return true; + } + case DUMP_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ParcelFileDescriptor fd = data.readFileDescriptor(); @@ -1303,6 +1311,14 @@ class ApplicationThreadProxy implements IApplicationThread { data.recycle(); } + public void attachAgent(String agent) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeString(agent); + mRemote.transact(ATTACH_AGENT_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } + public void setCoreSettings(Bundle coreSettings) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 559f69fc2aec..5b13164ddb4a 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -122,6 +122,7 @@ public interface IApplicationThread extends IInterface { throws RemoteException; void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) throws RemoteException; + void attachAgent(String path) throws RemoteException; void setSchedulingGroup(int group) throws RemoteException; // the package has been removed, clean up internal references static final int PACKAGE_REMOVED = 0; @@ -224,4 +225,5 @@ public interface IApplicationThread extends IInterface { int SCHEDULE_MULTI_WINDOW_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58; int SCHEDULE_PICTURE_IN_PICTURE_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59; int SCHEDULE_LOCAL_VOICE_INTERACTION_STARTED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+60; + int ATTACH_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+61; } diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java index fc804e592148..0b4c4c12d3df 100644 --- a/core/java/android/os/ShellCommand.java +++ b/core/java/android/os/ShellCommand.java @@ -274,7 +274,7 @@ public abstract class ShellCommand { /** * 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()} + * Use {@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()}. * diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c985a5853b5d..fdde15013663 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -21831,4 +21831,29 @@ public final class ActivityManagerService extends ActivityManagerNative Binder.restoreCallingIdentity(callingId); } } + + /** + * Attach an agent to the specified process (proces name or PID) + */ + public void attachAgent(String process, String path) { + try { + synchronized (this) { + ProcessRecord proc = findProcessLocked(process, UserHandle.USER_SYSTEM, "attachAgent"); + if (proc == null || proc.thread == null) { + throw new IllegalArgumentException("Unknown process: " + process); + } + + boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); + if (!isDebuggable) { + if ((proc.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) { + throw new SecurityException("Process not debuggable: " + proc); + } + } + + proc.thread.attachAgent(path); + } + } catch (RemoteException e) { + throw new IllegalStateException("Process disappeared"); + } + } } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index adf6d3670af3..2d0ccbd305e6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -66,6 +66,8 @@ class ActivityManagerShellCommand extends ShellCommand { return runLenientBackgroundCheck(pw); case "get-uid-state": return getUidState(pw); + case "attach-agent": + return runAttachAgent(pw); default: return handleDefaultCommands(cmd); } @@ -183,6 +185,21 @@ class ActivityManagerShellCommand extends ShellCommand { return 0; } + int runAttachAgent(PrintWriter pw) { + // TODO: revisit the permissions required for attaching agents + mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, + "attach-agent"); + String process = getNextArgRequired(); + String agent = getNextArgRequired(); + String opt; + if ((opt = getNextArg()) != null) { + pw.println("Error: Unknown option: " + opt); + return -1; + } + mInternal.attachAgent(process, agent); + return 0; + } + @Override public void onHelp() { PrintWriter pw = getOutPrintWriter(); @@ -241,6 +258,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(" attach-agent <PROCESS> <FILE>"); + pw.println(" Attach an agent to the specified <PROCESS>, which may be either a process name or a PID."); } } } |