Merge "ActivityManager: Add support for agents on startup"
This commit is contained in:
@@ -137,6 +137,7 @@ interface IActivityManager {
|
|||||||
void publishService(in IBinder token, in Intent intent, in IBinder service);
|
void publishService(in IBinder token, in Intent intent, in IBinder service);
|
||||||
void activityResumed(in IBinder token);
|
void activityResumed(in IBinder token);
|
||||||
void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent);
|
void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent);
|
||||||
|
void setAgentApp(in String packageName, @nullable String agent);
|
||||||
void setAlwaysFinish(boolean enabled);
|
void setAlwaysFinish(boolean enabled);
|
||||||
boolean startInstrumentation(in ComponentName className, in String profileFile,
|
boolean startInstrumentation(in ComponentName className, in String profileFile,
|
||||||
int flags, in Bundle arguments, in IInstrumentationWatcher watcher,
|
int flags, in Bundle arguments, in IInstrumentationWatcher watcher,
|
||||||
|
|||||||
@@ -84,6 +84,15 @@ public class ProfilerInfo implements Parcelable {
|
|||||||
attachAgentDuringBind = in.attachAgentDuringBind;
|
attachAgentDuringBind = in.attachAgentDuringBind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ProfilerInfo instance, with fields populated from this object,
|
||||||
|
* and {@link agent} and {@link attachAgentDuringBind} as given.
|
||||||
|
*/
|
||||||
|
public ProfilerInfo setAgent(String agent, boolean attachAgentDuringBind) {
|
||||||
|
return new ProfilerInfo(this.profileFile, this.profileFd, this.samplingInterval,
|
||||||
|
this.autoStopProfiler, this.streamingOutput, agent, attachAgentDuringBind);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close profileFd, if it is open. The field will be null after a call to this function.
|
* Close profileFd, if it is open. The field will be null after a call to this function.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1493,6 +1493,14 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||||||
String mProfileApp = null;
|
String mProfileApp = null;
|
||||||
ProcessRecord mProfileProc = null;
|
ProcessRecord mProfileProc = null;
|
||||||
ProfilerInfo mProfilerInfo = null;
|
ProfilerInfo mProfilerInfo = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a map of process name -> agent string. When a process is started and mAgentAppMap
|
||||||
|
* is not null, this map is checked and the mapped agent installed during bind-time. Note:
|
||||||
|
* A non-null agent in mProfileInfo overrides this.
|
||||||
|
*/
|
||||||
|
private @Nullable Map<String, String> mAppAgentMap = null;
|
||||||
|
|
||||||
int mProfileType = 0;
|
int mProfileType = 0;
|
||||||
final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
|
final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
|
||||||
String mMemWatchDumpProcName;
|
String mMemWatchDumpProcName;
|
||||||
@@ -7017,25 +7025,6 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfilerInfo profilerInfo = null;
|
|
||||||
String preBindAgent = null;
|
|
||||||
if (mProfileApp != null && mProfileApp.equals(processName)) {
|
|
||||||
mProfileProc = app;
|
|
||||||
if (mProfilerInfo != null) {
|
|
||||||
// Send a profiler info object to the app if either a file is given, or
|
|
||||||
// an agent should be loaded at bind-time.
|
|
||||||
boolean needsInfo = mProfilerInfo.profileFile != null
|
|
||||||
|| mProfilerInfo.attachAgentDuringBind;
|
|
||||||
profilerInfo = needsInfo ? new ProfilerInfo(mProfilerInfo) : null;
|
|
||||||
if (!mProfilerInfo.attachAgentDuringBind) {
|
|
||||||
preBindAgent = mProfilerInfo.agent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (app.instr != null && app.instr.mProfileFile != null) {
|
|
||||||
profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false,
|
|
||||||
null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean enableTrackAllocation = false;
|
boolean enableTrackAllocation = false;
|
||||||
if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
|
if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
|
||||||
enableTrackAllocation = true;
|
enableTrackAllocation = true;
|
||||||
@@ -7060,6 +7049,39 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||||||
ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
|
ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
|
||||||
app.compat = compatibilityInfoForPackageLocked(appInfo);
|
app.compat = compatibilityInfoForPackageLocked(appInfo);
|
||||||
|
|
||||||
|
ProfilerInfo profilerInfo = null;
|
||||||
|
String preBindAgent = null;
|
||||||
|
if (mProfileApp != null && mProfileApp.equals(processName)) {
|
||||||
|
mProfileProc = app;
|
||||||
|
if (mProfilerInfo != null) {
|
||||||
|
// Send a profiler info object to the app if either a file is given, or
|
||||||
|
// an agent should be loaded at bind-time.
|
||||||
|
boolean needsInfo = mProfilerInfo.profileFile != null
|
||||||
|
|| mProfilerInfo.attachAgentDuringBind;
|
||||||
|
profilerInfo = needsInfo ? new ProfilerInfo(mProfilerInfo) : null;
|
||||||
|
if (mProfilerInfo.agent != null) {
|
||||||
|
preBindAgent = mProfilerInfo.agent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (app.instr != null && app.instr.mProfileFile != null) {
|
||||||
|
profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false,
|
||||||
|
null, false);
|
||||||
|
}
|
||||||
|
if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
|
||||||
|
// We need to do a debuggable check here. See setAgentApp for why the check is
|
||||||
|
// postponed to here.
|
||||||
|
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
|
||||||
|
String agent = mAppAgentMap.get(processName);
|
||||||
|
// Do not overwrite already requested agent.
|
||||||
|
if (profilerInfo == null) {
|
||||||
|
profilerInfo = new ProfilerInfo(null, null, 0, false, false,
|
||||||
|
mAppAgentMap.get(processName), true);
|
||||||
|
} else if (profilerInfo.agent == null) {
|
||||||
|
profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (profilerInfo != null && profilerInfo.profileFd != null) {
|
if (profilerInfo != null && profilerInfo.profileFd != null) {
|
||||||
profilerInfo.profileFd = profilerInfo.profileFd.dup();
|
profilerInfo.profileFd = profilerInfo.profileFd.dup();
|
||||||
}
|
}
|
||||||
@@ -12793,6 +12815,52 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or remove an agent to be run whenever an app with the given process name starts.
|
||||||
|
*
|
||||||
|
* This method will not check whether the given process name matches a debuggable app. That
|
||||||
|
* would require scanning all current packages, and a rescan when new packages are installed
|
||||||
|
* or updated.
|
||||||
|
*
|
||||||
|
* Instead, do the check when an application is started and matched to a stored agent.
|
||||||
|
*
|
||||||
|
* @param packageName the process name of the app.
|
||||||
|
* @param agent the agent string to be used, or null to remove any previously set agent.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setAgentApp(@NonNull String packageName, @Nullable String agent) {
|
||||||
|
synchronized (this) {
|
||||||
|
// note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
|
||||||
|
// its own permission.
|
||||||
|
if (checkCallingPermission(
|
||||||
|
android.Manifest.permission.SET_ACTIVITY_WATCHER) !=
|
||||||
|
PackageManager.PERMISSION_GRANTED) {
|
||||||
|
throw new SecurityException(
|
||||||
|
"Requires permission " + android.Manifest.permission.SET_ACTIVITY_WATCHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (agent == null) {
|
||||||
|
if (mAppAgentMap != null) {
|
||||||
|
mAppAgentMap.remove(packageName);
|
||||||
|
if (mAppAgentMap.isEmpty()) {
|
||||||
|
mAppAgentMap = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mAppAgentMap == null) {
|
||||||
|
mAppAgentMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
if (mAppAgentMap.size() >= 100) {
|
||||||
|
// Limit the size of the map, to avoid OOMEs.
|
||||||
|
Slog.e(TAG, "App agent map has too many entries, cannot add " + packageName
|
||||||
|
+ "/" + agent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mAppAgentMap.put(packageName, agent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void setTrackAllocationApp(ApplicationInfo app, String processName) {
|
void setTrackAllocationApp(ApplicationInfo app, String processName) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
|
boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
|||||||
return runDumpHeap(pw);
|
return runDumpHeap(pw);
|
||||||
case "set-debug-app":
|
case "set-debug-app":
|
||||||
return runSetDebugApp(pw);
|
return runSetDebugApp(pw);
|
||||||
|
case "set-agent-app":
|
||||||
|
return runSetAgentApp(pw);
|
||||||
case "clear-debug-app":
|
case "clear-debug-app":
|
||||||
return runClearDebugApp(pw);
|
return runClearDebugApp(pw);
|
||||||
case "set-watch-heap":
|
case "set-watch-heap":
|
||||||
@@ -862,6 +864,13 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int runSetAgentApp(PrintWriter pw) throws RemoteException {
|
||||||
|
String pkg = getNextArgRequired();
|
||||||
|
String agent = getNextArg();
|
||||||
|
mInterface.setAgentApp(pkg, agent);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int runClearDebugApp(PrintWriter pw) throws RemoteException {
|
int runClearDebugApp(PrintWriter pw) throws RemoteException {
|
||||||
mInterface.setDebugApp(null, false, true);
|
mInterface.setDebugApp(null, false, true);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user