Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/util/android/AndroidWindow.cpp
1693 views
1
//
2
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
5
//
6
7
// AndroidWindow.cpp: Implementation of OSWindow for Android
8
9
#include "util/android/AndroidWindow.h"
10
11
#include <pthread.h>
12
#include <iostream>
13
14
#include "common/debug.h"
15
#include "util/android/third_party/android_native_app_glue.h"
16
17
namespace
18
{
19
struct android_app *sApp = nullptr;
20
pthread_mutex_t sInitWindowMutex;
21
pthread_cond_t sInitWindowCond;
22
bool sInitWindowDone = false;
23
JNIEnv *gJni = nullptr;
24
25
// SCREEN_ORIENTATION_LANDSCAPE and SCREEN_ORIENTATION_PORTRAIT are
26
// available from Android API level 1
27
// https://developer.android.com/reference/android/app/Activity#setRequestedOrientation(int)
28
const int kScreenOrientationLandscape = 0;
29
const int kScreenOrientationPortrait = 1;
30
31
JNIEnv *GetJniEnv()
32
{
33
if (gJni)
34
return gJni;
35
36
sApp->activity->vm->AttachCurrentThread(&gJni, NULL);
37
return gJni;
38
}
39
40
int SetScreenOrientation(struct android_app *app, int orientation)
41
{
42
// Use reverse JNI to call the Java entry point that rotates the
43
// display to respect width and height
44
JNIEnv *jni = GetJniEnv();
45
if (!jni)
46
{
47
std::cerr << "Failed to get JNI env for screen rotation";
48
return JNI_ERR;
49
}
50
51
jclass clazz = jni->GetObjectClass(app->activity->clazz);
52
jmethodID methodID = jni->GetMethodID(clazz, "setRequestedOrientation", "(I)V");
53
jni->CallVoidMethod(app->activity->clazz, methodID, orientation);
54
55
return 0;
56
}
57
} // namespace
58
59
AndroidWindow::AndroidWindow() {}
60
61
AndroidWindow::~AndroidWindow() {}
62
63
bool AndroidWindow::initializeImpl(const std::string &name, int width, int height)
64
{
65
return resize(width, height);
66
}
67
void AndroidWindow::destroy() {}
68
69
void AndroidWindow::disableErrorMessageDialog() {}
70
71
void AndroidWindow::resetNativeWindow() {}
72
73
EGLNativeWindowType AndroidWindow::getNativeWindow() const
74
{
75
// Return the entire Activity Surface for now
76
// sApp->window is valid only after sInitWindowDone, which is true after initializeImpl()
77
return sApp->window;
78
}
79
80
EGLNativeDisplayType AndroidWindow::getNativeDisplay() const
81
{
82
return EGL_DEFAULT_DISPLAY;
83
}
84
85
void AndroidWindow::messageLoop()
86
{
87
// TODO: accumulate events in the real message loop of android_main,
88
// and process them here
89
}
90
91
void AndroidWindow::setMousePosition(int x, int y)
92
{
93
UNIMPLEMENTED();
94
}
95
96
bool AndroidWindow::setOrientation(int width, int height)
97
{
98
// Set tests to run in correct orientation
99
int32_t err = SetScreenOrientation(
100
sApp, (width > height) ? kScreenOrientationLandscape : kScreenOrientationPortrait);
101
102
return err == 0;
103
}
104
bool AndroidWindow::setPosition(int x, int y)
105
{
106
UNIMPLEMENTED();
107
return false;
108
}
109
110
bool AndroidWindow::resize(int width, int height)
111
{
112
mWidth = width;
113
mHeight = height;
114
115
// sApp->window used below is valid only after Activity Surface is created
116
pthread_mutex_lock(&sInitWindowMutex);
117
while (!sInitWindowDone)
118
{
119
pthread_cond_wait(&sInitWindowCond, &sInitWindowMutex);
120
}
121
pthread_mutex_unlock(&sInitWindowMutex);
122
123
// TODO: figure out a way to set the format as well,
124
// which is available only after EGLWindow initialization
125
int32_t err = ANativeWindow_setBuffersGeometry(sApp->window, mWidth, mHeight, 0);
126
return err == 0;
127
}
128
129
void AndroidWindow::setVisible(bool isVisible) {}
130
131
void AndroidWindow::signalTestEvent()
132
{
133
UNIMPLEMENTED();
134
}
135
136
static void onAppCmd(struct android_app *app, int32_t cmd)
137
{
138
switch (cmd)
139
{
140
case APP_CMD_INIT_WINDOW:
141
pthread_mutex_lock(&sInitWindowMutex);
142
sInitWindowDone = true;
143
pthread_cond_broadcast(&sInitWindowCond);
144
pthread_mutex_unlock(&sInitWindowMutex);
145
break;
146
case APP_CMD_DESTROY:
147
if (gJni)
148
{
149
sApp->activity->vm->DetachCurrentThread();
150
}
151
gJni = nullptr;
152
break;
153
154
// TODO: process other commands and pass them to AndroidWindow for handling
155
// TODO: figure out how to handle APP_CMD_PAUSE,
156
// which should immediately halt all the rendering,
157
// since Activity Surface is no longer available.
158
// Currently tests crash when paused, for example, due to device changing orientation
159
}
160
}
161
162
static int32_t onInputEvent(struct android_app *app, AInputEvent *event)
163
{
164
// TODO: Handle input events
165
return 0; // 0 == not handled
166
}
167
168
void android_main(struct android_app *app)
169
{
170
int events;
171
struct android_poll_source *source;
172
173
sApp = app;
174
pthread_mutex_init(&sInitWindowMutex, nullptr);
175
pthread_cond_init(&sInitWindowCond, nullptr);
176
177
// Event handlers, invoked from source->process()
178
app->onAppCmd = onAppCmd;
179
app->onInputEvent = onInputEvent;
180
181
// Message loop, polling for events indefinitely (due to -1 timeout)
182
// Must be here in order to handle APP_CMD_INIT_WINDOW event,
183
// which occurs after AndroidWindow::initializeImpl(), but before AndroidWindow::messageLoop
184
while (ALooper_pollAll(-1, nullptr, &events, reinterpret_cast<void **>(&source)) >= 0)
185
{
186
if (source != nullptr)
187
{
188
source->process(app, source);
189
}
190
}
191
}
192
193
// static
194
std::string AndroidWindow::GetExternalStorageDirectory()
195
{
196
// Use reverse JNI.
197
JNIEnv *jni = GetJniEnv();
198
if (!jni)
199
{
200
std::cerr << "GetExternalStorageDirectory:: Failed to get JNI env";
201
return "";
202
}
203
204
jclass classEnvironment = jni->FindClass("android/os/Environment");
205
if (classEnvironment == 0)
206
{
207
std::cerr << "GetExternalStorageDirectory: Failed to find Environment";
208
return "";
209
}
210
211
// public static File getExternalStorageDirectory ()
212
jmethodID methodIDgetExternalStorageDirectory =
213
jni->GetStaticMethodID(classEnvironment, "getExternalStorageDirectory", "()Ljava/io/File;");
214
if (methodIDgetExternalStorageDirectory == 0)
215
{
216
std::cerr << "GetExternalStorageDirectory: Failed to get static method";
217
return "";
218
}
219
220
jobject objectFile =
221
jni->CallStaticObjectMethod(classEnvironment, methodIDgetExternalStorageDirectory);
222
jthrowable exception = jni->ExceptionOccurred();
223
if (exception != 0)
224
{
225
jni->ExceptionDescribe();
226
jni->ExceptionClear();
227
std::cerr << "GetExternalStorageDirectory: Failed because of exception";
228
return "";
229
}
230
231
// Call method on File object to retrieve String object.
232
jclass classFile = jni->GetObjectClass(objectFile);
233
if (classEnvironment == 0)
234
{
235
std::cerr << "GetExternalStorageDirectory: Failed to find object class";
236
return "";
237
}
238
239
jmethodID methodIDgetAbsolutePath =
240
jni->GetMethodID(classFile, "getAbsolutePath", "()Ljava/lang/String;");
241
if (methodIDgetAbsolutePath == 0)
242
{
243
std::cerr << "GetExternalStorageDirectory: Failed to get method ID";
244
return "";
245
}
246
247
jstring stringPath =
248
static_cast<jstring>(jni->CallObjectMethod(objectFile, methodIDgetAbsolutePath));
249
250
// TODO(jmadill): Find how to pass the root test directory to ANGLE. http://crbug.com/1097957
251
252
// // https://stackoverflow.com/questions/12841240/android-pass-parameter-to-native-activity
253
// jclass clazz = jni->GetObjectClass(sApp->activity->clazz);
254
// if (clazz == 0)
255
// {
256
// std::cerr << "GetExternalStorageDirectory: Bad activity";
257
// return "";
258
// }
259
260
// jmethodID giid = jni->GetMethodID(clazz, "getIntent", "()Landroid/content/Intent;");
261
// if (giid == 0)
262
// {
263
// std::cerr << "GetExternalStorageDirectory: Could not find getIntent";
264
// return "";
265
// }
266
267
// jobject intent = jni->CallObjectMethod(sApp->activity->clazz, giid);
268
// if (intent == 0)
269
// {
270
// std::cerr << "GetExternalStorageDirectory: Error calling getIntent";
271
// return "";
272
// }
273
274
// jclass icl = jni->GetObjectClass(intent);
275
// if (icl == 0)
276
// {
277
// std::cerr << "GetExternalStorageDirectory: Error getting getIntent class";
278
// return "";
279
// }
280
281
// jmethodID gseid =
282
// jni->GetMethodID(icl, "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;");
283
// if (gseid == 0)
284
// {
285
// std::cerr << "GetExternalStorageDirectory: Could not find getStringExtra";
286
// return "";
287
// }
288
289
// jstring stringPath = static_cast<jstring>(jni->CallObjectMethod(
290
// intent, gseid, jni->NewStringUTF("org.chromium.base.test.util.UrlUtils.RootDirectory")));
291
// if (stringPath != 0)
292
// {
293
// const char *path = jni->GetStringUTFChars(stringPath, nullptr);
294
// return std::string(path) + "/chromium_tests_root";
295
// }
296
297
// jclass environment = jni->FindClass("org/chromium/base/test/util/UrlUtils");
298
// if (environment == 0)
299
// {
300
// std::cerr << "GetExternalStorageDirectory: Failed to find Environment";
301
// return "";
302
// }
303
304
// jmethodID getDir =
305
// jni->GetStaticMethodID(environment, "getIsolatedTestRoot", "()Ljava/lang/String;");
306
// if (getDir == 0)
307
// {
308
// std::cerr << "GetExternalStorageDirectory: Failed to get static method";
309
// return "";
310
// }
311
312
// stringPath = static_cast<jstring>(jni->CallStaticObjectMethod(environment, getDir));
313
314
exception = jni->ExceptionOccurred();
315
if (exception != 0)
316
{
317
jni->ExceptionDescribe();
318
jni->ExceptionClear();
319
std::cerr << "GetExternalStorageDirectory: Failed because of exception";
320
return "";
321
}
322
323
const char *path = jni->GetStringUTFChars(stringPath, nullptr);
324
return std::string(path) + "/chromium_tests_root";
325
}
326
327
// static
328
OSWindow *OSWindow::New()
329
{
330
// There should be only one live instance of AndroidWindow at a time,
331
// as there is only one Activity Surface behind it.
332
// Creating a new AndroidWindow each time works for ANGLETest,
333
// as it destroys an old window before creating a new one.
334
// TODO: use GLSurfaceView to support multiple windows
335
return new AndroidWindow();
336
}
337
338