提交 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") ...@@ -10,8 +10,9 @@ import("//build/config/android/rules.gni")
generate_jni("jni_headers") { generate_jni("jni_headers") {
sources = [ sources = [
"org/domokit/sky/shell/JavaServiceProvider.java", "org/domokit/sky/shell/JavaServiceProvider.java",
"org/domokit/sky/shell/SkyMain.java",
"org/domokit/sky/shell/PlatformView.java", "org/domokit/sky/shell/PlatformView.java",
"org/domokit/sky/shell/SkyMain.java",
"org/domokit/sky/shell/TracingController.java",
] ]
jni_package = "sky/shell" jni_package = "sky/shell"
} }
...@@ -35,6 +36,8 @@ shared_library("sky_shell") { ...@@ -35,6 +36,8 @@ shared_library("sky_shell") {
"shell.h", "shell.h",
"sky_main.cc", "sky_main.cc",
"sky_main.h", "sky_main.h",
"tracing_controller.cc",
"tracing_controller.h",
"ui/animator.cc", "ui/animator.cc",
"ui/animator.h", "ui/animator.h",
"ui/engine.cc", "ui/engine.cc",
...@@ -80,6 +83,7 @@ android_library("java") { ...@@ -80,6 +83,7 @@ android_library("java") {
"org/domokit/sky/shell/SkyActivity.java", "org/domokit/sky/shell/SkyActivity.java",
"org/domokit/sky/shell/SkyApplication.java", "org/domokit/sky/shell/SkyApplication.java",
"org/domokit/sky/shell/SkyMain.java", "org/domokit/sky/shell/SkyMain.java",
"org/domokit/sky/shell/TracingController.java",
] ]
deps = [ deps = [
......
...@@ -13,14 +13,16 @@ ...@@ -13,14 +13,16 @@
#include "sky/shell/java_service_provider.h" #include "sky/shell/java_service_provider.h"
#include "sky/shell/platform_view.h" #include "sky/shell/platform_view.h"
#include "sky/shell/sky_main.h" #include "sky/shell/sky_main.h"
#include "sky/shell/tracing_controller.h"
namespace { namespace {
base::android::RegistrationMethod kSkyRegisteredMethods[] = { base::android::RegistrationMethod kSkyRegisteredMethods[] = {
{"CoreImpl", mojo::android::RegisterCoreImpl}, {"CoreImpl", mojo::android::RegisterCoreImpl},
{"JavaServiceProvider", sky::shell::RegisterJavaServiceProvider}, {"JavaServiceProvider", sky::shell::RegisterJavaServiceProvider},
{"SkyMain", sky::shell::RegisterSkyMain},
{"PlatformView", sky::shell::PlatformView::Register}, {"PlatformView", sky::shell::PlatformView::Register},
{"SkyMain", sky::shell::RegisterSkyMain},
{"TracingController", sky::shell::RegisterTracingController},
}; };
bool RegisterJNI(JNIEnv* env) { bool RegisterJNI(JNIEnv* env) {
......
...@@ -14,6 +14,7 @@ import android.view.WindowManager; ...@@ -14,6 +14,7 @@ import android.view.WindowManager;
* Base class for activities that use Sky. * Base class for activities that use Sky.
*/ */
public class SkyActivity extends Activity { public class SkyActivity extends Activity {
private TracingController mTracingController;
private PlatformView mView; private PlatformView mView;
/** /**
...@@ -35,6 +36,7 @@ public class SkyActivity extends Activity { ...@@ -35,6 +36,7 @@ public class SkyActivity extends Activity {
SkyMain.ensureInitialized(getApplicationContext()); SkyMain.ensureInitialized(getApplicationContext());
mView = new PlatformView(this); mView = new PlatformView(this);
setContentView(mView); setContentView(mView);
mTracingController = new TracingController(this);
} }
public void loadUrl(String url) { 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 ...@@ -8,8 +8,10 @@ import argparse
import json import json
import logging import logging
import os import os
import re
import subprocess import subprocess
import sys import sys
import time
import urlparse import urlparse
SKY_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__)) SKY_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__))
...@@ -228,6 +230,49 @@ class Analyze(object): ...@@ -228,6 +230,49 @@ class Analyze(object):
] ]
subprocess.call(analyzer_args) 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): class SkyShellRunner(object):
def main(self): def main(self):
...@@ -236,7 +281,15 @@ class SkyShellRunner(object): ...@@ -236,7 +281,15 @@ class SkyShellRunner(object):
parser = argparse.ArgumentParser(description='Sky Shell Runner') parser = argparse.ArgumentParser(description='Sky Shell Runner')
subparsers = parser.add_subparsers(help='sub-command help') 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) command.add_subparser(subparsers)
args = parser.parse_args() args = parser.parse_args()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册