下面列出了怎么用android.os.Trace的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Intended to mimic the behavior of onKeyEvent if this were the only service running. It will be
* called from onKeyEvent, both from this service and from others in this apk (TalkBack). This
* method must not block, since it will block onKeyEvent as well.
*
* @param keyEvent A key event
* @return {@code true} if the event is handled, {@code false} otherwise.
*/
@Override
public boolean onKeyEventShared(KeyEvent keyEvent) {
Trace.beginSection("SwitchAccessService#onKeyEventShared");
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
PerformanceMonitor.getOrCreateInstance()
.startNewTimerEvent(KeyPressEvent.UNKNOWN_KEY_ASSIGNMENT);
}
if (keyboardEventManager.onKeyEvent(keyEvent, analytics, this)) {
wakeLock.acquire();
wakeLock.release();
Trace.endSection();
return true;
}
Trace.endSection();
return false;
}
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
// //设置虚拟机的内存利用率参数值为 0.75
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args = new Arguments(argv); // 解析参数
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
// 寻找 startClass 的 main() 方法。这里的 startClass 是 com.android.server.SystemServer
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
/**
* 方法执行前切入
*/
private void enterMethod(ProceedingJoinPoint joinPoint, DebugLog debugLog) {
if (!AppConfig.isDebug()) {
return;
}
CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature();
// 方法所在类
String className = codeSignature.getDeclaringType().getName();
// 方法名
String methodName = codeSignature.getName();
// 方法参数名集合
String[] parameterNames = codeSignature.getParameterNames();
// 方法参数集合
Object[] parameterValues = joinPoint.getArgs();
//记录并打印方法的信息
StringBuilder builder = getMethodLogInfo(className, methodName, parameterNames, parameterValues);
log(debugLog.value(), builder.toString());
final String section = builder.toString().substring(2);
Trace.beginSection(section);
}
public void stopUser(final int userHandle) {
Slog.i(TAG, "Calling onStopUser u" + userHandle);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStopUser "
+ service.getClass().getName());
long time = SystemClock.elapsedRealtime();
try {
service.onStopUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting stop of user " + userHandle
+ " to service " + service.getClass().getName(), ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStopUser");
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
void finishedInputEvent(int seq, boolean handled, boolean timeout) {
final PendingEvent p;
synchronized (mH) {
int index = mPendingEvents.indexOfKey(seq);
if (index < 0) {
return; // spurious, event already finished or timed out
}
p = mPendingEvents.valueAt(index);
mPendingEvents.removeAt(index);
Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
if (timeout) {
Log.w(TAG, "Timeout waiting for IME to handle input event after "
+ INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
} else {
mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
}
}
invokeFinishedInputEventCallback(p, handled);
}
static void install() {
if (!installed) {
installed = true;
if (isSupported()) {
try {
Method traceBegin = Trace.class.getDeclaredMethod("traceBegin", long.class, String.class);
Method traceEnd = Trace.class.getDeclaredMethod("traceEnd", long.class);
Hook.hook(traceBegin, ViewPerformanceSampler.class.getDeclaredMethod("traceBegin", long.class, String.class));
Hook.hook(traceEnd, ViewPerformanceSampler.class.getDeclaredMethod("traceEnd", long.class));
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
void traceStateLocked(String where, WindowManagerService service) {
if (!isEnabled()) {
return;
}
ProtoOutputStream os = new ProtoOutputStream();
long tokenOuter = os.start(ENTRY);
os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
os.write(WHERE, where);
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked");
try {
long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
service.writeToProtoLocked(os, true /* trim */);
os.end(tokenInner);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
os.end(tokenOuter);
appendTraceEntry(os);
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
mLastAlarmDeliveryTime = nowELAPSED;
for (int i=0; i<triggerList.size(); i++) {
Alarm alarm = triggerList.get(i);
final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
if (alarm.wakeup) {
Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch wakeup alarm to " + alarm.packageName);
} else {
Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch non-wakeup alarm to " + alarm.packageName);
}
try {
if (localLOGV) {
Slog.v(TAG, "sending alarm " + alarm);
}
if (RECORD_ALARMS_IN_HISTORY) {
ActivityManager.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid,
alarm.statsTag);
}
mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
} catch (RuntimeException e) {
Slog.w(TAG, "Failure sending alarm.", e);
}
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
@Override
public boolean isVisibleToUser() {
Trace.beginSection("SwitchAccessNodeCompat#isVisibleToUser");
if (!isOnScreenAndVisibleToUser()) {
Trace.endSection();
return false;
}
// Views are considered visible only if a minimum number of pixels is showing.
Rect visibleBounds = new Rect();
getVisibleBoundsInScreen(visibleBounds);
int visibleHeight = visibleBounds.height();
int visibleWidth = visibleBounds.width();
boolean isVisible =
(visibleHeight >= MIN_VISIBLE_PIXELS) && (visibleWidth >= MIN_VISIBLE_PIXELS);
Trace.endSection();
return isVisible;
}
@GuardedBy("mLock")
private void doCancelVibrateLocked() {
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doCancelVibrateLocked");
try {
mH.removeCallbacks(mVibrationEndRunnable);
if (mThread != null) {
mThread.cancel();
mThread = null;
}
doVibratorOff();
reportFinishVibrationLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
private void doVibratorOff() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOff");
try {
synchronized (mInputDeviceVibrators) {
if (DEBUG) {
Slog.d(TAG, "Turning vibrator off.");
}
noteVibratorOffLocked();
final int vibratorCount = mInputDeviceVibrators.size();
if (vibratorCount != 0) {
for (int i = 0; i < vibratorCount; i++) {
mInputDeviceVibrators.get(i).cancel();
}
} else {
vibratorOff();
}
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
private boolean napNoUpdateLocked(long eventTime, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
}
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
try {
Slog.i(TAG, "Nap time (uid " + uid +")...");
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime
+ ", uid=" + uid);
}
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallyGoToSleep");
try {
Slog.i(TAG, "Sleeping (uid " + uid +")...");
setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
private void logScreenOn() {
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);
final int latencyMs = (int) (SystemClock.uptimeMillis() - mLastWakeTime);
LogMaker log = new LogMaker(MetricsEvent.SCREEN);
log.setType(MetricsEvent.TYPE_OPEN);
log.setSubtype(0); // not user initiated
log.setLatency(latencyMs); // How long it took.
MetricsLogger.action(log);
EventLogTags.writePowerScreenState(1, 0, 0, 0, latencyMs);
if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {
Slog.w(TAG, "Screen on took " + latencyMs+ " ms");
}
}
@Override
public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
}
nativeReleaseSuspendBlocker(mName);
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
} else if (mReferenceCount < 0) {
Slog.wtf(TAG, "Suspend blocker \"" + mName
+ "\" was released without being acquired!", new Throwable());
mReferenceCount = 0;
}
}
}
private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
updateViewTreeDisplayList(view);
if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
try {
final int saveCount = canvas.save();
canvas.translate(mInsetLeft, mInsetTop);
callbacks.onPreDraw(canvas);
canvas.insertReorderBarrier();
canvas.drawRenderNode(view.updateDisplayListIfDirty());
canvas.insertInorderBarrier();
callbacks.onPostDraw(canvas);
canvas.restoreToCount(saveCount);
mRootNodeNeedsUpdate = false;
} finally {
mRootNode.end(canvas);
}
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
/**
* Return primary and secondary colors from the Material color palette that are similar to
* {@param color}.
*/
public MaterialPalette calculatePrimaryAndSecondaryColor(int color) {
Trace.beginSection("calculatePrimaryAndSecondaryColor");
final float colorHue = hue(color);
float minimumDistance = Float.MAX_VALUE;
int indexBestMatch = 0;
for (int i = 0; i < sPrimaryColors.length(); i++) {
final int primaryColor = sPrimaryColors.getColor(i, 0);
final float comparedHue = hue(primaryColor);
// No need to be perceptually accurate when calculating color distances since
// we are only mapping to 15 colors. Being slightly inaccurate isn't going to change
// the mapping very often.
final float distance = Math.abs(comparedHue - colorHue);
if (distance < minimumDistance) {
minimumDistance = distance;
indexBestMatch = i;
}
}
Trace.endSection();
return new MaterialPalette(sPrimaryColors.getColor(indexBestMatch, 0), sSecondaryColors.getColor(indexBestMatch, 0));
}
private void reduceVisibleRectangleForWindowsAbove(Rect visibleRect) {
Trace.beginSection("SwitchAccessNodeCompat#reduceVisibleRectangleForWindowsAbove");
Rect windowBoundsInScreen = new Rect();
int visibleRectWidth = visibleRect.right - visibleRect.left;
int visibleRectHeight = visibleRect.bottom - visibleRect.top;
for (int i = 0; i < windowsAbove.size(); ++i) {
windowsAbove.get(i).getBoundsInScreen(windowBoundsInScreen);
windowBoundsInScreen.sort();
Rect intersectingRectangle = new Rect(visibleRect);
if (intersectingRectangle.intersect(windowBoundsInScreen)) {
// If the rect above occupies less than a fraction of both sides of this rect, don't
// adjust this rect's bounds. This prevents things like FABs changing the bounds
// of scroll views under them.
if (((intersectingRectangle.right - intersectingRectangle.left)
< (visibleRectWidth * MIN_INTERSECTION_TO_CROP))
&& ((intersectingRectangle.bottom - intersectingRectangle.top)
< (visibleRectHeight * MIN_INTERSECTION_TO_CROP))) {
Trace.endSection();
return;
}
adjustRectToAvoidIntersection(visibleRect, windowBoundsInScreen);
}
}
Trace.endSection();
}
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
/**
* Don't call this method directly; call enqueueParallelBroadcastLocked or
* enqueueOrderedBroadcastLocked.
*/
private void enqueueBroadcastHelper(BroadcastRecord r) {
r.enqueueClockTime = System.currentTimeMillis();
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
System.identityHashCode(r));
}
}
/**
* Get the largest rectangle in the bounds of the View that is not covered by another window.
*
* @param visibleBoundsInScreen The rect to return the visible bounds in
*/
public void getVisibleBoundsInScreen(Rect visibleBoundsInScreen) {
Trace.beginSection("SwitchAccessNodeCompat#getVisibleBoundsInScreen");
updateVisibility(0 /* currentDepth */);
visibleBoundsInScreen.set(this.visibleBoundsInScreen);
Trace.endSection();
}
private void handleLightSensorEvent(long time, float lux) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ALS", (int) lux);
mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
if (mAmbientLightRingBuffer.size() == 0) {
// switch to using the steady-state sample rate after grabbing the initial light sample
adjustLightSensorRate(mNormalLightSensorRate);
}
applyLightSensorMeasurement(time, lux);
updateAmbientLux(time);
}
/**
* Dismisses the color fade surface.
*/
public void dismissColorFade() {
Trace.traceCounter(Trace.TRACE_TAG_POWER, COUNTER_COLOR_FADE, 100);
if (mColorFade != null) mColorFade.dismiss();
mColorFadePrepared = false;
mColorFadeReady = true;
}
@Override
public void run() {
mColorFadeDrawPending = false;
if (mColorFadePrepared) {
mColorFade.draw(mColorFadeLevel);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
COUNTER_COLOR_FADE, Math.round(mColorFadeLevel * 100));
}
mColorFadeReady = true;
invokeCleanListenerIfNeeded();
}
/**
* End tracing previously {@link #traceBegin(String) started} section.
* Also {@link #logDuration logs} the duration.
*/
public void traceEnd() {
assertSameThread();
Trace.traceEnd(mTraceTag);
if (!DEBUG_BOOT_TIME) {
return;
}
if (mStartTimes.peek() == null) {
Slog.w(mTag, "traceEnd called more times than traceBegin");
return;
}
Pair<String, Long> event = mStartTimes.pop();
logDuration(event.first, (SystemClock.elapsedRealtime() - event.second));
}
private void unblockScreenOn() {
if (mPendingScreenOnUnblocker != null) {
mPendingScreenOnUnblocker = null;
long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
}
}
private void blockScreenOff() {
if (mPendingScreenOffUnblocker == null) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
mPendingScreenOffUnblocker = new ScreenOffUnblocker();
mScreenOffBlockStartRealTime = SystemClock.elapsedRealtime();
Slog.i(TAG, "Blocking screen off");
}
}
private void unblockScreenOff() {
if (mPendingScreenOffUnblocker != null) {
mPendingScreenOffUnblocker = null;
long delay = SystemClock.elapsedRealtime() - mScreenOffBlockStartRealTime;
Slog.i(TAG, "Unblocked screen off after " + delay + " ms");
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
}
}
private void animateScreenBrightness(int target, int rate) {
if (DEBUG) {
Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
}
if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);
try {
mBatteryStats.noteScreenBrightness(target);
} catch (RemoteException ex) {
// same process
}
}
}
/**
* Starts the specified boot phase for all system services that have been started up to
* this point.
*
* @param phase The boot phase to start.
*/
public void startBootPhase(final int phase) {
if (phase <= mCurrentPhase) {
throw new IllegalArgumentException("Next phase must be larger than previous");
}
mCurrentPhase = phase;
Slog.i(TAG, "Starting phase " + mCurrentPhase);
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
long time = SystemClock.elapsedRealtime();
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, service.getClass().getName());
try {
service.onBootPhase(mCurrentPhase);
} catch (Exception ex) {
throw new RuntimeException("Failed to boot service "
+ service.getClass().getName()
+ ": onBootPhase threw an exception during phase "
+ mCurrentPhase, ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}