Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  *
      7  */
      8 
      9 #include <android_native_app_glue.h>
     10 
     11 #include "SkApplication.h"
     12 #include "VisualBench.h"
     13 
     14 /**
     15  * Shared state for our app.
     16  */
     17 enum State {
     18     kInit_State,
     19     kAnimate_State,
     20     kDestroyRequested_State,
     21     kFinished_State,
     22 };
     23 
     24 struct VisualBenchState {
     25     VisualBenchState() : fApp(nullptr), fWindow(nullptr), fState(kInit_State) {}
     26     struct android_app* fApp;
     27     SkOSWindow* fWindow;
     28     SkTArray<SkString> fFlags;
     29     State fState;
     30 };
     31 
     32 static void handle_cmd(struct android_app* app, int32_t cmd) {
     33     struct VisualBenchState* state = (struct VisualBenchState*)app->userData;
     34     switch (cmd) {
     35         case APP_CMD_INIT_WINDOW:
     36             // The window is being shown, get it ready.
     37             if (state->fApp->window != nullptr && kInit_State == state->fState) {
     38                 // drain any events that occurred before |window| was assigned.
     39                 while (SkEvent::ProcessEvent());
     40 
     41                 // Start normal Skia sequence
     42                 application_init();
     43 
     44                 SkTArray<const char*> args;
     45                 args.push_back("VisualBench");
     46                 for (int i = 0; i < state->fFlags.count(); i++) {
     47                     SkDebugf(state->fFlags[i].c_str());
     48                     args.push_back(state->fFlags[i].c_str());
     49                 }
     50 
     51                 state->fWindow = create_sk_window((void*)state->fApp->window,
     52                                                   args.count(),
     53                                                   const_cast<char**>(args.begin()));
     54                 state->fWindow->forceInvalAll();
     55                 state->fState = kAnimate_State;
     56             }
     57             break;
     58         case APP_CMD_TERM_WINDOW:
     59             state->fState = kDestroyRequested_State;
     60             break;
     61     }
     62 }
     63 
     64 void android_main(struct android_app* state) {
     65     struct VisualBenchState visualBenchState;
     66 
     67     // Make sure glue isn't stripped.
     68     app_dummy();
     69 
     70     state->userData = &visualBenchState;
     71     state->onAppCmd = handle_cmd;
     72     visualBenchState.fApp = state;
     73 
     74     // Get command line arguments
     75     JavaVM* jvm = state->activity->vm;
     76     JNIEnv *env;
     77     jvm->AttachCurrentThread(&env, 0);
     78 
     79     jobject me = state->activity->clazz;
     80 
     81     jclass acl = env->GetObjectClass(me); //class pointer of NativeActivity
     82     jmethodID giid = env->GetMethodID(acl, "getIntent", "()Landroid/content/Intent;");
     83     jobject intent = env->CallObjectMethod(me, giid); //Got our intent
     84 
     85     jclass icl = env->GetObjectClass(intent); //class pointer of Intent
     86     jmethodID gseid = env->GetMethodID(icl, "getStringExtra",
     87                                        "(Ljava/lang/String;)Ljava/lang/String;");
     88 
     89     jstring jsParam1 = (jstring)env->CallObjectMethod(intent, gseid,
     90                                                       env->NewStringUTF("cmdLineFlags"));
     91     if (jsParam1) {
     92         const char* flags = env->GetStringUTFChars(jsParam1, 0);
     93         SkStrSplit(flags, " ", &visualBenchState.fFlags);
     94         env->ReleaseStringUTFChars(jsParam1, flags);
     95     }
     96     jvm->DetachCurrentThread();
     97 
     98     while (1) {
     99         // Read all pending events.
    100         int ident;
    101         int events;
    102         struct android_poll_source* source;
    103 
    104         // We loop until all events are read, then continue to draw the next frame of animation.
    105         while ((ident=ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
    106             // Process this event.
    107             if (source != nullptr) {
    108                 source->process(state, source);
    109             }
    110 
    111             // Check if we are exiting.
    112             if (state->destroyRequested != 0) {
    113                 return;
    114             }
    115 
    116         }
    117 
    118         if (visualBenchState.fWindow) {
    119             if (visualBenchState.fWindow->destroyRequested()) {
    120                 visualBenchState.fState = kDestroyRequested_State;
    121             } else {
    122                 visualBenchState.fWindow->update(nullptr);
    123             }
    124         }
    125 
    126         if (kDestroyRequested_State == visualBenchState.fState) {
    127             delete visualBenchState.fWindow;
    128             visualBenchState.fWindow = nullptr;
    129             application_term();
    130             ANativeActivity_finish(state->activity);
    131             visualBenchState.fState = kFinished_State;
    132         }
    133     }
    134 }
    135