[android] Introduce android_benchmark_app (#8380)
author이한종/On-Device Lab(SR)/Engineer/삼성전자 <hanjoung.lee@samsung.com>
Fri, 25 Oct 2019 08:00:25 +0000 (17:00 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Fri, 25 Oct 2019 08:00:25 +0000 (17:00 +0900)
* [android] Introduce android_benchmark_app

This commit introduces an Android benchmark app for easy testing with an
actual Android visual app rather than running on shell.

The app contains minimal UI which consist of 2 buttons and few text
views to show results.

Signed-off-by: Hanjoung Lee <hanjoung.lee@samsung.com>
* Fixes

16 files changed:
Makefile.template
infra/nnfw/cmake/CfgOptionFlags.cmake
infra/nnfw/cmake/options/options_arm64-android.cmake
runtimes/contrib/android_benchmark_app/AndroidManifest.xml [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/CMakeLists.txt [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/README.md [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/cpp/ndk_main.cpp [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/cpp/ndk_main.h [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/java/com/ndk/tflbench/MainActivity.java [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/res/drawable-hdpi/ic_launcher.png [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/res/drawable-mdpi/ic_launcher.png [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/res/drawable-xhdpi/ic_launcher.png [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/res/drawable-xxhdpi/ic_launcher.png [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/res/layout/activity_main.xml [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/res/values-v21/styles.xml [new file with mode: 0644]
runtimes/contrib/android_benchmark_app/res/values/strings.xml [new file with mode: 0644]

index a120398..fcb24ea 100644 (file)
@@ -61,6 +61,22 @@ ifeq ($(TARGET_OS),android)
        OPTIONS+= -DNDK_DIR=$(NDK_DIR)
 endif
 
+ifneq ($(ANDROID_BUILD_TOOLS_DIR),)
+  OPTIONS+= -DANDROID_BUILD_TOOLS_DIR=$(ANDROID_BUILD_TOOLS_DIR)
+endif
+
+ifneq ($(ANDROID_SDK_DIR),)
+  OPTIONS+= -DANDROID_SDK_DIR=$(ANDROID_SDK_DIR)
+endif
+
+ifneq ($(TFLITE_MODEL_PATH),)
+  OPTIONS+= -DTFLITE_MODEL_PATH=$(TFLITE_MODEL_PATH)
+endif
+
+ifneq ($(ANDROID_BOOST_ROOT),)
+  OPTIONS+= -DANDROID_BOOST_ROOT=$(ANDROID_BOOST_ROOT)
+endif
+
 ifeq ($(PARALLEL_BUILD),1)
        # Get number of processors (linux only for now)
        ifeq ($(HOST_OS),linux)
index 80736e8..8f53ba2 100644 (file)
@@ -36,6 +36,7 @@ option(ENVVAR_NEURUN_CONFIG "Use environment variable for neurun configuration"
 # Default build configuration for contrib
 #
 option(BUILD_ANDROID_TFLITE "Enable android support for TensorFlow Lite" OFF)
+option(BUILD_ANDROID_BENCHMARK_APP "Enable Android Benchmark App" OFF)
 option(BUILD_BENCHMARK_ACL "Build ARM Compute Library Benchmarks" OFF)
 option(BUILD_DETECTION_APP "Build detection example app" OFF)
 option(BUILD_LABS "Build lab projects" OFF)
index 3064866..392375c 100644 (file)
@@ -5,6 +5,7 @@ option(BUILD_ARMCOMPUTE "Build ARM Compute from the downloaded source" OFF)
 # tensorflow-lite does not build BuiltinOpResolver but JNI lib need it
 # Related Issue : #1403
 option(BUILD_ANDROID_TFLITE "Enable android support for TensorFlow Lite" ON)
+option(BUILD_ANDROID_BENCHMARK_APP "Enable Android Benchmark App" ON)
 option(DOWNLOAD_NEON2SSE "Download NEON2SSE library source" OFF)
 # Need boost library
 option(BUILD_RUNTIME_NNAPI_TEST "Build Runtime NN API Generated Test" OFF)
diff --git a/runtimes/contrib/android_benchmark_app/AndroidManifest.xml b/runtimes/contrib/android_benchmark_app/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..f0b967c
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.ndk.tflbench" >
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.ndk.tflbench.MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/runtimes/contrib/android_benchmark_app/CMakeLists.txt b/runtimes/contrib/android_benchmark_app/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8e9d3c7
--- /dev/null
@@ -0,0 +1,97 @@
+if(NOT BUILD_ANDROID_BENCHMARK_APP)
+  return()
+endif(NOT BUILD_ANDROID_BENCHMARK_APP)
+
+if(NOT ANDROID)
+  message(STATUS "Sample app is disabled as non-Android build")
+  return()
+endif()
+
+if(NOT DEFINED ANDROID_BUILD_TOOLS_DIR)
+  message(STATUS "Sample app is disabled as ANDROID_BUILD_TOOLS_DIR is not defined")
+  return()
+endif()
+
+if(NOT DEFINED ANDROID_SDK_DIR)
+  message(STATUS "Sample app is disabled as ANDROID_SDK_DIR is not defined")
+  return()
+endif()
+
+if(NOT DEFINED TFLITE_MODEL_PATH)
+  message(STATUS "Sample app is disabled as TFLITE_MODEL_PATH is not defined")
+  return()
+endif()
+
+nnas_find_package(ARMCompute REQUIRED)
+
+if(NOT CORE_LIBRARY OR NOT RUNTIME_LIBRARY)
+  message(STATUS "Sample app is disabled as ARM Compute Library is missing")
+  return()
+endif()
+
+get_filename_component(TFLITE_MODEL_FILENAME ${TFLITE_MODEL_PATH} NAME)
+
+set(ANDROID_API_VERSION 27)
+set(ANDROID_PLATFORM_DIR ${ANDROID_SDK_DIR}/platforms/android-${ANDROID_API_VERSION})
+
+set(GEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/gen)
+set(OBJ_DIR ${CMAKE_CURRENT_BINARY_DIR}/obj)
+set(PKG_DIR ${CMAKE_CURRENT_BINARY_DIR}/pkg)
+set(LIB_DIR ${PKG_DIR}/lib/arm64-v8a)
+set(ASSETS_DIR ${PKG_DIR}/assets)
+set(SRC_LIST ${CMAKE_CURRENT_BINARY_DIR}/src.list)
+
+if (ANDROID_BOOST_ROOT)
+  set(BOOST_ROOT ${ANDROID_BOOST_ROOT})
+endif (ANDROID_BOOST_ROOT)
+
+nnas_find_package(Boost REQUIRED)
+
+add_library(android_benchmark_native SHARED cpp/ndk_main.cpp)
+target_compile_definitions(android_benchmark_native PRIVATE MODEL_NAME="${TFLITE_MODEL_FILENAME}")
+target_include_directories(android_benchmark_native PRIVATE ${NNAS_EXTERNALS_DIR}/tensorflow)
+target_include_directories(android_benchmark_native PRIVATE ${Boost_INCLUDE_DIRS})
+target_link_libraries(android_benchmark_native nnfw_lib_tflite)
+target_link_libraries(android_benchmark_native nnfw_lib_misc)
+target_link_libraries(android_benchmark_native log)
+
+nnfw_find_package(FlatBuffersSource REQUIRED)
+target_include_directories(android_benchmark_native PUBLIC ${FlatBuffersSource_DIR}/include .)
+
+add_custom_target(android-benchmark-apk ALL
+  COMMAND ${CMAKE_COMMAND} -E remove_directory ${GEN_DIR}
+  COMMAND ${CMAKE_COMMAND} -E make_directory ${GEN_DIR}
+  COMMAND ${ANDROID_BUILD_TOOLS_DIR}/aapt package -m -J ${GEN_DIR}
+                                                  -M ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml
+                                                  -S ${CMAKE_CURRENT_SOURCE_DIR}/res
+                                                  -I ${ANDROID_PLATFORM_DIR}/android.jar
+  COMMAND ${CMAKE_COMMAND} -E remove_directory ${OBJ_DIR}
+  COMMAND ${CMAKE_COMMAND} -E make_directory ${OBJ_DIR}
+  COMMAND ${CMAKE_COMMAND} -E remove -f ${SRC_LIST}
+  COMMAND find ${CMAKE_CURRENT_SOURCE_DIR}/java -name '*.java' >> ${SRC_LIST}
+  COMMAND find ${GEN_DIR} -name '*.java' >> ${SRC_LIST}
+  COMMAND javac -d ${OBJ_DIR} -source 1.7 -target 1.7 -bootclasspath "${JAVA_HOME}/jre/lib/rt.jar"
+                -classpath ${ANDROID_PLATFORM_DIR}/android.jar @${SRC_LIST}
+  COMMAND ${CMAKE_COMMAND} -E remove_directory ${PKG_DIR}
+  COMMAND ${CMAKE_COMMAND} -E make_directory ${PKG_DIR}
+  COMMAND ${CMAKE_COMMAND} -E make_directory ${ASSETS_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy ${TFLITE_MODEL_PATH} ${ASSETS_DIR}/model.tflite
+  COMMAND ${ANDROID_BUILD_TOOLS_DIR}/dx --dex --output=${PKG_DIR}/classes.dex ${OBJ_DIR}
+  COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy ${CORE_LIBRARY} ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy ${RUNTIME_LIBRARY} ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:android_benchmark_native> ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:neurun> ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:neurun_backend_acl_cl> ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:arm_compute_ex> ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:neurun_backend_acl_neon> ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:neurun_backend_cpu> ${LIB_DIR}
+  COMMAND ${CMAKE_COMMAND} -E echo ${ANDROID_BUILD_TOOLS_DIR}/aapt package -f -0 tflite -M ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml -S ${CMAKE_CURRENT_SOURCE_DIR}/res/ -I ${ANDROID_PLATFORM_DIR}/android.jar -F ${CMAKE_CURRENT_BINARY_DIR}/android-benchmark.unsigned.pkg ${PKG_DIR}
+  COMMAND ${ANDROID_BUILD_TOOLS_DIR}/aapt package -f
+                                                  -0 tflite
+                                                  -M ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml
+                                                  -S ${CMAKE_CURRENT_SOURCE_DIR}/res/
+                                                  -I ${ANDROID_PLATFORM_DIR}/android.jar
+                                                  -F ${CMAKE_CURRENT_BINARY_DIR}/android-benchmark.unsigned.pkg
+                                                  ${PKG_DIR}
+  DEPENDS android_benchmark_native neurun neurun_backend_acl_cl neurun_backend_acl_neon neurun_backend_cpu)
diff --git a/runtimes/contrib/android_benchmark_app/README.md b/runtimes/contrib/android_benchmark_app/README.md
new file mode 100644 (file)
index 0000000..d53a56c
--- /dev/null
@@ -0,0 +1,58 @@
+# Android Benchmark App
+
+An Android sample app that run `.tflite` and measure performance.
+
+You can run with two engines.
+
+- Tensorflow Lite Interpreter
+- NN API Delegate (neurun)
+
+## Build
+
+In addition to arm64-Android build, you need to specify more parameters.
+
+- `ANDROID_BUILD_TOOLS_DIR` : Android `build-tools` directory (You may find it in Android SDK directory)
+- `ANDROID_SDK_DIR` : Android SDK directory
+- `TFLITE_MODEL_PATH` : A model to run (Only one model can be packed)
+- `ANDROID_BOOST_ROOT` : Boost library root path
+    - This repo should contain `lib` and `include` directory
+    - How to build Boost for Android - Build with [this repo](https://github.com/moritz-wundke/Boost-for-Android)
+
+Example:
+
+```bash
+make TARGET_ARCH=arm64 \
+    CROSS_BUILD=1 \
+    BUILD_TYPE=RELEASE \
+    NDK_DIR=/home/hanjoung/ws/android-tools/r20/ndk \
+    EXT_ACL_FOLDER=/home/hanjoung/ws/temp/arm_compute-v19.05-bin-android/lib/android-arm64-v8a-neon-cl \
+    ANDROID_BUILD_TOOLS_DIR=/home/hanjoung/ws/android-tools/sdk/build-tools/27.0.3/ \
+    ANDROID_SDK_DIR=/home/hanjoung/ws/android-tools/sdk \
+    TFLITE_MODEL_PATH=/Users/hanjoung/ws/ghent/STAR/nnfw/tests/framework/cache/MODELS/mobilenet/mobilenet_v1_0.25_128.tflite \
+    ANDROID_BOOST_ROOT=/home/hanjoung/ws/gh/moritz-wundke/Boost-for-Android/build/out/arm64-v8a
+```
+
+And you will get `obj/contrib/android_benchmark_app/android-benchmark.unsigned.pkg`. This is an unsigned Android app package.
+
+## Sign APK
+
+Before installing the package you probably need to sign the package.
+
+- `apksigner` : This is in `build-tools` directory
+- Your keystore : How-to is TBD
+
+```bash
+apksigner sign \
+    --ks ~/.android/debug.keystore \
+    --in Product/arm64-android.release/obj/contrib/android_benchmark_app/android-benchmark.unsigned.pkg \
+    --out tflbench.apk
+```
+
+You should enter the keystore password. Then you will get `tflbench.apk`.
+
+## Install APK
+
+```bash
+adb install tflbench.apk
+adb uninstall com.ndk.tflbench # To uninstall
+```
diff --git a/runtimes/contrib/android_benchmark_app/cpp/ndk_main.cpp b/runtimes/contrib/android_benchmark_app/cpp/ndk_main.cpp
new file mode 100644 (file)
index 0000000..f2ca131
--- /dev/null
@@ -0,0 +1,228 @@
+#include "ndk_main.h"
+
+#include "tensorflow/lite/kernels/register.h"
+#include "tensorflow/lite/model.h"
+
+#include "tflite/Assert.h"
+#include "tflite/Session.h"
+#include "tflite/InterpreterSession.h"
+#include "tflite/NNAPISession.h"
+#include "tflite/ext/kernels/register.h"
+
+#include "misc/benchmark.h"
+
+#include <boost/accumulators/accumulators.hpp>
+#include <boost/accumulators/statistics/stats.hpp>
+#include <boost/accumulators/statistics/mean.hpp>
+#include <boost/accumulators/statistics/min.hpp>
+#include <boost/accumulators/statistics/max.hpp>
+
+#include <cassert>
+#include <chrono>
+#include <sstream>
+
+#include <android/log.h>
+
+using namespace tflite;
+using namespace tflite::ops::builtin;
+
+static StderrReporter error_reporter;
+
+static std::unique_ptr<FlatBufferModel> model;
+
+inline void setText(JNIEnv *env, jobject thisObj, const std::string &message)
+{
+  jclass thisClass = env->GetObjectClass(thisObj);
+  jmethodID setTextMethod = env->GetMethodID(thisClass, "setText", "(Ljava/lang/String;)V");
+
+  assert(setTextMethod != nullptr);
+
+  env->CallVoidMethod(thisObj, setTextMethod, env->NewStringUTF(message.c_str()));
+}
+
+inline void setTitle(JNIEnv *env, jobject thisObj, const std::string &message)
+{
+  jclass thisClass = env->GetObjectClass(thisObj);
+  jmethodID setTextMethod = env->GetMethodID(thisClass, "setTitle", "(Ljava/lang/String;)V");
+
+  assert(setTextMethod != nullptr);
+
+  env->CallVoidMethod(thisObj, setTextMethod, env->NewStringUTF(message.c_str()));
+
+  // Clear message
+  setText(env, thisObj, "");
+}
+
+inline void setText(JNIEnv *env, jobject thisObj, const std::stringstream &ss)
+{
+  setText(env, thisObj, ss.str());
+}
+
+inline std::unique_ptr<FlatBufferModel> loadModel(JNIEnv *env, jobject thisObj,
+                                                  jobject model_buffer)
+{
+  const char *model_base = static_cast<char *>(env->GetDirectBufferAddress(model_buffer));
+  jlong model_size = env->GetDirectBufferCapacity(model_buffer);
+
+  return FlatBufferModel::BuildFromBuffer(model_base, static_cast<size_t>(model_size),
+                                          &error_reporter);
+}
+
+struct Activity
+{
+  virtual ~Activity() = default;
+
+  virtual void prepare(void) const = 0;
+  virtual void run(void) const = 0;
+  virtual void teardown(void) const = 0;
+};
+
+struct LiteActivity final : public Activity
+{
+public:
+  LiteActivity(nnfw::tflite::Session &sess) : _sess(sess)
+  {
+    // DO NOTHING
+  }
+
+public:
+  void prepare(void) const override { _sess.prepare(); }
+  void run(void) const override { _sess.run(); }
+  void teardown(void) const override { _sess.teardown(); }
+
+private:
+  nnfw::tflite::Session &_sess;
+};
+
+struct SimpleActivity final : public Activity
+{
+public:
+  SimpleActivity(const std::function<void(void)> &fn) : _fn{fn}
+  {
+    // DO NOTHING
+  }
+
+public:
+  void prepare(void) const override {}
+  void run(void) const override { _fn(); }
+  void teardown(void) const override {}
+
+private:
+  std::function<void(void)> _fn;
+};
+
+inline void runBenchmark(JNIEnv *env, jobject thisObj, Activity &act)
+{
+  auto runTrial = [&](void) {
+    std::chrono::milliseconds elapsed(0);
+
+    act.prepare();
+    nnfw::misc::benchmark::measure(elapsed) << [&](void) { act.run(); };
+    act.teardown();
+
+    return elapsed;
+  };
+
+  // Warm-up
+  for (uint32_t n = 0; n < 3; ++n)
+  {
+    auto elapsed = runTrial();
+
+    std::stringstream ss;
+    ss << "Warm-up #" << n << "  takes " << elapsed.count() << "ms" << std::endl;
+    setText(env, thisObj, ss);
+  }
+
+  // Measure
+  using namespace boost::accumulators;
+
+  accumulator_set<double, stats<tag::mean, tag::min, tag::max>> acc;
+
+  for (uint32_t n = 0; n < 100; ++n)
+  {
+    auto elapsed = runTrial();
+
+    std::stringstream ss;
+    ss << "Iteration #" << n << " takes " << elapsed.count() << "ms" << std::endl;
+    setText(env, thisObj, ss);
+
+    acc(elapsed.count());
+  }
+
+  std::stringstream ss;
+  ss << "Average is " << mean(acc) << "ms" << std::endl;
+  ss << "Min is " << min(acc) << "ms" << std::endl;
+  ss << "Max is " << max(acc) << "ms" << std::endl;
+  setText(env, thisObj, ss);
+}
+
+JNIEXPORT void JNICALL Java_com_ndk_tflbench_MainActivity_runInterpreterBenchmark(
+    JNIEnv *env, jobject thisObj, jobject model_buffer)
+{
+  setTitle(env, thisObj, "Running Interpreter Benchmark");
+
+  auto model = loadModel(env, thisObj, model_buffer);
+  assert(model != nullptr);
+
+  nnfw::tflite::BuiltinOpResolver resolver;
+  InterpreterBuilder builder(*model, resolver);
+
+  std::unique_ptr<Interpreter> interpreter;
+
+  TFLITE_ENSURE(builder(&interpreter));
+
+  interpreter->SetNumThreads(-1);
+
+  nnfw::tflite::InterpreterSession sess(interpreter.get());
+  LiteActivity act{sess};
+  runBenchmark(env, thisObj, act);
+}
+
+static void runNNAPIBenchmark(JNIEnv *env, jobject thisObj, jobject model_buffer)
+{
+  auto model = loadModel(env, thisObj, model_buffer);
+  assert(model != nullptr);
+
+  nnfw::tflite::BuiltinOpResolver resolver;
+  InterpreterBuilder builder(*model, resolver);
+
+  std::unique_ptr<Interpreter> interpreter;
+
+  TFLITE_ENSURE(builder(&interpreter));
+
+  nnfw::tflite::NNAPISession sess(interpreter.get());
+  LiteActivity act{sess};
+  runBenchmark(env, thisObj, act);
+}
+
+JNIEXPORT void JNICALL Java_com_ndk_tflbench_MainActivity_runNNAPIBenchmark(JNIEnv *env,
+                                                                            jobject thisObj,
+                                                                            jobject model_buffer)
+{
+  setTitle(env, thisObj, "Running NNAPI Benchmark");
+
+  try
+  {
+    runNNAPIBenchmark(env, thisObj, model_buffer);
+  }
+  catch (const std::exception &ex)
+  {
+    std::stringstream ss;
+    ss << "Caught an exception " << ex.what();
+    setText(env, thisObj, ss);
+  }
+}
+
+JNIEXPORT jstring JNICALL Java_com_ndk_tflbench_MainActivity_getModelName(JNIEnv *env,
+                                                                          jobject thisObj)
+{
+  return env->NewStringUTF(MODEL_NAME);
+}
+
+#define TF_ENSURE(e)                               \
+  {                                                \
+    if (!(e).ok())                                 \
+    {                                              \
+      throw std::runtime_error{"'" #e "' FAILED"}; \
+    }                                              \
+  }
diff --git a/runtimes/contrib/android_benchmark_app/cpp/ndk_main.h b/runtimes/contrib/android_benchmark_app/cpp/ndk_main.h
new file mode 100644 (file)
index 0000000..8de39ce
--- /dev/null
@@ -0,0 +1,92 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_ndk_tflbench_MainActivity */
+
+#ifndef _Included_com_ndk_tflbench_MainActivity
+#define _Included_com_ndk_tflbench_MainActivity
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_ndk_tflbench_MainActivity_BIND_ABOVE_CLIENT
+#define com_ndk_tflbench_MainActivity_BIND_ABOVE_CLIENT 8L
+#undef com_ndk_tflbench_MainActivity_BIND_ADJUST_WITH_ACTIVITY
+#define com_ndk_tflbench_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L
+#undef com_ndk_tflbench_MainActivity_BIND_ALLOW_OOM_MANAGEMENT
+#define com_ndk_tflbench_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L
+#undef com_ndk_tflbench_MainActivity_BIND_AUTO_CREATE
+#define com_ndk_tflbench_MainActivity_BIND_AUTO_CREATE 1L
+#undef com_ndk_tflbench_MainActivity_BIND_DEBUG_UNBIND
+#define com_ndk_tflbench_MainActivity_BIND_DEBUG_UNBIND 2L
+#undef com_ndk_tflbench_MainActivity_BIND_EXTERNAL_SERVICE
+#define com_ndk_tflbench_MainActivity_BIND_EXTERNAL_SERVICE -2147483648L
+#undef com_ndk_tflbench_MainActivity_BIND_IMPORTANT
+#define com_ndk_tflbench_MainActivity_BIND_IMPORTANT 64L
+#undef com_ndk_tflbench_MainActivity_BIND_NOT_FOREGROUND
+#define com_ndk_tflbench_MainActivity_BIND_NOT_FOREGROUND 4L
+#undef com_ndk_tflbench_MainActivity_BIND_WAIVE_PRIORITY
+#define com_ndk_tflbench_MainActivity_BIND_WAIVE_PRIORITY 32L
+#undef com_ndk_tflbench_MainActivity_CONTEXT_IGNORE_SECURITY
+#define com_ndk_tflbench_MainActivity_CONTEXT_IGNORE_SECURITY 2L
+#undef com_ndk_tflbench_MainActivity_CONTEXT_INCLUDE_CODE
+#define com_ndk_tflbench_MainActivity_CONTEXT_INCLUDE_CODE 1L
+#undef com_ndk_tflbench_MainActivity_CONTEXT_RESTRICTED
+#define com_ndk_tflbench_MainActivity_CONTEXT_RESTRICTED 4L
+#undef com_ndk_tflbench_MainActivity_MODE_APPEND
+#define com_ndk_tflbench_MainActivity_MODE_APPEND 32768L
+#undef com_ndk_tflbench_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING
+#define com_ndk_tflbench_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L
+#undef com_ndk_tflbench_MainActivity_MODE_MULTI_PROCESS
+#define com_ndk_tflbench_MainActivity_MODE_MULTI_PROCESS 4L
+#undef com_ndk_tflbench_MainActivity_MODE_NO_LOCALIZED_COLLATORS
+#define com_ndk_tflbench_MainActivity_MODE_NO_LOCALIZED_COLLATORS 16L
+#undef com_ndk_tflbench_MainActivity_MODE_PRIVATE
+#define com_ndk_tflbench_MainActivity_MODE_PRIVATE 0L
+#undef com_ndk_tflbench_MainActivity_MODE_WORLD_READABLE
+#define com_ndk_tflbench_MainActivity_MODE_WORLD_READABLE 1L
+#undef com_ndk_tflbench_MainActivity_MODE_WORLD_WRITEABLE
+#define com_ndk_tflbench_MainActivity_MODE_WORLD_WRITEABLE 2L
+#undef com_ndk_tflbench_MainActivity_RECEIVER_VISIBLE_TO_INSTANT_APPS
+#define com_ndk_tflbench_MainActivity_RECEIVER_VISIBLE_TO_INSTANT_APPS 1L
+#undef com_ndk_tflbench_MainActivity_DEFAULT_KEYS_DIALER
+#define com_ndk_tflbench_MainActivity_DEFAULT_KEYS_DIALER 1L
+#undef com_ndk_tflbench_MainActivity_DEFAULT_KEYS_DISABLE
+#define com_ndk_tflbench_MainActivity_DEFAULT_KEYS_DISABLE 0L
+#undef com_ndk_tflbench_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL
+#define com_ndk_tflbench_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L
+#undef com_ndk_tflbench_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL
+#define com_ndk_tflbench_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L
+#undef com_ndk_tflbench_MainActivity_DEFAULT_KEYS_SHORTCUT
+#define com_ndk_tflbench_MainActivity_DEFAULT_KEYS_SHORTCUT 2L
+#undef com_ndk_tflbench_MainActivity_RESULT_CANCELED
+#define com_ndk_tflbench_MainActivity_RESULT_CANCELED 0L
+#undef com_ndk_tflbench_MainActivity_RESULT_FIRST_USER
+#define com_ndk_tflbench_MainActivity_RESULT_FIRST_USER 1L
+#undef com_ndk_tflbench_MainActivity_RESULT_OK
+#define com_ndk_tflbench_MainActivity_RESULT_OK -1L
+/*
+ * Class:     com_ndk_tflbench_MainActivity
+ * Method:    getModelName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_ndk_tflbench_MainActivity_getModelName(JNIEnv *, jobject);
+
+/*
+ * Class:     com_ndk_tflbench_MainActivity
+ * Method:    runInterpreterBenchmark
+ * Signature: (Ljava/nio/MappedByteBuffer;)V
+ */
+JNIEXPORT void JNICALL Java_com_ndk_tflbench_MainActivity_runInterpreterBenchmark(JNIEnv *, jobject,
+                                                                                  jobject);
+
+/*
+ * Class:     com_ndk_tflbench_MainActivity
+ * Method:    runNNAPIBenchmark
+ * Signature: (Ljava/nio/MappedByteBuffer;)V
+ */
+JNIEXPORT void JNICALL Java_com_ndk_tflbench_MainActivity_runNNAPIBenchmark(JNIEnv *, jobject,
+                                                                            jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/runtimes/contrib/android_benchmark_app/java/com/ndk/tflbench/MainActivity.java b/runtimes/contrib/android_benchmark_app/java/com/ndk/tflbench/MainActivity.java
new file mode 100644 (file)
index 0000000..14bf239
--- /dev/null
@@ -0,0 +1,110 @@
+package com.ndk.tflbench;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.content.Intent;
+import android.view.View;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.TextView;
+import android.widget.Button;
+import android.net.Uri;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.graphics.Bitmap;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.util.Log;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Vector;
+
+public class MainActivity extends Activity {
+
+  static {
+    System.loadLibrary("android_benchmark_native");
+  }
+
+  private void setModel(final String message) {
+    final TextView textView = (TextView)findViewById(R.id.model_label);
+    runOnUiThread(new Runnable() {
+      @Override
+      public void run() { textView.setText(message); }
+    });
+  }
+
+  private void setTitle(final String message) {
+    final TextView textView = (TextView)findViewById(R.id.title_label);
+    runOnUiThread(new Runnable() {
+      @Override
+      public void run() { textView.setText(message); }
+    });
+  }
+
+  private void setText(final String message) {
+    final TextView textView = (TextView)findViewById(R.id.message_label);
+    runOnUiThread(new Runnable() {
+      @Override
+      public void run() { textView.setText(message); }
+    });
+  }
+
+  private MappedByteBuffer buffer;
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.activity_main);
+
+    setModel(getModelName());
+
+    // Load Tensorflow Lite model
+    try
+    {
+      AssetManager assets = getAssets();
+      AssetFileDescriptor fileDescriptor = assets.openFd("model.tflite");
+      FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
+      FileChannel fileChannel = inputStream.getChannel();
+      final long startOffset = fileDescriptor.getStartOffset();
+      final long declaredLength = fileDescriptor.getDeclaredLength();
+
+      buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
+    } catch (IOException e) {
+      Log.e("MYAPP", "exception", e);
+    }
+
+    Button btn_interp = (Button)findViewById(R.id.button_interp);
+    btn_interp.setOnClickListener(new Button.OnClickListener() {
+      @Override public void onClick(View view) {
+        new Thread(new Runnable() {
+          @Override
+          public void run() { runInterpreterBenchmark(buffer); }
+        }).start();
+      }
+    });
+
+    Button btn_nnapi = (Button)findViewById(R.id.button_nnapi);
+    btn_nnapi.setOnClickListener(new Button.OnClickListener() {
+      @Override public void onClick(View view) {
+        new Thread(new Runnable() {
+          @Override
+          public void run() { runNNAPIBenchmark(buffer); }
+        }).start();
+      }
+    });
+  }
+
+  public native String getModelName();
+  public native void runInterpreterBenchmark(MappedByteBuffer buffer);
+  public native void runNNAPIBenchmark(MappedByteBuffer buffer);
+}
diff --git a/runtimes/contrib/android_benchmark_app/res/drawable-hdpi/ic_launcher.png b/runtimes/contrib/android_benchmark_app/res/drawable-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..96a442e
Binary files /dev/null and b/runtimes/contrib/android_benchmark_app/res/drawable-hdpi/ic_launcher.png differ
diff --git a/runtimes/contrib/android_benchmark_app/res/drawable-mdpi/ic_launcher.png b/runtimes/contrib/android_benchmark_app/res/drawable-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..359047d
Binary files /dev/null and b/runtimes/contrib/android_benchmark_app/res/drawable-mdpi/ic_launcher.png differ
diff --git a/runtimes/contrib/android_benchmark_app/res/drawable-xhdpi/ic_launcher.png b/runtimes/contrib/android_benchmark_app/res/drawable-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..71c6d76
Binary files /dev/null and b/runtimes/contrib/android_benchmark_app/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/runtimes/contrib/android_benchmark_app/res/drawable-xxhdpi/ic_launcher.png b/runtimes/contrib/android_benchmark_app/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..4df1894
Binary files /dev/null and b/runtimes/contrib/android_benchmark_app/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/runtimes/contrib/android_benchmark_app/res/layout/activity_main.xml b/runtimes/contrib/android_benchmark_app/res/layout/activity_main.xml
new file mode 100644 (file)
index 0000000..5519525
--- /dev/null
@@ -0,0 +1,38 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  xmlns:tools="http://schemas.android.com/tools"
+  android:layout_width="match_parent"
+  android:layout_height="match_parent"
+  android:orientation="vertical">
+
+  <Button android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:id="@+id/button_interp"
+          android:text="Run Interp benchmark"/>
+
+  <Button android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:id="@+id/button_nnapi"
+          android:text="Run NNAPI benchmark"/>
+
+  <TextView android:text=""
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:id="@+id/model_label"
+            android:layout_centerHorizontal="true"
+            android:textSize="16dp"/>
+
+  <TextView android:text=""
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:id="@+id/title_label"
+            android:layout_centerHorizontal="true"
+            android:textSize="16dp"/>
+
+  <TextView android:text=""
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:id="@+id/message_label"
+            android:layout_centerHorizontal="true"
+            android:textSize="16dp"/>
+
+</LinearLayout>
diff --git a/runtimes/contrib/android_benchmark_app/res/values-v21/styles.xml b/runtimes/contrib/android_benchmark_app/res/values-v21/styles.xml
new file mode 100644 (file)
index 0000000..dba3c41
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="AppTheme" parent="android:Theme.Material.Light">
+    </style>
+</resources>
diff --git a/runtimes/contrib/android_benchmark_app/res/values/strings.xml b/runtimes/contrib/android_benchmark_app/res/values/strings.xml
new file mode 100644 (file)
index 0000000..3c6c4aa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+  <string name="app_name">T/F Lite Benchmark</string>
+
+</resources>