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