aboutsummaryrefslogtreecommitdiffhomepage
path: root/platform_tools
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2015-06-12 12:51:44 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-06-12 12:51:44 -0700
commit030dc847dc497b011c417dc6694e8b6de290895f (patch)
treed943ac79c22575874932e4100e3dd91dccac168f /platform_tools
parent6eba3054229a9b656e372c3b80003f442a5d6161 (diff)
Visual bench on native android
Diffstat (limited to 'platform_tools')
-rw-r--r--platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp18
-rw-r--r--platform_tools/android/gyp/dependencies.gypi34
-rw-r--r--platform_tools/android/gyp/skia_android.gypi134
-rw-r--r--platform_tools/android/visualbench/AndroidManifest.xml29
-rw-r--r--platform_tools/android/visualbench/build.xml61
-rw-r--r--platform_tools/android/visualbench/jni/SkOSWindow_AndroidNative.cpp187
-rw-r--r--platform_tools/android/visualbench/jni/main.cpp128
-rw-r--r--platform_tools/android/visualbench/project.properties14
-rw-r--r--platform_tools/android/visualbench/src/com/skia/VisualBenchActivity.java50
9 files changed, 626 insertions, 29 deletions
diff --git a/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp b/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp
index 7eb1c09388..d66221a01c 100644
--- a/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp
+++ b/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp
@@ -58,6 +58,12 @@ SampleWindow* gWindow;
///////////// SkOSWindow impl /////////////
///////////////////////////////////////////
+SkOSWindow::SkOSWindow(void*) : fDestroyRequested(false) {
+}
+
+SkOSWindow::~SkOSWindow() {
+}
+
bool SkOSWindow::attach(SkBackEndTypes /* attachType */, int /*msaaSampleCount*/, AttachmentInfo* info)
{
JNIEnv* env = gActivityGlue.m_env;
@@ -75,6 +81,18 @@ bool SkOSWindow::attach(SkBackEndTypes /* attachType */, int /*msaaSampleCount*/
return true;
}
+void SkOSWindow::detach() {
+}
+
+void SkOSWindow::present() {
+}
+
+void SkOSWindow::closeWindow() {
+}
+
+void SkOSWindow::setVsync(bool) {
+}
+
void SkOSWindow::onSetTitle(const char title[])
{
JNIEnv* env = gActivityGlue.m_env;
diff --git a/platform_tools/android/gyp/dependencies.gypi b/platform_tools/android/gyp/dependencies.gypi
index 40dcf767c1..507a163458 100644
--- a/platform_tools/android/gyp/dependencies.gypi
+++ b/platform_tools/android/gyp/dependencies.gypi
@@ -290,7 +290,39 @@
'../app/jni/com_skia_SkiaSampleRenderer.cpp',
],
},
-
+ },
+ {
+ # This target is a dependency for VisualBench application which runs on
+ # Android. Since Android requires us to load native code in shared
+ # libraries, we need a common entry point to wrap around main(). Here
+ # we also change the type of all would-be executables to be shared
+ # libraries. The alternative would be to introduce a condition in every
+ # executable target which changes to a shared library if the target OS is
+ # Android. This is nicer because the switch is in one place.
+ 'target_name': 'Android_VisualBench',
+ 'type': 'static_library',
+ 'direct_dependent_settings': {
+ 'target_conditions': [
+ # '_type' is an 'automatic variable' which is defined for any
+ # target which defines a key-value pair with 'type' as the key (so,
+ # all of them). Conditionals inside 'target_conditions' are evaluated
+ # *after* all other definitions and conditionals are evaluated, so
+ # we're guaranteed that '_type' will be defined when we get here.
+ # For more info, see:
+ # - http://code.google.com/p/gyp/wiki/InputFormatReference#Variables
+ # - http://codereview.appspot.com/6353065/
+ ['_type == "executable"', {
+ 'type': 'shared_library',
+ }],
+ ],
+ 'include_dirs': [
+ '../../../tools/timer/',
+ ],
+ 'sources': [
+ '../visualbench/jni/SkOSWindow_AndroidNative.cpp',
+ '../visualbench/jni/main.cpp',
+ ],
+ },
},
]
}
diff --git a/platform_tools/android/gyp/skia_android.gypi b/platform_tools/android/gyp/skia_android.gypi
index ace21ccae7..a250b5958c 100644
--- a/platform_tools/android/gyp/skia_android.gypi
+++ b/platform_tools/android/gyp/skia_android.gypi
@@ -1,5 +1,38 @@
+# Copyright 2015 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This GYP file stores the dependencies necessary to build Skia on the Android
+# platform. The OS doesn't provide many stable libraries as part of the
+# distribution so we have to build a few of them ourselves.
#
{
+ 'variables': {
+ 'conditions': [
+ [ 'skia_arch_type == "arm" and arm_version != 7', {
+ 'android_arch%': "armeabi",
+ }],
+ [ 'skia_arch_type == "arm" and arm_version == 7', {
+ 'android_arch%': "armeabi-v7a",
+ }],
+ [ 'skia_arch_type == "arm64"', {
+ 'android_arch%': "arm64-v8a",
+ }],
+ [ 'skia_arch_type == "x86"', {
+ 'android_arch%': "x86",
+ }],
+ [ 'skia_arch_type == "x86_64"', {
+ 'android_arch%': "x86_64",
+ }],
+ [ 'skia_arch_type == "mips" and skia_arch_width == 32', {
+ 'android_arch%': "mips",
+ }],
+ [ 'skia_arch_type == "mips" and skia_arch_width == 64', {
+ 'android_arch%': "mips64",
+ }],
+ ],
+ },
'targets': [
{
'target_name': 'CopySampleAppDeps',
@@ -8,31 +41,6 @@
'skia_lib.gyp:skia_lib',
'SampleApp.gyp:SampleApp',
],
- 'variables': {
- 'conditions': [
- [ 'skia_arch_type == "arm" and arm_version != 7', {
- 'android_arch%': "armeabi",
- }],
- [ 'skia_arch_type == "arm" and arm_version == 7', {
- 'android_arch%': "armeabi-v7a",
- }],
- [ 'skia_arch_type == "arm64"', {
- 'android_arch%': "arm64-v8a",
- }],
- [ 'skia_arch_type == "x86"', {
- 'android_arch%': "x86",
- }],
- [ 'skia_arch_type == "x86_64"', {
- 'android_arch%': "x86_64",
- }],
- [ 'skia_arch_type == "mips" and skia_arch_width == 32', {
- 'android_arch%': "mips",
- }],
- [ 'skia_arch_type == "mips" and skia_arch_width == 64', {
- 'android_arch%': "mips64",
- }],
- ],
- },
'copies': [
# Copy all shared libraries into the Android app's libs folder. Note
# that this copy requires us to build SkiaAndroidApp after those
@@ -40,7 +48,7 @@
# libraries to copy, this will cause an error in Make, but the app will
# still build.
{
- 'destination': '<(PRODUCT_DIR)/android/libs/<(android_arch)',
+ 'destination': '<(PRODUCT_DIR)/android/SampleApp/libs/<(android_arch)',
'conditions': [
[ 'skia_shared_lib', {
'files': [
@@ -66,7 +74,7 @@
# the ninja generator treats PRODUCT_DIR as a relative path to the
# gyp directory but android ant build wants a path relative to the
# build.xml file so we do that adjustment here.
- 'ANDROID_OUT': '../../<(PRODUCT_DIR)/android'
+ 'ANDROID_OUT': '../../<(PRODUCT_DIR)/android/SampleApp'
},
'actions': [
{
@@ -82,7 +90,7 @@
'<(android_base)/app/src/com/skia/SkiaSampleView.java',
],
'outputs': [
- '<(PRODUCT_DIR)/../android/bin/SkiaAndroid.apk',
+ '<(PRODUCT_DIR)/../android/SampleApp/bin/SkiaAndroid.apk',
],
'action': [
'ant',
@@ -99,5 +107,75 @@
},
],
},
+ {
+ 'target_name': 'CopyVisualBenchDeps',
+ 'type': 'none',
+ 'dependencies': [
+ 'skia_lib.gyp:skia_lib',
+ 'visualbench.gyp:visualbench',
+ ],
+
+ 'copies': [
+ # Copy all shared libraries into the Android app's libs folder. Note
+ # that this copy requires us to build SkiaAndroidApp after those
+ # libraries, so that they exist by the time it occurs. If there are no
+ # libraries to copy, this will cause an error in Make, but the app will
+ # still build.
+ {
+ 'destination': '<(PRODUCT_DIR)/android/VisualBench/libs/<(android_arch)',
+ 'conditions': [
+ [ 'skia_shared_lib', {
+ 'files': [
+ '<(SHARED_LIB_DIR)/libskia_android.so',
+ '<(SHARED_LIB_DIR)/libvisualbench.so',
+ ]}, {
+ 'files': [
+ '<(SHARED_LIB_DIR)/libvisualbench.so',
+ ]}
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'VisualBench_APK',
+ 'type': 'none',
+ 'dependencies': [
+ 'CopyVisualBenchDeps',
+ ],
+ 'variables': {
+ 'ANDROID_SDK_ROOT': '<!(echo $ANDROID_SDK_ROOT)',
+ # the ninja generator treats PRODUCT_DIR as a relative path to the
+ # gyp directory but android ant build wants a path relative to the
+ # build.xml file so we do that adjustment here.
+ 'ANDROID_OUT': '../../<(PRODUCT_DIR)/android/VisualBench/'
+ },
+ 'actions': [
+ {
+ 'action_name': 'SkiaVisualBench_apk',
+ 'inputs': [
+ '<(android_base)/visualbench/AndroidManifest.xml',
+ '<(android_base)/visualbench/build.xml',
+ '<(android_base)/visualbench/project.properties',
+ '<(android_base)/visualbench/src/com/skia/VisualBenchActivity.java',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/../android/VisualBench/bin/VisualBench.apk',
+ ],
+ 'action': [
+ 'ant',
+ '-quiet',
+ '-f',
+ '<(android_base)/visualbench/build.xml',
+ '-Dout.dir=<(ANDROID_OUT)/bin',
+ '-Dgen.absolute.dir=<(ANDROID_OUT)/gen',
+ '-Dnative.libs.absolute.dir=<(ANDROID_OUT)/libs',
+ '-Dout.final.file=<(ANDROID_OUT)/bin/VisualBench.apk',
+ '-Dsdk.dir=<(ANDROID_SDK_ROOT)',
+ 'debug',
+ ],
+ },
+ ],
+ },
],
}
diff --git a/platform_tools/android/visualbench/AndroidManifest.xml b/platform_tools/android/visualbench/AndroidManifest.xml
new file mode 100644
index 0000000000..c15dee6e16
--- /dev/null
+++ b/platform_tools/android/visualbench/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- BEGIN_INCLUDE(manifest) -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.skia"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <!-- This is the platform API where NativeActivity was introduced. -->
+ <uses-sdk android:minSdkVersion="9" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <application android:label="VisualBenchActivity">
+ <activity android:name=".VisualBenchActivity"
+ android:label="VisualBenchActivity"
+ android:configChanges="orientation|keyboardHidden"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+ <meta-data android:name="android.app.lib_name"
+ android:value="visualbench" />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
+<!-- END_INCLUDE(manifest) -->
diff --git a/platform_tools/android/visualbench/build.xml b/platform_tools/android/visualbench/build.xml
new file mode 100644
index 0000000000..61df264754
--- /dev/null
+++ b/platform_tools/android/visualbench/build.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="VisualBench" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
+ unless="sdk.dir"
+ />
+
+ <!--
+ Import per project custom build rules if present at the root of the project.
+ This is the place to put custom intermediary targets such as:
+ -pre-build
+ -pre-compile
+ -post-compile (This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir})
+ -post-package
+ -post-build
+ -pre-clean
+ -->
+ <import file="custom_rules.xml" optional="true" />
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: 1 -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/platform_tools/android/visualbench/jni/SkOSWindow_AndroidNative.cpp b/platform_tools/android/visualbench/jni/SkOSWindow_AndroidNative.cpp
new file mode 100644
index 0000000000..e2bc99610f
--- /dev/null
+++ b/platform_tools/android/visualbench/jni/SkOSWindow_AndroidNative.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkOSWindow_Android.h"
+
+#include <GLES/gl.h>
+
+SkOSWindow::SkOSWindow(void* hwnd) {
+ fWindow.fDisplay = EGL_NO_DISPLAY;
+ fWindow.fContext = EGL_NO_CONTEXT;
+ fWindow.fSurface = EGL_NO_SURFACE;
+ fNativeWindow = (ANativeWindow*)hwnd;
+ fDestroyRequested = false;
+}
+
+SkOSWindow::~SkOSWindow() {
+ if (fWindow.fDisplay != EGL_NO_DISPLAY) {
+ eglMakeCurrent(fWindow.fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (fWindow.fContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(fWindow.fDisplay, fWindow.fContext);
+ }
+ if (fWindow.fSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(fWindow.fDisplay, fWindow.fSurface);
+ }
+ eglTerminate(fWindow.fDisplay);
+ }
+ fWindow.fDisplay = EGL_NO_DISPLAY;
+ fWindow.fContext = EGL_NO_CONTEXT;
+ fWindow.fSurface = EGL_NO_SURFACE;
+}
+
+bool SkOSWindow::attach(SkBackEndTypes attachType,
+ int /*msaaSampleCount*/,
+ AttachmentInfo* info) {
+ static const EGLint kEGLContextAttribsForOpenGL[] = {
+ EGL_NONE
+ };
+
+ static const EGLint kEGLContextAttribsForOpenGLES[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ static const struct {
+ const EGLint* fContextAttribs;
+ EGLenum fAPI;
+ EGLint fRenderableTypeBit;
+ } kAPIs[] = {
+ { // OpenGL
+ kEGLContextAttribsForOpenGL,
+ EGL_OPENGL_API,
+ EGL_OPENGL_BIT,
+ },
+ { // OpenGL ES. This seems to work for both ES2 and 3 (when available).
+ kEGLContextAttribsForOpenGLES,
+ EGL_OPENGL_ES_API,
+ EGL_OPENGL_ES2_BIT,
+ },
+ };
+
+ size_t apiLimit = SK_ARRAY_COUNT(kAPIs);
+
+ for (size_t api = 0; api < apiLimit; ++api) {
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ eglInitialize(display, &majorVersion, &minorVersion);
+
+#if 0
+ SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR));
+ SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS));
+ SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION));
+ SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS));
+#endif
+
+ if (!eglBindAPI(kAPIs[api].fAPI)) {
+ continue;
+ }
+
+ const EGLint configAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE
+ };
+
+ EGLint format;
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLSurface surface;
+ EGLContext context;
+
+ /* Here, the application chooses the configuration it desires. In this
+ * sample, we have a very simplified selection process, where we pick
+ * the first EGLConfig that matches our criteria */
+ eglChooseConfig(display, configAttribs, &config, 1, &numConfigs);
+
+ /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
+ * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
+ * As soon as we picked a EGLConfig, we can safely reconfigure the
+ * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
+ eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
+
+ ANativeWindow_setBuffersGeometry(fNativeWindow, 0, 0, format);
+
+ surface = eglCreateWindowSurface(display, config, fNativeWindow, NULL);
+ context = eglCreateContext(display, config, NULL, kAPIs[api].fContextAttribs);
+ if (EGL_NO_CONTEXT == context) {
+ SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError());
+ continue;
+ }
+
+ if (!eglMakeCurrent(display, surface, surface, context)) {
+ SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError());
+ continue;
+ }
+
+ fWindow.fDisplay = display;
+ fWindow.fContext = context;
+ fWindow.fSurface = surface;
+ }
+
+ if (fWindow.fDisplay && fWindow.fContext && fWindow.fSurface) {
+ EGLint w, h;
+ eglQuerySurface(fWindow.fDisplay, fWindow.fSurface, EGL_WIDTH, &w);
+ eglQuerySurface(fWindow.fDisplay, fWindow.fSurface, EGL_HEIGHT, &h);
+
+ glViewport(0, 0, w, h);
+ glClearColor(0.0, 0, 0, 0.0);
+ glClearStencil(0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ // We retrieve the fullscreen width and height
+ this->setSize((SkScalar)w, (SkScalar)h);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void SkOSWindow::detach() {
+ fDestroyRequested = true;
+}
+
+void SkOSWindow::present() {
+ if (fWindow.fDisplay != EGL_NO_DISPLAY && fWindow.fContext != EGL_NO_CONTEXT) {
+ eglSwapBuffers(fWindow.fDisplay, fWindow.fSurface);
+ }
+}
+
+void SkOSWindow::closeWindow() {
+ fDestroyRequested = true;
+}
+
+void SkOSWindow::setVsync(bool vsync) {
+ if (fWindow.fDisplay != EGL_NO_DISPLAY) {
+ int swapInterval = vsync ? 1 : 0;
+ eglSwapInterval(fWindow.fDisplay, swapInterval);
+ }
+}
+
+void SkOSWindow::onSetTitle(const char title[]) {
+}
+
+void SkOSWindow::onHandleInval(const SkIRect& rect) {
+}
+
+void SkOSWindow::onPDFSaved(const char title[], const char desc[], const char path[]) {
+}
+
+///////////////////////////////////////////
+/////////////// SkEvent impl //////////////
+///////////////////////////////////////////
+
+void SkEvent::SignalQueueTimer(SkMSec ms) {
+}
+
+void SkEvent::SignalNonEmptyQueue() {
+}
diff --git a/platform_tools/android/visualbench/jni/main.cpp b/platform_tools/android/visualbench/jni/main.cpp
new file mode 100644
index 0000000000..293041ae8e
--- /dev/null
+++ b/platform_tools/android/visualbench/jni/main.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#include <android_native_app_glue.h>
+
+#include "SkApplication.h"
+#include "VisualBench.h"
+
+/**
+ * Shared state for our app.
+ */
+struct VisualBenchState {
+ VisualBenchState() : fApp(NULL), fWindow(NULL) {}
+ struct android_app* fApp;
+ SkOSWindow* fWindow;
+ SkTArray<SkString> fFlags;
+};
+
+static void handle_cmd(struct android_app* app, int32_t cmd) {
+ struct VisualBenchState* state = (struct VisualBenchState*)app->userData;
+ switch (cmd) {
+ case APP_CMD_INIT_WINDOW:
+ // The window is being shown, get it ready.
+ if (state->fApp->window != NULL) {
+ if (state->fWindow) {
+ SkDELETE(state->fWindow);
+ application_term();
+ }
+
+ // drain any events that occurred before |window| was assigned.
+ while (SkEvent::ProcessEvent());
+
+ // Start normal Skia sequence
+ application_init();
+
+ SkTArray<const char*> args;
+ args.push_back("VisualBench");
+ for (int i = 0; i < state->fFlags.count(); i++) {
+ SkDebugf(state->fFlags[i].c_str());
+ args.push_back(state->fFlags[i].c_str());
+ }
+
+ state->fWindow = create_sk_window((void*)state->fApp->window,
+ args.count(),
+ const_cast<char**>(args.begin()));
+ }
+ break;
+ case APP_CMD_TERM_WINDOW:
+ SkDELETE(state->fWindow);
+ state->fWindow = NULL;
+ application_term();
+ break;
+ }
+}
+
+void android_main(struct android_app* state) {
+ struct VisualBenchState visualBenchState;
+
+ // Make sure glue isn't stripped.
+ app_dummy();
+
+ state->userData = &visualBenchState;
+ state->onAppCmd = handle_cmd;
+ visualBenchState.fApp = state;
+
+ // Get command line arguments
+ JavaVM* jvm = state->activity->vm;
+ JNIEnv *env;
+ jvm->AttachCurrentThread(&env, 0);
+
+ jobject me = state->activity->clazz;
+
+ jclass acl = env->GetObjectClass(me); //class pointer of NativeActivity
+ jmethodID giid = env->GetMethodID(acl, "getIntent", "()Landroid/content/Intent;");
+ jobject intent = env->CallObjectMethod(me, giid); //Got our intent
+
+ jclass icl = env->GetObjectClass(intent); //class pointer of Intent
+ jmethodID gseid = env->GetMethodID(icl, "getStringExtra",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+
+ jstring jsParam1 = (jstring)env->CallObjectMethod(intent, gseid,
+ env->NewStringUTF("cmdLineArguments"));
+ if (jsParam1) {
+ const char* flags = env->GetStringUTFChars(jsParam1, 0);
+ SkTArray<SkString> flagEntries;
+ SkStrSplit(flags, " ", &visualBenchState.fFlags);
+ env->ReleaseStringUTFChars(jsParam1, flags);
+ }
+ jvm->DetachCurrentThread();
+
+ while (1) {
+ // Read all pending events.
+ int ident;
+ int events;
+ struct android_poll_source* source;
+
+ // We loop until all events are read, then continue to draw the next frame of animation.
+ while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) {
+ // Process this event.
+ if (source != NULL) {
+ source->process(state, source);
+ }
+
+ // Check if we are exiting.
+ if (state->destroyRequested != 0) {
+ SkDELETE(visualBenchState.fWindow);
+ application_term();
+ return;
+ }
+ }
+
+ if (visualBenchState.fWindow) {
+ if (visualBenchState.fWindow->destroyRequested()) {
+ SkDELETE(visualBenchState.fWindow);
+ visualBenchState.fWindow = NULL;
+ application_term();
+ break;
+ }
+ visualBenchState.fWindow->update(NULL);
+ }
+ }
+ ANativeActivity_finish(state->activity);
+}
diff --git a/platform_tools/android/visualbench/project.properties b/platform_tools/android/visualbench/project.properties
new file mode 100644
index 0000000000..4ab125693c
--- /dev/null
+++ b/platform_tools/android/visualbench/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
diff --git a/platform_tools/android/visualbench/src/com/skia/VisualBenchActivity.java b/platform_tools/android/visualbench/src/com/skia/VisualBenchActivity.java
new file mode 100644
index 0000000000..00f2cb0df9
--- /dev/null
+++ b/platform_tools/android/visualbench/src/com/skia/VisualBenchActivity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+package com.skia;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+
+public class VisualBenchActivity extends android.app.NativeActivity {
+ static {
+ System.loadLibrary("skia_android");
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ if (!hasFocus) {
+ return;
+ }
+ getWindow().getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
+ View.SYSTEM_UI_FLAG_FULLSCREEN |// hide status bar
+ View.SYSTEM_UI_FLAG_IMMERSIVE);
+
+ // Disable backlight to keep the system as cool as possible
+ // TODO make this configurable
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+
+ WindowManager.LayoutParams lp = getWindow().getAttributes();
+ lp.screenBrightness = 0; // 0f - no backlight
+ getWindow().setAttributes(lp);
+ }
+}