diff options
5 files changed, 80 insertions, 45 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 00e55fa260ef..559989368a9f 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -927,6 +927,7 @@ public final class ActivityThread extends ClientTransactionHandler int samplingInterval; boolean autoStopProfiler; boolean streamingOutput; + int mClockType; boolean profiling; boolean handlingProfiling; public void setProfiler(ProfilerInfo profilerInfo) { @@ -953,6 +954,7 @@ public final class ActivityThread extends ClientTransactionHandler samplingInterval = profilerInfo.samplingInterval; autoStopProfiler = profilerInfo.autoStopProfiler; streamingOutput = profilerInfo.streamingOutput; + mClockType = profilerInfo.clockType; } public void startProfiling() { if (profileFd == null || profiling) { @@ -961,8 +963,8 @@ public final class ActivityThread extends ClientTransactionHandler try { int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8); VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), - bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval, - streamingOutput); + bufferSize * 1024 * 1024, mClockType, samplingInterval != 0, + samplingInterval, streamingOutput); profiling = true; } catch (RuntimeException e) { Slog.w(TAG, "Profiling failed on path " + profileFile, e); @@ -6511,6 +6513,7 @@ public final class ActivityThread extends ClientTransactionHandler mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput; + mProfiler.mClockType = data.initProfilerInfo.clockType; if (data.initProfilerInfo.attachAgentDuringBind) { agent = data.initProfilerInfo.agent; } diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java index 854406cae782..f7a3d78af207 100644 --- a/core/java/android/app/ProfilerInfo.java +++ b/core/java/android/app/ProfilerInfo.java @@ -33,6 +33,17 @@ import java.util.Objects; */ public class ProfilerInfo implements Parcelable { + // CLOCK_TYPE_DEFAULT chooses the default used by ART. ART uses CLOCK_TYPE_DUAL by default (see + // kDefaultTraceClockSource in art/runtime/runtime_globals.h). + public static final int CLOCK_TYPE_DEFAULT = 0x000; + // The values of these constants are chosen such that they correspond to the flags passed to + // VMDebug.startMethodTracing to choose the corresponding clock type (see + // core/java/android/app/ActivityThread.java). + // The flag values are defined in ART (see TraceFlag in art/runtime/trace.h). + public static final int CLOCK_TYPE_WALL = 0x010; + public static final int CLOCK_TYPE_THREAD_CPU = 0x100; + public static final int CLOCK_TYPE_DUAL = 0x110; + private static final String TAG = "ProfilerInfo"; /* Name of profile output file. */ @@ -66,13 +77,20 @@ public class ProfilerInfo implements Parcelable { */ public final boolean attachAgentDuringBind; + /** + * Indicates the clock source to be used for profiling. The source could be wallclock, thread + * cpu or both + */ + public final int clockType; + public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop, - boolean streaming, String agent, boolean attachAgentDuringBind) { + boolean streaming, String agent, boolean attachAgentDuringBind, int clockType) { profileFile = filename; profileFd = fd; samplingInterval = interval; autoStopProfiler = autoStop; streamingOutput = streaming; + this.clockType = clockType; this.agent = agent; this.attachAgentDuringBind = attachAgentDuringBind; } @@ -85,6 +103,25 @@ public class ProfilerInfo implements Parcelable { streamingOutput = in.streamingOutput; agent = in.agent; attachAgentDuringBind = in.attachAgentDuringBind; + clockType = in.clockType; + } + + /** + * Get the value for the clock type corresponding to the option string passed to the activity + * manager. am profile start / am start-activity start-profiler commands accept clock-type + * option to choose the source of timestamps when profiling. This function maps the option + * string to the value of flags that is used when calling VMDebug.startMethodTracing + */ + public static int getClockTypeFromString(String type) { + if ("thread-cpu".equals(type)) { + return CLOCK_TYPE_THREAD_CPU; + } else if ("wall".equals(type)) { + return CLOCK_TYPE_WALL; + } else if ("dual".equals(type)) { + return CLOCK_TYPE_DUAL; + } else { + return CLOCK_TYPE_DEFAULT; + } } /** @@ -93,7 +130,8 @@ public class ProfilerInfo implements Parcelable { */ public ProfilerInfo setAgent(String agent, boolean attachAgentDuringBind) { return new ProfilerInfo(this.profileFile, this.profileFd, this.samplingInterval, - this.autoStopProfiler, this.streamingOutput, agent, attachAgentDuringBind); + this.autoStopProfiler, this.streamingOutput, agent, attachAgentDuringBind, + this.clockType); } /** @@ -133,6 +171,7 @@ public class ProfilerInfo implements Parcelable { out.writeInt(streamingOutput ? 1 : 0); out.writeString(agent); out.writeBoolean(attachAgentDuringBind); + out.writeInt(clockType); } /** @hide */ @@ -146,6 +185,7 @@ public class ProfilerInfo implements Parcelable { proto.write(ProfilerInfoProto.AUTO_STOP_PROFILER, autoStopProfiler); proto.write(ProfilerInfoProto.STREAMING_OUTPUT, streamingOutput); proto.write(ProfilerInfoProto.AGENT, agent); + proto.write(ProfilerInfoProto.CLOCK_TYPE, clockType); proto.end(token); } @@ -170,6 +210,7 @@ public class ProfilerInfo implements Parcelable { streamingOutput = in.readInt() != 0; agent = in.readString(); attachAgentDuringBind = in.readBoolean(); + clockType = in.readInt(); } @Override @@ -186,7 +227,8 @@ public class ProfilerInfo implements Parcelable { && autoStopProfiler == other.autoStopProfiler && samplingInterval == other.samplingInterval && streamingOutput == other.streamingOutput - && Objects.equals(agent, other.agent); + && Objects.equals(agent, other.agent) + && clockType == other.clockType; } @Override @@ -197,6 +239,7 @@ public class ProfilerInfo implements Parcelable { result = 31 * result + (autoStopProfiler ? 1 : 0); result = 31 * result + (streamingOutput ? 1 : 0); result = 31 * result + Objects.hashCode(agent); + result = 31 * result + clockType; return result; } } diff --git a/core/proto/android/app/profilerinfo.proto b/core/proto/android/app/profilerinfo.proto index d318533b77e5..86261ecdf54e 100644 --- a/core/proto/android/app/profilerinfo.proto +++ b/core/proto/android/app/profilerinfo.proto @@ -35,4 +35,5 @@ message ProfilerInfoProto { optional bool streaming_output = 5; // Denotes an agent (and its parameters) to attach for profiling. optional string agent = 6; + optional int32 clock_type = 7; } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 6b0764791b48..5d8c3b6c3dd0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -90,7 +90,6 @@ import android.os.ServiceManager; import android.os.ShellCommand; import android.os.StrictMode; import android.os.SystemClock; -import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; @@ -175,6 +174,7 @@ final class ActivityManagerShellCommand extends ShellCommand { private boolean mStreaming; // Streaming the profiling output to a file. private String mAgent; // Agent to attach on startup. private boolean mAttachAgentDuringBind; // Whether agent should be attached late. + private int mClockType; // Whether we need thread cpu / wall clock / both. private int mDisplayId; private int mTaskDisplayAreaFeatureId; private int mWindowingMode; @@ -400,6 +400,9 @@ final class ActivityManagerShellCommand extends ShellCommand { mAutoStop = false; } else if (opt.equals("--sampling")) { mSamplingInterval = Integer.parseInt(getNextArgRequired()); + } else if (opt.equals("--clock-type")) { + String clock_type = getNextArgRequired(); + mClockType = ProfilerInfo.getClockTypeFromString(clock_type); } else if (opt.equals("--streaming")) { mStreaming = true; } else if (opt.equals("--attach-agent")) { @@ -548,7 +551,7 @@ final class ActivityManagerShellCommand extends ShellCommand { } } profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop, - mStreaming, mAgent, mAttachAgentDuringBind); + mStreaming, mAgent, mAttachAgentDuringBind, mClockType); } pw.println("Starting: " + intent); @@ -878,24 +881,15 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } - static void removeWallOption() { - String props = SystemProperties.get("dalvik.vm.extra-opts"); - if (props != null && props.contains("-Xprofile:wallclock")) { - props = props.replace("-Xprofile:wallclock", ""); - props = props.trim(); - SystemProperties.set("dalvik.vm.extra-opts", props); - } - } - private int runProfile(PrintWriter pw) throws RemoteException { final PrintWriter err = getErrPrintWriter(); String profileFile = null; boolean start = false; - boolean wall = false; int userId = UserHandle.USER_CURRENT; int profileType = 0; mSamplingInterval = 0; mStreaming = false; + mClockType = ProfilerInfo.CLOCK_TYPE_DEFAULT; String process = null; @@ -907,8 +901,9 @@ final class ActivityManagerShellCommand extends ShellCommand { while ((opt=getNextOption()) != null) { if (opt.equals("--user")) { userId = UserHandle.parseUserArg(getNextArgRequired()); - } else if (opt.equals("--wall")) { - wall = true; + } else if (opt.equals("--clock-type")) { + String clock_type = getNextArgRequired(); + mClockType = ProfilerInfo.getClockTypeFromString(clock_type); } else if (opt.equals("--streaming")) { mStreaming = true; } else if (opt.equals("--sampling")) { @@ -956,29 +951,12 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming, - null, false); + null, false, mClockType); } - try { - if (wall) { - // XXX doesn't work -- this needs to be set before booting. - String props = SystemProperties.get("dalvik.vm.extra-opts"); - if (props == null || !props.contains("-Xprofile:wallclock")) { - props = props + " -Xprofile:wallclock"; - //SystemProperties.set("dalvik.vm.extra-opts", props); - } - } else if (start) { - //removeWallOption(); - } - if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) { - wall = false; - err.println("PROFILE FAILED on process " + process); - return -1; - } - } finally { - if (!wall) { - //removeWallOption(); - } + if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) { + err.println("PROFILE FAILED on process " + process); + return -1; } return 0; } @@ -3456,8 +3434,9 @@ final class ActivityManagerShellCommand extends ShellCommand { 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] [--streaming] [-R COUNT] [-S]"); - pw.println(" [--track-allocation] [--user <USER_ID> | current] <INTENT>"); + pw.println(" [--sampling INTERVAL] [--clock-type <TYPE>] [--streaming]"); + pw.println(" [-R COUNT] [-S] [--track-allocation]"); + pw.println(" [--user <USER_ID> | current] <INTENT>"); pw.println(" Start an Activity. Options are:"); pw.println(" -D: enable debugging"); pw.println(" -N: enable native debugging"); @@ -3465,6 +3444,9 @@ final class ActivityManagerShellCommand extends ShellCommand { 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(" --clock-type <TYPE>: type can be wall / thread-cpu / dual. Specify"); + pw.println(" the clock that is used to report the timestamps when profiling"); + pw.println(" The default value is dual. (use with --start-profiler)"); pw.println(" --streaming: stream the profiling output to the specified file"); pw.println(" (use with --start-profiler)"); pw.println(" -P <FILE>: like above, but profiling stops when app goes idle"); @@ -3542,12 +3524,16 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" stop: stop tracing IPC transactions and dump the results to file."); pw.println(" --dump-file <FILE>: Specify the file the trace should be dumped to."); pw.println(" profile start [--user <USER_ID> current]"); + pw.println(" [--clock-type <TYPE>]"); pw.println(" [--sampling INTERVAL | --streaming] <PROCESS> <FILE>"); pw.println(" Start profiler on a process. The given <PROCESS> argument"); pw.println(" may be either a process name or pid. Options are:"); pw.println(" --user <USER_ID> | current: When supplying a process name,"); pw.println(" specify user of process to profile; uses current user if not"); pw.println(" specified."); + pw.println(" --clock-type <TYPE>: use the specified clock to report timestamps."); + pw.println(" The type can be one of wall | thread-cpu | dual. The default"); + pw.println(" value is dual."); pw.println(" --sampling INTERVAL: use sample profiling with INTERVAL microseconds"); pw.println(" between samples."); pw.println(" --streaming: stream the profiling output to the specified file."); diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java index e97654cde174..15efb7dc865c 100644 --- a/services/core/java/com/android/server/am/AppProfiler.java +++ b/services/core/java/com/android/server/am/AppProfiler.java @@ -2043,7 +2043,7 @@ public class AppProfiler { } } else if (instr != null && instr.mProfileFile != null) { profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false, - null, false); + null, false, 0); } if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) { // We need to do a debuggable check here. See setAgentApp for why the check is @@ -2053,7 +2053,7 @@ public class AppProfiler { // Do not overwrite already requested agent. if (profilerInfo == null) { profilerInfo = new ProfilerInfo(null, null, 0, false, false, - mAppAgentMap.get(processName), true); + mAppAgentMap.get(processName), true, 0); } else if (profilerInfo.agent == null) { profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true); } @@ -2185,7 +2185,9 @@ public class AppProfiler { + " mAutoStopProfiler=" + mProfileData.getProfilerInfo().autoStopProfiler + " mStreamingOutput=" - + mProfileData.getProfilerInfo().streamingOutput); + + mProfileData.getProfilerInfo().streamingOutput + + " mClockType=" + + mProfileData.getProfilerInfo().clockType); pw.println(" mProfileType=" + mProfileType); } } |