Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/util/android/third_party/android_native_app_glue.c
1694 views
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 <jni.h>
19
20
#include <errno.h>
21
#include <stdlib.h>
22
#include <string.h>
23
#include <unistd.h>
24
#include <sys/resource.h>
25
26
#include "android_native_app_glue.h"
27
#include <android/log.h>
28
29
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
30
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
31
32
/* For debug builds, always enable the debug traces in this library */
33
#ifndef NDEBUG
34
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
35
#else
36
# define LOGV(...) ((void)0)
37
#endif
38
39
static void free_saved_state(struct android_app* android_app) {
40
pthread_mutex_lock(&android_app->mutex);
41
if (android_app->savedState != NULL) {
42
free(android_app->savedState);
43
android_app->savedState = NULL;
44
android_app->savedStateSize = 0;
45
}
46
pthread_mutex_unlock(&android_app->mutex);
47
}
48
49
int8_t android_app_read_cmd(struct android_app* android_app) {
50
int8_t cmd;
51
if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
52
switch (cmd) {
53
case APP_CMD_SAVE_STATE:
54
free_saved_state(android_app);
55
break;
56
}
57
return cmd;
58
} else {
59
LOGE("No data on command pipe!");
60
}
61
return -1;
62
}
63
64
static void print_cur_config(struct android_app* android_app) {
65
char lang[2], country[2];
66
AConfiguration_getLanguage(android_app->config, lang);
67
AConfiguration_getCountry(android_app->config, country);
68
69
LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
70
"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
71
"modetype=%d modenight=%d",
72
AConfiguration_getMcc(android_app->config),
73
AConfiguration_getMnc(android_app->config),
74
lang[0], lang[1], country[0], country[1],
75
AConfiguration_getOrientation(android_app->config),
76
AConfiguration_getTouchscreen(android_app->config),
77
AConfiguration_getDensity(android_app->config),
78
AConfiguration_getKeyboard(android_app->config),
79
AConfiguration_getNavigation(android_app->config),
80
AConfiguration_getKeysHidden(android_app->config),
81
AConfiguration_getNavHidden(android_app->config),
82
AConfiguration_getSdkVersion(android_app->config),
83
AConfiguration_getScreenSize(android_app->config),
84
AConfiguration_getScreenLong(android_app->config),
85
AConfiguration_getUiModeType(android_app->config),
86
AConfiguration_getUiModeNight(android_app->config));
87
}
88
89
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
90
switch (cmd) {
91
case APP_CMD_INPUT_CHANGED:
92
LOGV("APP_CMD_INPUT_CHANGED\n");
93
pthread_mutex_lock(&android_app->mutex);
94
if (android_app->inputQueue != NULL) {
95
AInputQueue_detachLooper(android_app->inputQueue);
96
}
97
android_app->inputQueue = android_app->pendingInputQueue;
98
if (android_app->inputQueue != NULL) {
99
LOGV("Attaching input queue to looper");
100
AInputQueue_attachLooper(android_app->inputQueue,
101
android_app->looper, LOOPER_ID_INPUT, NULL,
102
&android_app->inputPollSource);
103
}
104
pthread_cond_broadcast(&android_app->cond);
105
pthread_mutex_unlock(&android_app->mutex);
106
break;
107
108
case APP_CMD_INIT_WINDOW:
109
LOGV("APP_CMD_INIT_WINDOW\n");
110
pthread_mutex_lock(&android_app->mutex);
111
android_app->window = android_app->pendingWindow;
112
pthread_cond_broadcast(&android_app->cond);
113
pthread_mutex_unlock(&android_app->mutex);
114
break;
115
116
case APP_CMD_TERM_WINDOW:
117
LOGV("APP_CMD_TERM_WINDOW\n");
118
pthread_cond_broadcast(&android_app->cond);
119
break;
120
121
case APP_CMD_RESUME:
122
case APP_CMD_START:
123
case APP_CMD_PAUSE:
124
case APP_CMD_STOP:
125
LOGV("activityState=%d\n", cmd);
126
pthread_mutex_lock(&android_app->mutex);
127
android_app->activityState = cmd;
128
pthread_cond_broadcast(&android_app->cond);
129
pthread_mutex_unlock(&android_app->mutex);
130
break;
131
132
case APP_CMD_CONFIG_CHANGED:
133
LOGV("APP_CMD_CONFIG_CHANGED\n");
134
AConfiguration_fromAssetManager(android_app->config,
135
android_app->activity->assetManager);
136
print_cur_config(android_app);
137
break;
138
139
case APP_CMD_DESTROY:
140
LOGV("APP_CMD_DESTROY\n");
141
android_app->destroyRequested = 1;
142
break;
143
}
144
}
145
146
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
147
switch (cmd) {
148
case APP_CMD_TERM_WINDOW:
149
LOGV("APP_CMD_TERM_WINDOW\n");
150
pthread_mutex_lock(&android_app->mutex);
151
android_app->window = NULL;
152
pthread_cond_broadcast(&android_app->cond);
153
pthread_mutex_unlock(&android_app->mutex);
154
break;
155
156
case APP_CMD_SAVE_STATE:
157
LOGV("APP_CMD_SAVE_STATE\n");
158
pthread_mutex_lock(&android_app->mutex);
159
android_app->stateSaved = 1;
160
pthread_cond_broadcast(&android_app->cond);
161
pthread_mutex_unlock(&android_app->mutex);
162
break;
163
164
case APP_CMD_RESUME:
165
free_saved_state(android_app);
166
break;
167
}
168
}
169
170
void app_dummy(void) {
171
172
}
173
174
static void android_app_destroy(struct android_app* android_app) {
175
LOGV("android_app_destroy!");
176
free_saved_state(android_app);
177
pthread_mutex_lock(&android_app->mutex);
178
if (android_app->inputQueue != NULL) {
179
AInputQueue_detachLooper(android_app->inputQueue);
180
}
181
AConfiguration_delete(android_app->config);
182
android_app->destroyed = 1;
183
pthread_cond_broadcast(&android_app->cond);
184
pthread_mutex_unlock(&android_app->mutex);
185
// Can't touch android_app object after this.
186
}
187
188
static void process_input(struct android_app* app, struct android_poll_source* source) {
189
AInputEvent* event = NULL;
190
while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
191
LOGV("New input event: type=%d\n", AInputEvent_getType(event));
192
if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
193
continue;
194
}
195
int32_t handled = 0;
196
if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
197
AInputQueue_finishEvent(app->inputQueue, event, handled);
198
}
199
}
200
201
static void process_cmd(struct android_app* app, struct android_poll_source* source) {
202
int8_t cmd = android_app_read_cmd(app);
203
android_app_pre_exec_cmd(app, cmd);
204
if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
205
android_app_post_exec_cmd(app, cmd);
206
}
207
208
static void* android_app_entry(void* param) {
209
struct android_app* android_app = (struct android_app*)param;
210
211
android_app->config = AConfiguration_new();
212
AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
213
214
print_cur_config(android_app);
215
216
android_app->cmdPollSource.id = LOOPER_ID_MAIN;
217
android_app->cmdPollSource.app = android_app;
218
android_app->cmdPollSource.process = process_cmd;
219
android_app->inputPollSource.id = LOOPER_ID_INPUT;
220
android_app->inputPollSource.app = android_app;
221
android_app->inputPollSource.process = process_input;
222
223
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
224
ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
225
&android_app->cmdPollSource);
226
android_app->looper = looper;
227
228
pthread_mutex_lock(&android_app->mutex);
229
android_app->running = 1;
230
pthread_cond_broadcast(&android_app->cond);
231
pthread_mutex_unlock(&android_app->mutex);
232
233
android_main(android_app);
234
235
android_app_destroy(android_app);
236
return NULL;
237
}
238
239
// --------------------------------------------------------------------
240
// Native activity interaction (called from main thread)
241
// --------------------------------------------------------------------
242
243
static struct android_app* android_app_create(ANativeActivity* activity,
244
void* savedState, size_t savedStateSize) {
245
struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
246
memset(android_app, 0, sizeof(struct android_app));
247
android_app->activity = activity;
248
249
pthread_mutex_init(&android_app->mutex, NULL);
250
pthread_cond_init(&android_app->cond, NULL);
251
252
if (savedState != NULL) {
253
android_app->savedState = malloc(savedStateSize);
254
android_app->savedStateSize = savedStateSize;
255
memcpy(android_app->savedState, savedState, savedStateSize);
256
}
257
258
int msgpipe[2];
259
if (pipe(msgpipe)) {
260
LOGE("could not create pipe: %s", strerror(errno));
261
return NULL;
262
}
263
android_app->msgread = msgpipe[0];
264
android_app->msgwrite = msgpipe[1];
265
266
pthread_attr_t attr;
267
pthread_attr_init(&attr);
268
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
269
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
270
271
// Wait for thread to start.
272
pthread_mutex_lock(&android_app->mutex);
273
while (!android_app->running) {
274
pthread_cond_wait(&android_app->cond, &android_app->mutex);
275
}
276
pthread_mutex_unlock(&android_app->mutex);
277
278
return android_app;
279
}
280
281
static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
282
if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
283
LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
284
}
285
}
286
287
static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
288
pthread_mutex_lock(&android_app->mutex);
289
android_app->pendingInputQueue = inputQueue;
290
android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
291
while (android_app->inputQueue != android_app->pendingInputQueue) {
292
pthread_cond_wait(&android_app->cond, &android_app->mutex);
293
}
294
pthread_mutex_unlock(&android_app->mutex);
295
}
296
297
static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
298
pthread_mutex_lock(&android_app->mutex);
299
if (android_app->pendingWindow != NULL) {
300
android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
301
}
302
android_app->pendingWindow = window;
303
if (window != NULL) {
304
android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
305
}
306
while (android_app->window != android_app->pendingWindow) {
307
pthread_cond_wait(&android_app->cond, &android_app->mutex);
308
}
309
pthread_mutex_unlock(&android_app->mutex);
310
}
311
312
static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
313
pthread_mutex_lock(&android_app->mutex);
314
android_app_write_cmd(android_app, cmd);
315
while (android_app->activityState != cmd) {
316
pthread_cond_wait(&android_app->cond, &android_app->mutex);
317
}
318
pthread_mutex_unlock(&android_app->mutex);
319
}
320
321
static void android_app_free(struct android_app* android_app) {
322
pthread_mutex_lock(&android_app->mutex);
323
android_app_write_cmd(android_app, APP_CMD_DESTROY);
324
while (!android_app->destroyed) {
325
pthread_cond_wait(&android_app->cond, &android_app->mutex);
326
}
327
pthread_mutex_unlock(&android_app->mutex);
328
329
close(android_app->msgread);
330
close(android_app->msgwrite);
331
pthread_cond_destroy(&android_app->cond);
332
pthread_mutex_destroy(&android_app->mutex);
333
free(android_app);
334
}
335
336
static void onDestroy(ANativeActivity* activity) {
337
LOGV("Destroy: %p\n", activity);
338
android_app_free((struct android_app*)activity->instance);
339
}
340
341
static void onStart(ANativeActivity* activity) {
342
LOGV("Start: %p\n", activity);
343
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
344
}
345
346
static void onResume(ANativeActivity* activity) {
347
LOGV("Resume: %p\n", activity);
348
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
349
}
350
351
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
352
struct android_app* android_app = (struct android_app*)activity->instance;
353
void* savedState = NULL;
354
355
LOGV("SaveInstanceState: %p\n", activity);
356
pthread_mutex_lock(&android_app->mutex);
357
android_app->stateSaved = 0;
358
android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
359
while (!android_app->stateSaved) {
360
pthread_cond_wait(&android_app->cond, &android_app->mutex);
361
}
362
363
if (android_app->savedState != NULL) {
364
savedState = android_app->savedState;
365
*outLen = android_app->savedStateSize;
366
android_app->savedState = NULL;
367
android_app->savedStateSize = 0;
368
}
369
370
pthread_mutex_unlock(&android_app->mutex);
371
372
return savedState;
373
}
374
375
static void onPause(ANativeActivity* activity) {
376
LOGV("Pause: %p\n", activity);
377
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
378
}
379
380
static void onStop(ANativeActivity* activity) {
381
LOGV("Stop: %p\n", activity);
382
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
383
}
384
385
static void onConfigurationChanged(ANativeActivity* activity) {
386
struct android_app* android_app = (struct android_app*)activity->instance;
387
LOGV("ConfigurationChanged: %p\n", activity);
388
android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
389
}
390
391
static void onLowMemory(ANativeActivity* activity) {
392
struct android_app* android_app = (struct android_app*)activity->instance;
393
LOGV("LowMemory: %p\n", activity);
394
android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
395
}
396
397
static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
398
LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
399
android_app_write_cmd((struct android_app*)activity->instance,
400
focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
401
}
402
403
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
404
LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
405
android_app_set_window((struct android_app*)activity->instance, window);
406
}
407
408
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
409
LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
410
android_app_set_window((struct android_app*)activity->instance, NULL);
411
}
412
413
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
414
LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
415
android_app_set_input((struct android_app*)activity->instance, queue);
416
}
417
418
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
419
LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
420
android_app_set_input((struct android_app*)activity->instance, NULL);
421
}
422
423
__attribute__((visibility("default"))) void ANativeActivity_onCreate(ANativeActivity* activity,
424
void* savedState, size_t savedStateSize) {
425
LOGV("Creating: %p\n", activity);
426
activity->callbacks->onDestroy = onDestroy;
427
activity->callbacks->onStart = onStart;
428
activity->callbacks->onResume = onResume;
429
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
430
activity->callbacks->onPause = onPause;
431
activity->callbacks->onStop = onStop;
432
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
433
activity->callbacks->onLowMemory = onLowMemory;
434
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
435
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
436
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
437
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
438
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
439
440
activity->instance = android_app_create(activity, savedState, savedStateSize);
441
}
442
443