| /* |
| * 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. |
| */ |
| enum State { |
| kInit_State, |
| kAnimate_State, |
| kDestroyRequested_State, |
| kFinished_State, |
| }; |
| |
| struct VisualBenchState { |
| VisualBenchState() : fApp(nullptr), fWindow(nullptr), fState(kInit_State) {} |
| struct android_app* fApp; |
| SkOSWindow* fWindow; |
| SkTArray<SkString> fFlags; |
| State fState; |
| }; |
| |
| 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 != nullptr && kInit_State == state->fState) { |
| // 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())); |
| state->fWindow->forceInvalAll(); |
| state->fState = kAnimate_State; |
| } |
| break; |
| case APP_CMD_TERM_WINDOW: |
| state->fState = kDestroyRequested_State; |
| 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("cmdLineFlags")); |
| if (jsParam1) { |
| const char* flags = env->GetStringUTFChars(jsParam1, 0); |
| 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, nullptr, &events, (void**)&source)) >= 0) { |
| // Process this event. |
| if (source != nullptr) { |
| source->process(state, source); |
| } |
| |
| // Check if we are exiting. |
| if (state->destroyRequested != 0) { |
| return; |
| } |
| |
| } |
| |
| if (visualBenchState.fWindow) { |
| if (visualBenchState.fWindow->destroyRequested()) { |
| visualBenchState.fState = kDestroyRequested_State; |
| } else { |
| visualBenchState.fWindow->update(nullptr); |
| } |
| } |
| |
| if (kDestroyRequested_State == visualBenchState.fState) { |
| delete visualBenchState.fWindow; |
| visualBenchState.fWindow = nullptr; |
| application_term(); |
| ANativeActivity_finish(state->activity); |
| visualBenchState.fState = kFinished_State; |
| } |
| } |
| } |