Perfetto 是 google 从 Android10 开始引入的一个全新的平台级跟踪分析工具。它可以记录 Android 系统运行过程中的关键数据,并通过图形化的形式展示这些数据。Perfetto 不仅可用于系统级的性能分析,也是我们学习系统源码流程的好帮手。
Perfetto 算是Systrace的升级版本,可以直观的看到跨进程的调用方式。
2. 如何抓取 Trace
使用 Perfetto 一般分两步进行:
收集手机运行过程中的信息,这些信息通常称之为 Trace,收集的过程称之为抓取 Trace。
使用 Perfetto 打开 Trace,分析 Trace
本节介绍如何抓取 Trace 。
2.1 使用命令行抓取 Trace
2.1.1 使用 perfetto 命令抓取
首先使用 usb 线将电脑和手机连接,确保 adb shell 命令能正常工作。
接着执行下面的命令:
1
2
adb shell perfetto -o /data/misc/perfetto-traces/trace_file.perfetto-trace t 20s \ sched freq idle am wm gfx view binder_driver hal dalvik camera input res memory
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/#ifndef_LIBS_CUTILS_TRACE_H#define_LIBS_CUTILS_TRACE_H#include<inttypes.h>#include<stdatomic.h>#include<stdbool.h>#include<stdint.h>#include<stdio.h>#include<sys/cdefs.h>#include<sys/types.h>#include<unistd.h>#include<cutils/compiler.h>__BEGIN_DECLS/**
* The ATRACE_TAG macro can be defined before including this header to trace
* using one of the tags defined below. It must be defined to one of the
* following ATRACE_TAG_* macros. The trace tag is used to filter tracing in
* userland to avoid some of the runtime cost of tracing when it is not desired.
*
* Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
* being enabled - this should ONLY be done for debug code, as userland tracing
* has a performance cost even when the trace is not being recorded. Defining
* ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
* in the tracing always being disabled.
*
* ATRACE_TAG_HAL should be bitwise ORed with the relevant tags for tracing
* within a hardware module. For example a camera hardware module would set:
* #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
*
* Keep these in sync with frameworks/base/core/java/android/os/Trace.java.
*/#defineATRACE_TAG_NEVER0// This tag is never enabled.#defineATRACE_TAG_ALWAYS(1<<0)// This tag is always enabled.#defineATRACE_TAG_GRAPHICS(1<<1)#defineATRACE_TAG_INPUT(1<<2)#defineATRACE_TAG_VIEW(1<<3)#defineATRACE_TAG_WEBVIEW(1<<4)#defineATRACE_TAG_WINDOW_MANAGER(1<<5)#defineATRACE_TAG_ACTIVITY_MANAGER(1<<6)#defineATRACE_TAG_SYNC_MANAGER(1<<7)#defineATRACE_TAG_AUDIO(1<<8)#defineATRACE_TAG_VIDEO(1<<9)#defineATRACE_TAG_CAMERA(1<<10)#defineATRACE_TAG_HAL(1<<11)#defineATRACE_TAG_APP(1<<12)#defineATRACE_TAG_RESOURCES(1<<13)#defineATRACE_TAG_DALVIK(1<<14)#defineATRACE_TAG_RS(1<<15)#defineATRACE_TAG_BIONIC(1<<16)#defineATRACE_TAG_POWER(1<<17)#defineATRACE_TAG_PACKAGE_MANAGER(1<<18)#defineATRACE_TAG_SYSTEM_SERVER(1<<19)#defineATRACE_TAG_DATABASE(1<<20)#defineATRACE_TAG_NETWORK(1<<21)#defineATRACE_TAG_ADB(1<<22)#defineATRACE_TAG_VIBRATOR(1<<23)#defineATRACE_TAG_AIDL(1<<24)#defineATRACE_TAG_NNAPI(1<<25)#defineATRACE_TAG_RRO(1<<26)#defineATRACE_TAG_THERMAL(1<<27)#defineATRACE_TAG_LASTATRACE_TAG_THERMAL// Reserved for initialization.#defineATRACE_TAG_NOT_READY(1ULL<<63)#defineATRACE_TAG_VALID_MASK((ATRACE_TAG_LAST-1)|ATRACE_TAG_LAST)#ifndefATRACE_TAG#defineATRACE_TAGATRACE_TAG_NEVER#elifATRACE_TAG>ATRACE_TAG_VALID_MASK#errorATRACE_TAGmustbedefinedtobeoneofthetagsdefinedincutils/trace.h#endif/**
* Opens the trace file for writing and reads the property for initial tags.
* The atrace.tags.enableflags property sets the tags to trace.
* This function should not be explicitly called, the first call to any normal
* trace function will cause it to be run safely.
*/voidatrace_setup();/**
* If tracing is ready, set atrace_enabled_tags to the system property
* debug.atrace.tags.enableflags. Can be used as a sysprop change callback.
*/voidatrace_update_tags();/**
* Set whether tracing is enabled for the current process. This is used to
* prevent tracing within the Zygote process.
*/voidatrace_set_tracing_enabled(boolenabled);/**
* This is always set to false. This forces code that uses an old version
* of this header to always call into atrace_setup, in which we call
* atrace_init unconditionally.
*/externatomic_boolatrace_is_ready;/**
* Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY.
* A value of zero indicates setup has failed.
* Any other nonzero value indicates setup has succeeded, and tracing is on.
*/externuint64_tatrace_enabled_tags;/**
* Handle to the kernel's trace buffer, initialized to -1.
* Any other value indicates setup has succeeded, and is a valid fd for tracing.
*/externintatrace_marker_fd;/**
* atrace_init readies the process for tracing by opening the trace_marker file.
* Calling any trace function causes this to be run, so calling it is optional.
* This can be explicitly run to avoid setup delay on first trace function.
*/#defineATRACE_INIT()atrace_init()#defineATRACE_GET_ENABLED_TAGS()atrace_get_enabled_tags()voidatrace_init();uint64_tatrace_get_enabled_tags();/**
* Test if a given tag is currently enabled.
* Returns nonzero if the tag is enabled, otherwise zero.
* It can be used as a guard condition around more expensive trace calculations.
*/#defineATRACE_ENABLED()atrace_is_tag_enabled(ATRACE_TAG)staticinlineuint64_tatrace_is_tag_enabled(uint64_ttag){returnatrace_get_enabled_tags()&tag;}/**
* Trace the beginning of a context. name is used to identify the context.
* This is often used to time function execution.
*/#defineATRACE_BEGIN(name)atrace_begin(ATRACE_TAG,name)staticinlinevoidatrace_begin(uint64_ttag,constchar*name){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_begin_body(constchar*);atrace_begin_body(name);}}/**
* Trace the end of a context.
* This should match up (and occur after) a corresponding ATRACE_BEGIN.
*/#defineATRACE_END()atrace_end(ATRACE_TAG)staticinlinevoidatrace_end(uint64_ttag){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_end_body();atrace_end_body();}}/**
* Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END
* contexts, asynchronous events do not need to be nested. The name describes
* the event, and the cookie provides a unique identifier for distinguishing
* simultaneous events. The name and cookie used to begin an event must be
* used to end it.
*/#defineATRACE_ASYNC_BEGIN(name,cookie)\atrace_async_begin(ATRACE_TAG,name,cookie)staticinlinevoidatrace_async_begin(uint64_ttag,constchar*name,int32_tcookie){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_async_begin_body(constchar*,int32_t);atrace_async_begin_body(name,cookie);}}/**
* Trace the end of an asynchronous event.
* This should have a corresponding ATRACE_ASYNC_BEGIN.
*/#defineATRACE_ASYNC_END(name,cookie)atrace_async_end(ATRACE_TAG,name,cookie)staticinlinevoidatrace_async_end(uint64_ttag,constchar*name,int32_tcookie){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_async_end_body(constchar*,int32_t);atrace_async_end_body(name,cookie);}}/**
* Trace the beginning of an asynchronous event. In addition to the name and a
* cookie as in ATRACE_ASYNC_BEGIN/ATRACE_ASYNC_END, a track name argument is
* provided, which is the name of the row where this async event should be
* recorded. The track name, name, and cookie used to begin an event must be
* used to end it.
*/#defineATRACE_ASYNC_FOR_TRACK_BEGIN(track_name,name,cookie)\atrace_async_for_track_begin(ATRACE_TAG,track_name,name,cookie)staticinlinevoidatrace_async_for_track_begin(uint64_ttag,constchar*track_name,constchar*name,int32_tcookie){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_async_for_track_begin_body(constchar*,constchar*,int32_t);atrace_async_for_track_begin_body(track_name,name,cookie);}}/**
* Trace the end of an asynchronous event.
* This should correspond to a previous ATRACE_ASYNC_FOR_TRACK_BEGIN.
*/#defineATRACE_ASYNC_FOR_TRACK_END(track_name,name,cookie)\atrace_async_for_track_end(ATRACE_TAG,track_name,name,cookie)staticinlinevoidatrace_async_for_track_end(uint64_ttag,constchar*track_name,constchar*name,int32_tcookie){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_async_for_track_end_body(constchar*,constchar*,int32_t);atrace_async_for_track_end_body(track_name,name,cookie);}}/**
* Trace an instantaneous context. name is used to identify the context.
*
* An "instant" is an event with no defined duration. Visually is displayed like a single marker
* in the timeline (rather than a span, in the case of begin/end events).
*
* By default, instant events are added into a dedicated track that has the same name of the event.
* Use atrace_instant_for_track to put different instant events into the same timeline track/row.
*/#defineATRACE_INSTANT(name)atrace_instant(ATRACE_TAG,name)staticinlinevoidatrace_instant(uint64_ttag,constchar*name){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_instant_body(constchar*);atrace_instant_body(name);}}/**
* Trace an instantaneous context. name is used to identify the context.
* track_name is the name of the row where the event should be recorded.
*
* An "instant" is an event with no defined duration. Visually is displayed like a single marker
* in the timeline (rather than a span, in the case of begin/end events).
*/#defineATRACE_INSTANT_FOR_TRACK(trackName,name)\atrace_instant_for_track(ATRACE_TAG,trackName,name)staticinlinevoidatrace_instant_for_track(uint64_ttag,constchar*track_name,constchar*name){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_instant_for_track_body(constchar*,constchar*);atrace_instant_for_track_body(track_name,name);}}/**
* Traces an integer counter value. name is used to identify the counter.
* This can be used to track how a value changes over time.
*/#defineATRACE_INT(name,value)atrace_int(ATRACE_TAG,name,value)staticinlinevoidatrace_int(uint64_ttag,constchar*name,int32_tvalue){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_int_body(constchar*,int32_t);atrace_int_body(name,value);}}/**
* Traces a 64-bit integer counter value. name is used to identify the
* counter. This can be used to track how a value changes over time.
*/#defineATRACE_INT64(name,value)atrace_int64(ATRACE_TAG,name,value)staticinlinevoidatrace_int64(uint64_ttag,constchar*name,int64_tvalue){if(CC_UNLIKELY(atrace_is_tag_enabled(tag))){voidatrace_int64_body(constchar*,int64_t);atrace_int64_body(name,value);}}__END_DECLS#endif//_LIBS_CUTILS_TRACE_H
/**
* Writes a trace message to indicate that a given section of code has
* begun. Must be followed by a call to {@link #traceEnd} using the same
* tag.
*
* @param traceTag The trace tag.
* @param methodName The method name to appear in the trace.
*
* @hide
*/@UnsupportedAppUsage@SystemApi(client=MODULE_LIBRARIES)publicstaticvoidtraceBegin(longtraceTag,@NonNullStringmethodName){if(isTagEnabled(traceTag)){nativeTraceBegin(traceTag,methodName);}}/**
* Writes a trace message to indicate that the current method has ended.
* Must be called exactly once for each call to {@link #traceBegin} using the same tag.
*
* @param traceTag The trace tag.
*
* @hide
*/@UnsupportedAppUsage@SystemApi(client=MODULE_LIBRARIES)publicstaticvoidtraceEnd(longtraceTag){if(isTagEnabled(traceTag)){nativeTraceEnd(traceTag);}}
具体使用方法:
1
2
3
4
5
6
7
8
protectedvoidonStart(){Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,"Settings Home onStart()");((SettingsApplication)getApplication()).setHomeActivity(this);super.onStart();doAidlHalCall();Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);}