下面列出了怎么用android.util.TimingLogger的API类实例代码及写法,或者点击链接到github查看源代码。
@SuppressWarnings("JavaReflectionMemberAccess")
private void initFields() {
try {
Class tlClz = TimingLogger.class;
mDisabledField = tlClz.getDeclaredField("mDisabled");
mDisabledField.setAccessible(true);
mSplitsField = tlClz.getDeclaredField("mSplits");
mSplitsField.setAccessible(true);
mSplitLabelsField = tlClz.getDeclaredField("mSplitLabels");
mSplitLabelsField.setAccessible(true);
mTagField = tlClz.getDeclaredField("mTag");
mTagField.setAccessible(true);
mLabelField = tlClz.getDeclaredField("mLabel");
mLabelField.setAccessible(true);
} catch (NoSuchFieldException e) {
Log.w(TAG, "initFields: ", e);
}
}
@Nullable
public Context createContext() {
if (null == mTargetClass) {
mTargetClass = PluginInterceptActivity.class;
}
try {
TimingLogger logger = new TimingLogger(Constants.TAG, "PluginContext#createContext");
PluginInterceptActivity pluginActivity = (PluginInterceptActivity) mTargetClass.newInstance();
pluginActivity.setContextProxy(mContextProxy);
logger.addSplit("create proxy object");
attachStatus(pluginActivity);
logger.addSplit("attachStatus");
setTheme(pluginActivity);
logger.addSplit("setTheme");
logger.dumpToLog();
return pluginActivity;
} catch (Exception e) {
final String msg = "createContext error, targetClass: " + mTargetClass;
VLog.w(e, msg);
LogReporter.reportUsableSpaceMegabytes();
LogReporter.reportException(new PluginContextCreateException(msg, e), null);
}
return null;
}
@SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel")
public synchronized void init(@NonNull Context context, @NonNull List<String> trustedSignatures) {
if (mInitialized) {
VLog.w("already initialized, skip this time");
return;
}
TimingLogger logger = new TimingLogger(Constants.TAG, "PluginManager init");
mContext = context.getApplicationContext();
mTrustedSignatures = trustedSignatures;
mPluginDir = mContext.getDir("plugins", Context.MODE_PRIVATE);
logger.addSplit("create plugin dir");
initHostCompileDependencies();
logger.addSplit("init host compile dependencies");
initHostExportServices();
logger.addSplit("init host export service map");
int count = scanInstalledPlugins();
logger.addSplit("scanInstalledPlugins, count: " + count);
logger.dumpToLog();
mInitialized = true;
}
@Override
public void onResume() {
super.onResume();
setExportProgressBarVisible(exportProgressBarVisible);
setSyncProgressBarVisible(syncProgressBarVisible);
setClaimProgressBarVisible(claimProgressBarVisible);
connectivityBroadcastReceiver = new ConnectivityBroadcastReceiver();
getContext().registerReceiver(connectivityBroadcastReceiver, networkIntentFilter);
TimingLogger timing = new TimingLogger(TAG, "Sync on Resume");
AppSingleton.getInstance(applicationContext)
.whenNewExperimentSynced()
.takeUntil(paused.happens())
.subscribe(
count -> {
Handler uiHandler = new Handler(applicationContext.getMainLooper());
uiHandler.post(
() -> {
// This fragment may be gone by the time this code executes.
if (isFragmentGone()) {
return;
}
loadExperiments();
timing.addSplit("Syncing complete");
timing.dumpToLog();
});
});
loadExperiments();
syncNow("Sync On Resume");
}
public List<PreferenceIndex> doCrawl() {
final TimingLogger logger = new TimingLogger(TAG, "doCrawl");
List<PreferenceIndex> indexablePreferences = new ArrayList<>();
List<BaseIndexableFragment> indexableFragments = IndexableFragments.values();
for (BaseIndexableFragment indexableFragment : indexableFragments) {
indexablePreferences.addAll(indexableFragment.index(mContext));
logger.addSplit("processed " + indexableFragment.fragmentName);
}
logger.addSplit("Finish crawling");
logger.dumpToLog();
return indexablePreferences;
}
@SuppressLint("NewApi")
public static Bitmap NV21ToRGBABitmap(byte []nv21, int width, int height, Context context) {
TimingLogger timings = new TimingLogger(TIMING_LOG_TAG, "NV21ToRGBABitmap");
Rect rect = new Rect(0, 0, width, height);
try {
Class.forName("android.renderscript.Element$DataKind").getField("PIXEL_YUV");
Class.forName("android.renderscript.ScriptIntrinsicYuvToRGB");
byte[] imageData = nv21;
if (mRS == null) {
mRS = RenderScript.create(context);
mYuvToRgb = ScriptIntrinsicYuvToRGB.create(mRS, Element.U8_4(mRS));
Type.Builder tb = new Type.Builder(mRS, Element
.createPixel(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV));
tb.setX(width);
tb.setY(height);
tb.setMipmaps(false);
tb.setYuvFormat(ImageFormat.NV21);
ain = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT);
timings.addSplit("Prepare for ain");
Type.Builder tb2 = new Type.Builder(mRS, Element.RGBA_8888(mRS));
tb2.setX(width);
tb2.setY(height);
tb2.setMipmaps(false);
aOut = Allocation
.createTyped(mRS, tb2.create(), Allocation.USAGE_SCRIPT & Allocation.USAGE_SHARED);
timings.addSplit("Prepare for aOut");
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
timings.addSplit("Create Bitmap");
}
ain.copyFrom(imageData);
timings.addSplit("ain copyFrom");
mYuvToRgb.setInput(ain);
timings.addSplit("setInput ain");
mYuvToRgb.forEach(aOut);
timings.addSplit("NV21 to ARGB forEach");
aOut.copyTo(bitmap);
timings.addSplit("Allocation to Bitmap");
} catch (Exception e) {
YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
timings.addSplit("NV21 bytes to YuvImage");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvImage.compressToJpeg(rect, 90, baos);
byte[] cur = baos.toByteArray();
timings.addSplit("YuvImage crop and compress to Jpeg Bytes");
bitmap = BitmapFactory.decodeByteArray(cur, 0, cur.length);
timings.addSplit("Jpeg Bytes to Bitmap");
}
timings.dumpToLog();
return bitmap;
}
private Service handleCreateService(final PluginInfo pluginInfo, String serviceClassName) throws Throwable {
VLog.d("handleCreateService, pluginInfo: %s, serviceClassName: %s", pluginInfo.packageName, serviceClassName);
TimingLogger logger = new TimingLogger(TAG, "handleCreateService");
if (!pluginInfo.start()) {
throw new IllegalStateException("PluginInfo start failed");
}
logger.addSplit("start plugin");
final PluginClassLoader pluginClassLoader = pluginInfo.getPluginClassLoader();
if (pluginClassLoader == null) {
throw new IllegalStateException("PluginInfo#getPluginClassLoader is null");
}
logger.addSplit("get plugin classloader");
Class<?> serviceClass = pluginClassLoader.loadClass(serviceClassName);
if (serviceClass == null) {
throw new IllegalStateException("PluginClassLoader#loadClass return null");
}
logger.addSplit("load service class");
Service service = (Service) serviceClass.newInstance();
logger.addSplit("create service proxy");
if (PluginInterceptService.class.isAssignableFrom(serviceClass)) {
final PluginInterceptService pluginInterceptService = (PluginInterceptService) service;
pluginInterceptService.setContextProxy(new ContextProxy<Service>(pluginInfo, this));
pluginInterceptService.attachBaseContext(getBaseContext());
} else if (PluginInterceptIntentService.class.isAssignableFrom(serviceClass)) {
final PluginInterceptIntentService pluginInterceptIntentService = (PluginInterceptIntentService) service;
pluginInterceptIntentService.setContextProxy(new ContextProxy<Service>(pluginInfo, this));
pluginInterceptIntentService.attachBaseContext(getBaseContext());
}
logger.addSplit("call service attachBaseContext");
service.onCreate();
logger.addSplit("call service onCreate");
logger.dumpToLog();
ServiceHostProxyManager.INSTANCE.putPluginService(getClass().getName(), service);
return service;
}
private void loadPlugin(Context ctx, boolean firstStart) throws Throwable {
TimingLogger logger = new TimingLogger(Constants.TAG,
"PluginInfo#loadPlugin -> " + packageName + ", firstStart: " + firstStart);
final String tagDexLoad =
(firstStart ? LogReporter.EventId.PLUGIN_DEX_LOAD_FIRST : LogReporter.EventId.PLUGIN_DEX_LOAD)
+ packageName;
TimingUtils.startTime(tagDexLoad);
final PhantomCore phantomCore = PhantomCore.getInstance();
boolean turboDexEnabled = phantomCore.isTurboDexEnabled();
VLog.w("packageName: %s, firstStart: %s, turboDexEnabled: %s", packageName, firstStart, turboDexEnabled);
// Workaround for ANDROID_PHANTOM-204 异常信息为:创建 DexClassLoader 时,optimizedDirectory 不存在
// 这里再次确保目录已创建好
File odexDirFile = new File(odexDir);
File libDirFile = new File(libPath);
FileUtils.ensureDirectoryCreated(odexDirFile);
FileUtils.ensureDirectoryCreated(libDirFile);
// 首次加载插件是否需要加速 ?
final boolean shouldBoostFirstDexLoad = firstStart && turboDexEnabled;
if (shouldBoostFirstDexLoad) {
// 优化 ART 虚拟机(Android 5.0 及更高版本)冷启动 **首次** 加载插件耗时
// 1. 使用 alibaba-atlas 中的 ARTUtils 禁用 dexopt
// 2. 创建插件 ClassLoader 加载插件(这里由于禁用了 dexopt ,耗时会在 1 秒以内)
// 3. 重新启用 dexopt
// 4. 在后台线程中进行 dexopt ,提升在后续冷启动 **非首次** 运行插件效率
ARTUtils.setIsDex2oatEnabled(false);
mPluginClassLoader = new PluginClassLoader(this, ctx.getClassLoader());
ARTUtils.setIsDex2oatEnabled(true);
AsyncTask.execute(new DexOptTask(apkPath, odexPath));
} else {
mPluginClassLoader = new PluginClassLoader(this, ctx.getClassLoader());
}
trackDexLoadTime(firstStart, TimingUtils.getNormalizedDuration(tagDexLoad, TimingUtils.SECTION_DURATION_500_MS,
TimingUtils.MAX_SECTION_40));
logger.addSplit("create plugin classloader, firstStart: " + firstStart);
mPluginAssetManager = createAssetManager(ctx);
logger.addSplit("create asset manager");
mPluginResources = createResources(ctx, mPluginAssetManager);
logger.addSplit("create resource");
final String tagAppLoad = (firstStart ? LogReporter.EventId.PLUGIN_APPLICATION_LOAD_FIRST
: LogReporter.EventId.PLUGIN_APPLICATION_LOAD) + packageName;
TimingUtils.startTime(tagAppLoad);
createApplication(ctx.getApplicationContext());
trackAppCreateTime(firstStart,
TimingUtils.getNormalizedDuration(tagAppLoad, TimingUtils.SECTION_DURATION_100_MS,
TimingUtils.MAX_SECTION_20));
logger.addSplit("create application");
registerStaticBroadcastReceiver(ctx);
logger.addSplit("register static broadcast receiver");
logger.dumpToLog();
}
DexOptTask(String sourcePathName, String outputPathName) {
mTimingLogger = new TimingLogger(Constants.TAG, "DexOptTask");
mSourcePathName = sourcePathName;
mOutputPathName = outputPathName;
}
@SuppressLint("NewApi")
public static Bitmap NV21ToRGBABitmap(byte []nv21, int width, int height, Context context) {
TimingLogger timings = new TimingLogger(TIMING_LOG_TAG, "NV21ToRGBABitmap");
Rect rect = new Rect(0, 0, width, height);
try {
Class.forName("android.renderscript.Element$DataKind").getField("PIXEL_YUV");
Class.forName("android.renderscript.ScriptIntrinsicYuvToRGB");
byte[] imageData = nv21;
if (mRS == null) {
mRS = RenderScript.create(context);
mYuvToRgb = ScriptIntrinsicYuvToRGB.create(mRS, Element.U8_4(mRS));
Type.Builder tb = new Type.Builder(mRS, Element.createPixel(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV));
tb.setX(width);
tb.setY(height);
tb.setMipmaps(false);
tb.setYuvFormat(ImageFormat.NV21);
ain = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT);
timings.addSplit("Prepare for ain");
Type.Builder tb2 = new Type.Builder(mRS, Element.RGBA_8888(mRS));
tb2.setX(width);
tb2.setY(height);
tb2.setMipmaps(false);
aOut = Allocation.createTyped(mRS, tb2.create(), Allocation.USAGE_SCRIPT & Allocation.USAGE_SHARED);
timings.addSplit("Prepare for aOut");
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
timings.addSplit("Create Bitmap");
}
ain.copyFrom(imageData);
timings.addSplit("ain copyFrom");
mYuvToRgb.setInput(ain);
timings.addSplit("setInput ain");
mYuvToRgb.forEach(aOut);
timings.addSplit("NV21 to ARGB forEach");
aOut.copyTo(bitmap);
timings.addSplit("Allocation to Bitmap");
} catch (Exception e) {
YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
timings.addSplit("NV21 bytes to YuvImage");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvImage.compressToJpeg(rect, 90, baos);
byte[] cur = baos.toByteArray();
timings.addSplit("YuvImage crop and compress to Jpeg Bytes");
bitmap = BitmapFactory.decodeByteArray(cur, 0, cur.length);
timings.addSplit("Jpeg Bytes to Bitmap");
}
timings.dumpToLog();
return bitmap;
}
/**
* Create and initialize a TimingLogger object that will log using
* the specific tag.
*
* @param tag the log tag to use while logging the timings
* @param label a string to be displayed with each log
*/
public TrueTimingLogger(String tag, String label) {
ReflectionOnPie.clearClassLoaderInClass(TrueTimingLogger.class);
logger = new TimingLogger(tag, label);
initFields();
reset(tag, label);
}