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 <memory>
32 #include <sys/time.h>
33 #include <vector>
34
35 #include <EGL/egl.h>
36 #include <EGL/eglext.h>
37
38 #include <android/sensor.h>
39 #include <android/log.h>
40 #include <android_native_app_glue.h>
41
42 using namespace std::chrono_literals;
43 using namespace android::gamecore;
44
45 namespace {
46
47 int animating = 0;
48
49 /**
50 * Process the next input event.
51 */
engine_handle_input(struct android_app *,AInputEvent * event)52 int32_t engine_handle_input(struct android_app*, AInputEvent* event) {
53 if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
54 animating = 1;
55 return 1;
56 }
57 return 0;
58 }
59
60 /**
61 * Process the next main command.
62 */
engine_handle_cmd(struct android_app * app,int32_t cmd)63 void engine_handle_cmd(struct android_app* app, int32_t cmd) {
64 //struct engine* engine = (struct engine*)app->userData;
65 Renderer* renderer = reinterpret_cast<Renderer*>(app->userData);
66
67 switch (cmd) {
68 case APP_CMD_SAVE_STATE:
69 // We are not saving the state.
70 break;
71 case APP_CMD_INIT_WINDOW:
72 // The window is being shown, get it ready.
73 if (app->window != NULL) {
74 renderer->initDisplay(app->window);
75 renderer->draw();
76 animating = 1;
77 }
78 break;
79 case APP_CMD_TERM_WINDOW:
80 // The window is being hidden or closed, clean it up.
81 //engine_term_display(engine);
82 renderer->terminateDisplay();
83 animating = 0;
84 break;
85 case APP_CMD_LOST_FOCUS:
86 // Also stop animating.
87 animating = 0;
88 renderer->draw();
89 break;
90 default:
91 break;
92 }
93 }
94
95 } // end of anonymous namespace
96
97 /**
98 * This is the main entry point of a native application that is using
99 * android_native_app_glue. It runs in its own thread, with its own
100 * event loop for receiving input events and doing other things.
101 */
android_main(struct android_app * state)102 void android_main(struct android_app* state) {
103 std::srand(0);
104
105 LOGI("Running with SDK %d", state->activity->sdkVersion);
106
107 std::unique_ptr<Renderer> renderer(new Renderer(1));
108 state->userData = renderer.get();
109 state->onAppCmd = engine_handle_cmd;
110 state->onInputEvent = engine_handle_input;
111
112 // loop waiting for stuff to do.
113 while (1) {
114 // Read all pending events.
115 int events;
116 struct android_poll_source* source;
117
118 // If not animating, we will block forever waiting for events.
119 // If animating, we loop until all events are read, then continue
120 // to draw the next frame of animation.
121 while (ALooper_pollAll(animating ? 0 : -1, NULL, &events, (void**)&source) >= 0) {
122
123 // Process this event.
124 if (source != NULL) {
125 source->process(state, source);
126 }
127
128 // Check if we are exiting.
129 if (state->destroyRequested != 0) {
130 renderer->terminateDisplay();
131 return;
132 }
133 }
134
135 if (animating) {
136 renderer->update();
137
138 // Drawing is throttled to the screen update rate, so there
139 // is no need to do timing here.
140 renderer->draw();
141
142 // Broadcast intent every 5 seconds.
143 static auto last_timestamp = std::chrono::steady_clock::now();
144 auto now = std::chrono::steady_clock::now();
145 if (now - last_timestamp >= std::chrono::seconds(5)) {
146 last_timestamp = now;
147 android::GameQualification qualification;
148 qualification.startLoop(state->activity);
149 }
150 }
151 }
152 }
153