提交 6d1228a2 编写于 作者: A Adam Barth

Enable tracing in SkyShell

This CL teaches shelldb how to trace SkyShell.

R=eseidel@chromium.org

Review URL: https://codereview.chromium.org/1027903002
上级 3c70e473
......@@ -10,8 +10,9 @@ import("//build/config/android/rules.gni")
generate_jni("jni_headers") {
sources = [
"org/domokit/sky/shell/JavaServiceProvider.java",
"org/domokit/sky/shell/SkyMain.java",
"org/domokit/sky/shell/PlatformView.java",
"org/domokit/sky/shell/SkyMain.java",
"org/domokit/sky/shell/TracingController.java",
]
jni_package = "sky/shell"
}
......@@ -35,6 +36,8 @@ shared_library("sky_shell") {
"shell.h",
"sky_main.cc",
"sky_main.h",
"tracing_controller.cc",
"tracing_controller.h",
"ui/animator.cc",
"ui/animator.h",
"ui/engine.cc",
......@@ -80,6 +83,7 @@ android_library("java") {
"org/domokit/sky/shell/SkyActivity.java",
"org/domokit/sky/shell/SkyApplication.java",
"org/domokit/sky/shell/SkyMain.java",
"org/domokit/sky/shell/TracingController.java",
]
deps = [
......
......@@ -13,14 +13,16 @@
#include "sky/shell/java_service_provider.h"
#include "sky/shell/platform_view.h"
#include "sky/shell/sky_main.h"
#include "sky/shell/tracing_controller.h"
namespace {
base::android::RegistrationMethod kSkyRegisteredMethods[] = {
{"CoreImpl", mojo::android::RegisterCoreImpl},
{"JavaServiceProvider", sky::shell::RegisterJavaServiceProvider},
{"SkyMain", sky::shell::RegisterSkyMain},
{"PlatformView", sky::shell::PlatformView::Register},
{"SkyMain", sky::shell::RegisterSkyMain},
{"TracingController", sky::shell::RegisterTracingController},
};
bool RegisterJNI(JNIEnv* env) {
......
......@@ -14,6 +14,7 @@ import android.view.WindowManager;
* Base class for activities that use Sky.
*/
public class SkyActivity extends Activity {
private TracingController mTracingController;
private PlatformView mView;
/**
......@@ -35,6 +36,7 @@ public class SkyActivity extends Activity {
SkyMain.ensureInitialized(getApplicationContext());
mView = new PlatformView(this);
setContentView(mView);
mTracingController = new TracingController(this);
}
public void loadUrl(String url) {
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.domokit.sky.shell;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.chromium.base.JNINamespace;
/**
* A controller for the tracing system.
*/
@JNINamespace("sky::shell")
class TracingController {
private static final String TAG = "TracingController";
private static final String TRACING_START = ".TRACING_START";
private static final String TRACING_STOP = ".TRACING_STOP";
private final Context mContext;
private final TracingBroadcastReceiver mBroadcastReceiver;
private final TracingIntentFilter mIntentFilter;
public TracingController(Context context) {
mContext = context;
mBroadcastReceiver = new TracingBroadcastReceiver();
mIntentFilter = new TracingIntentFilter(context);
mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
}
private String generateTracingFilePath() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HHmmss", Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
File dir = mContext.getCacheDir();
String date = formatter.format(new Date());
File file = new File(dir, "sky-trace-" + date + ".json");
return file.getPath();
}
class TracingIntentFilter extends IntentFilter {
TracingIntentFilter(Context context) {
Log.e(TAG, context.getPackageName() + TRACING_START);
addAction(context.getPackageName() + TRACING_START);
addAction(context.getPackageName() + TRACING_STOP);
}
}
class TracingBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().endsWith(TRACING_START)) {
nativeStartTracing();
} else if (intent.getAction().endsWith(TRACING_STOP)) {
nativeStopTracing(generateTracingFilePath());
} else {
Log.e(TAG, "Unexpected intent: " + intent);
}
}
}
private static native void nativeStartTracing();
private static native void nativeStopTracing(String path);
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/shell/tracing_controller.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/trace_event/trace_event.h"
#include "jni/TracingController_jni.h"
namespace sky {
namespace shell {
namespace {
const char kStart[] = "{\"traceEvents\":[";
const char kEnd[] = "]}";
static FILE* g_file = NULL;
void Write(const std::string& data) {
ignore_result(fwrite(data.data(), data.length(), 1, g_file));
}
void HandleChunk(const scoped_refptr<base::RefCountedString>& chunk,
bool has_more_events) {
Write(chunk->data());
if (has_more_events)
Write(",");
if (!has_more_events) {
Write(kEnd);
base::CloseFile(g_file);
g_file = NULL;
LOG(INFO) << "Trace complete";
}
}
} // namespace
static void StartTracing(JNIEnv* env, jclass clazz) {
LOG(INFO) << "Starting trace";
base::trace_event::TraceLog::GetInstance()->SetEnabled(
base::trace_event::CategoryFilter("*"),
base::trace_event::TraceLog::RECORDING_MODE,
base::trace_event::TraceOptions(base::trace_event::RECORD_UNTIL_FULL));
}
static void StopTracing(JNIEnv* env, jclass clazz, jstring path) {
base::trace_event::TraceLog::GetInstance()->SetDisabled();
base::FilePath file_path(base::android::ConvertJavaStringToUTF8(env, path));
g_file = base::OpenFile(file_path, "w");
CHECK(g_file) << "Failed to open file " << file_path.LossyDisplayName();
LOG(INFO) << "Saving trace to " << file_path.LossyDisplayName();
Write(kStart);
base::trace_event::TraceLog::GetInstance()->Flush(base::Bind(&HandleChunk));
}
bool RegisterTracingController(JNIEnv* env) {
return RegisterNativesImpl(env);
}
} // namespace shell
} // namespace sky
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_SHELL_TRACING_CONTROLLER_H_
#define SKY_SHELL_TRACING_CONTROLLER_H_
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
namespace sky {
namespace shell {
bool RegisterTracingController(JNIEnv* env);
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_TRACING_CONTROLLER_H_
......@@ -8,8 +8,10 @@ import argparse
import json
import logging
import os
import re
import subprocess
import sys
import time
import urlparse
SKY_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__))
......@@ -228,6 +230,49 @@ class Analyze(object):
]
subprocess.call(analyzer_args)
class StartTracing(object):
def add_subparser(self, subparsers):
start_tracing_parser = subparsers.add_parser('start_tracing',
help=('start tracing a running sky instance'))
start_tracing_parser.set_defaults(func=self.run)
def run(self, args, pids):
subprocess.check_output([ADB_PATH, 'shell',
'am', 'broadcast',
'-a', 'org.domokit.sky.demo.TRACING_START'])
TRACE_COMPLETE_REGEXP = re.compile('Trace complete')
TRACE_FILE_REGEXP = re.compile(r'Saving trace to (?P<path>\S+)')
class StopTracing(object):
def add_subparser(self, subparsers):
stop_tracing_parser = subparsers.add_parser('stop_tracing',
help=('stop tracing a running sky instance'))
stop_tracing_parser.set_defaults(func=self.run)
def run(self, args, pids):
subprocess.check_output([ADB_PATH, 'logcat', '-c'])
subprocess.check_output([ADB_PATH, 'shell',
'am', 'broadcast',
'-a', 'org.domokit.sky.demo.TRACING_STOP'])
device_path = None
is_complete = False
while not is_complete:
time.sleep(0.2)
log = subprocess.check_output([ADB_PATH, 'logcat', '-d'])
if device_path is None:
result = TRACE_FILE_REGEXP.search(log)
if result:
device_path = result.group('path')
is_complete = TRACE_COMPLETE_REGEXP.search(log) is not None
print 'Downloading trace %s ...' % os.path.basename(device_path)
if device_path:
subprocess.check_output([ADB_PATH, 'pull', device_path])
subprocess.check_output([ADB_PATH, 'shell', 'rm', device_path])
class SkyShellRunner(object):
def main(self):
......@@ -236,7 +281,15 @@ class SkyShellRunner(object):
parser = argparse.ArgumentParser(description='Sky Shell Runner')
subparsers = parser.add_subparsers(help='sub-command help')
for command in [StartSky(), StopSky(), Analyze()]:
commands = [
StartSky(),
StopSky(),
Analyze(),
StartTracing(),
StopTracing(),
]
for command in commands:
command.add_subparser(subparsers)
args = parser.parse_args()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册