OSDN Git Service

Adding "attach-agent" to ActivityManagerShellCommand
authorLeonard Mosescu <mosescu@google.com>
Fri, 7 Oct 2016 00:32:05 +0000 (17:32 -0700)
committerLeonard Mosescu <mosescu@google.com>
Tue, 25 Oct 2016 22:42:39 +0000 (22:42 +0000)
This new command is used to attach runtime agents to a running application:

attach-agent <PROCESS> <FILE>
   Attach an agent to the specified <PROCESS>,
   which may be either a process name or a PID.

Test: m test-art-host, manual testing:
    . invalid syntax, missing arguments
    . invalid syntax, extra arguments
    . invalid numeric PID
    . invalid process name
    . valid process, not debuggable
    . valid process, missing agent
    . valid process, valid agent

Bug: 31682382

Change-Id: Ife88dbf23991dde7945d9208e54cd014bb7ecdc6

core/java/android/app/ActivityThread.java
core/java/android/app/IApplicationThread.aidl
core/java/android/os/ShellCommand.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ActivityManagerShellCommand.java

index fbbfec3..e9a200f 100644 (file)
@@ -978,6 +978,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
@@ -1429,6 +1433,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) {
@@ -1485,6 +1490,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);
@@ -1739,6 +1745,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;
@@ -3008,6 +3016,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>();
 
     /**
index 2dd3b1a..e2f6fb5 100644 (file)
@@ -155,6 +155,7 @@ oneway interface IApplicationThread {
     void scheduleLocalVoiceInteractionStarted(IBinder token,
             IVoiceInteractor voiceInteractor) = 61;
     void handleTrustStorageUpdate() = 62;
+    void attachAgent(String path) = 63;
     /**
      * Don't change the existing transaction Ids as they could be used in the native code.
      * When adding a new method, assign the next available transaction id.
index dbb9650..e4a12e8 100644 (file)
@@ -302,7 +302,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()}.
      *
index bb00bc2..1edc8d2 100644 (file)
@@ -22483,4 +22483,29 @@ public final class ActivityManagerService extends ActivityManagerNative
         // before the profile user is unlocked.
         return rInfo != null && rInfo.activityInfo != null;
     }
+
+    /**
+     * 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");
+        }
+    }
 }
index c7a04c1..7a692b6 100644 (file)
@@ -220,6 +220,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
                     return runTask(pw);
                 case "write":
                     return runWrite(pw);
+                case "attach-agent":
+                    return runAttachAgent(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -2462,6 +2464,21 @@ final 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();
@@ -2619,6 +2636,8 @@ final 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.");
             pw.println("  get-config");
             pw.println("      Rtrieve the configuration and any recent configurations of the device.");
             pw.println("  suppress-resize-config-changes <true|false>");