• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #include "agq.h"
19 #include "circle.h"
20 #include "common.h"
21 #include "renderer.h"
22 #include "vecmath.h"
23 
24 #include <cassert>
25 #include <chrono>
26 #include <cinttypes>
27 #include <cstdlib>
28 #include <cstring>
29 #include <errno.h>
30 #include <initializer_list>
31 #include <jni.h>
32 #include <memory>
33 #include <sys/time.h>
34 #include <vector>
35 
36 #include <EGL/egl.h>
37 #include <EGL/eglext.h>
38 
39 #include <android/sensor.h>
40 #include <android/log.h>
41 #include <android_native_app_glue.h>
42 
43 using namespace std::chrono_literals;
44 using namespace android::gamecore;
45 
46 namespace {
47 
48 int animating = 0;
49 
50 /**
51  * Process the next input event.
52  */
engine_handle_input(struct android_app *,AInputEvent * event)53 int32_t engine_handle_input(struct android_app*, AInputEvent* event) {
54     if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
55         animating = 1;
56         return 1;
57     }
58     return 0;
59 }
60 
61 /**
62  * Process the next main command.
63  */
engine_handle_cmd(struct android_app * app,int32_t cmd)64 void engine_handle_cmd(struct android_app* app, int32_t cmd) {
65     //struct engine* engine = (struct engine*)app->userData;
66     Renderer* renderer = reinterpret_cast<Renderer*>(app->userData);
67 
68     switch (cmd) {
69         case APP_CMD_SAVE_STATE:
70             // We are not saving the state.
71             break;
72         case APP_CMD_INIT_WINDOW:
73             // The window is being shown, get it ready.
74             if (app->window != NULL) {
75                 renderer->initDisplay(app->window);
76                 renderer->draw();
77                 animating = 1;
78             }
79             break;
80         case APP_CMD_TERM_WINDOW:
81             // The window is being hidden or closed, clean it up.
82             //engine_term_display(engine);
83             renderer->terminateDisplay();
84             animating = 0;
85             break;
86         case APP_CMD_LOST_FOCUS:
87             // Also stop animating.
88             animating = 0;
89             renderer->draw();
90             break;
91         default:
92             break;
93     }
94 }
95 
96 } // end of anonymous namespace
97 
98 /**
99  * This is the main entry point of a native application that is using
100  * android_native_app_glue.  It runs in its own thread, with its own
101  * event loop for receiving input events and doing other things.
102  */
android_main(struct android_app * state)103 void android_main(struct android_app* state) {
104     std::srand(0);
105 
106     LOGI("Running with SDK %d", state->activity->sdkVersion);
107 
108     std::unique_ptr<Renderer> renderer(new Renderer(1));
109     state->userData = renderer.get();
110     state->onAppCmd = engine_handle_cmd;
111     state->onInputEvent = engine_handle_input;
112 
113     // loop waiting for stuff to do.
114     while (1) {
115         // Read all pending events.
116         int events;
117         struct android_poll_source* source;
118 
119         // If not animating, we will block forever waiting for events.
120         // If animating, we loop until all events are read, then continue
121         // to draw the next frame of animation.
122         while (ALooper_pollAll(animating ? 0 : -1, NULL, &events, (void**)&source) >= 0) {
123 
124             // Process this event.
125             if (source != NULL) {
126                 source->process(state, source);
127             }
128 
129             // Check if we are exiting.
130             if (state->destroyRequested != 0) {
131                 renderer->terminateDisplay();
132                 return;
133             }
134         }
135 
136         if (animating) {
137             renderer->update();
138 
139             // Drawing is throttled to the screen update rate, so there
140             // is no need to do timing here.
141             renderer->draw();
142 
143             // Broadcast intent every 5 seconds.
144             static auto last_timestamp = std::chrono::steady_clock::now();
145             auto now = std::chrono::steady_clock::now();
146             if (now - last_timestamp >= std::chrono::seconds(5)) {
147                 last_timestamp = now;
148                 android::GameQualification qualification;
149                 qualification.startLoop(state->activity);
150             }
151         }
152     }
153 }
154