1 /*************************************************************************/
2 /*  os_android.cpp                                                       */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #include "os_android.h"
31 #include "drivers/gles2/rasterizer_gles2.h"
32 
33 #include "core/io/file_access_buffered_fa.h"
34 #include "drivers/unix/dir_access_unix.h"
35 #include "drivers/unix/file_access_unix.h"
36 
37 #include "main/main.h"
38 #include "servers/visual/visual_server_raster.h"
39 #include "servers/visual/visual_server_wrap_mt.h"
40 
41 #include "file_access_android.h"
42 
43 #include "core/globals.h"
44 
45 #ifdef ANDROID_NATIVE_ACTIVITY
46 #include "dir_access_android.h"
47 #include "file_access_android.h"
48 #else
49 #include "dir_access_jandroid.h"
50 #include "file_access_jandroid.h"
51 #endif
52 
get_video_driver_count() const53 int OS_Android::get_video_driver_count() const {
54 
55 	return 1;
56 }
57 
get_video_driver_name(int p_driver) const58 const char *OS_Android::get_video_driver_name(int p_driver) const {
59 
60 	return "GLES2";
61 }
62 
get_default_video_mode() const63 OS::VideoMode OS_Android::get_default_video_mode() const {
64 
65 	return OS::VideoMode();
66 }
67 
get_audio_driver_count() const68 int OS_Android::get_audio_driver_count() const {
69 
70 	return 1;
71 }
72 
get_audio_driver_name(int p_driver) const73 const char *OS_Android::get_audio_driver_name(int p_driver) const {
74 
75 	return "Android";
76 }
77 
initialize_core()78 void OS_Android::initialize_core() {
79 
80 	OS_Unix::initialize_core();
81 
82 #ifdef ANDROID_NATIVE_ACTIVITY
83 
84 	FileAccess::make_default<FileAccessAndroid>(FileAccess::ACCESS_RESOURCES);
85 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
86 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
87 	//FileAccessBufferedFA<FileAccessUnix>::make_default();
88 	DirAccess::make_default<DirAccessAndroid>(DirAccess::ACCESS_RESOURCES);
89 	DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
90 	DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
91 
92 #else
93 
94 	if (use_apk_expansion)
95 		FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
96 	else {
97 #ifdef USE_JAVA_FILE_ACCESS
98 		FileAccess::make_default<FileAccessBufferedFA<FileAccessJAndroid> >(FileAccess::ACCESS_RESOURCES);
99 #else
100 		//FileAccess::make_default<FileAccessBufferedFA<FileAccessAndroid> >(FileAccess::ACCESS_RESOURCES);
101 		FileAccess::make_default<FileAccessAndroid>(FileAccess::ACCESS_RESOURCES);
102 #endif
103 	}
104 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
105 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
106 	//FileAccessBufferedFA<FileAccessUnix>::make_default();
107 	if (use_apk_expansion)
108 		DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
109 	else
110 		DirAccess::make_default<DirAccessJAndroid>(DirAccess::ACCESS_RESOURCES);
111 	DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
112 	DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
113 
114 #endif
115 }
116 
set_opengl_extensions(const char * p_gl_extensions)117 void OS_Android::set_opengl_extensions(const char *p_gl_extensions) {
118 
119 	ERR_FAIL_COND(!p_gl_extensions);
120 	gl_extensions = p_gl_extensions;
121 }
122 
initialize(const VideoMode & p_desired,int p_video_driver,int p_audio_driver)123 void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
124 
125 	use_gl2 = p_video_driver != 1;
126 
127 	if (gfx_init_func)
128 		gfx_init_func(gfx_init_ud, use_gl2);
129 
130 	AudioDriverManagerSW::add_driver(&audio_driver_android);
131 
132 	RasterizerGLES2 *rasterizer_gles22 = memnew(RasterizerGLES2(false, use_reload_hooks, false, use_reload_hooks));
133 	if (gl_extensions)
134 		rasterizer_gles22->set_extensions(gl_extensions);
135 	rasterizer = rasterizer_gles22;
136 
137 	rasterizer->set_force_16_bits_fbo(use_16bits_fbo);
138 
139 	visual_server = memnew(VisualServerRaster(rasterizer));
140 	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
141 
142 		visual_server = memnew(VisualServerWrapMT(visual_server, false));
143 	};
144 	visual_server->init();
145 
146 	AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
147 
148 	if (AudioDriverManagerSW::get_driver(p_audio_driver)->init() != OK) {
149 
150 		ERR_PRINT("Initializing audio failed.");
151 	}
152 
153 	sample_manager = memnew(SampleManagerMallocSW);
154 	audio_server = memnew(AudioServerSW(sample_manager));
155 
156 	audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR, true);
157 	audio_server->init();
158 
159 	spatial_sound_server = memnew(SpatialSoundServerSW);
160 	spatial_sound_server->init();
161 
162 	spatial_sound_2d_server = memnew(SpatialSound2DServerSW);
163 	spatial_sound_2d_server->init();
164 
165 	//
166 	physics_server = memnew(PhysicsServerSW);
167 	physics_server->init();
168 	//physics_2d_server = memnew( Physics2DServerSW );
169 	physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
170 	physics_2d_server->init();
171 
172 	input = memnew(InputDefault);
173 	input->set_fallback_mapping("Default Android Gamepad");
174 }
175 
set_main_loop(MainLoop * p_main_loop)176 void OS_Android::set_main_loop(MainLoop *p_main_loop) {
177 
178 	main_loop = p_main_loop;
179 	input->set_main_loop(p_main_loop);
180 }
181 
delete_main_loop()182 void OS_Android::delete_main_loop() {
183 
184 	memdelete(main_loop);
185 }
186 
finalize()187 void OS_Android::finalize() {
188 
189 	memdelete(input);
190 }
191 
vprint(const char * p_format,va_list p_list,bool p_stderr)192 void OS_Android::vprint(const char *p_format, va_list p_list, bool p_stderr) {
193 
194 	__android_log_vprint(p_stderr ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "godot", p_format, p_list);
195 }
196 
print(const char * p_format,...)197 void OS_Android::print(const char *p_format, ...) {
198 
199 	va_list argp;
200 	va_start(argp, p_format);
201 	__android_log_vprint(ANDROID_LOG_INFO, "godot", p_format, argp);
202 	va_end(argp);
203 }
204 
alert(const String & p_alert,const String & p_title)205 void OS_Android::alert(const String &p_alert, const String &p_title) {
206 
207 	print("ALERT: %s\n", p_alert.utf8().get_data());
208 	if (alert_func)
209 		alert_func(p_alert, p_title);
210 }
211 
set_mouse_show(bool p_show)212 void OS_Android::set_mouse_show(bool p_show) {
213 
214 	//android has no mouse...
215 }
216 
set_mouse_grab(bool p_grab)217 void OS_Android::set_mouse_grab(bool p_grab) {
218 
219 	//it really has no mouse...!
220 }
221 
is_mouse_grab_enabled() const222 bool OS_Android::is_mouse_grab_enabled() const {
223 
224 	//*sigh* technology has evolved so much since i was a kid..
225 	return false;
226 }
227 
get_mouse_pos() const228 Point2 OS_Android::get_mouse_pos() const {
229 
230 	return Point2();
231 }
232 
get_mouse_button_state() const233 int OS_Android::get_mouse_button_state() const {
234 
235 	return 0;
236 }
237 
set_window_title(const String & p_title)238 void OS_Android::set_window_title(const String &p_title) {
239 }
240 
set_video_mode(const VideoMode & p_video_mode,int p_screen)241 void OS_Android::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
242 }
243 
get_video_mode(int p_screen) const244 OS::VideoMode OS_Android::get_video_mode(int p_screen) const {
245 
246 	return default_videomode;
247 }
248 
get_fullscreen_mode_list(List<VideoMode> * p_list,int p_screen) const249 void OS_Android::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
250 
251 	p_list->push_back(default_videomode);
252 }
253 
set_keep_screen_on(bool p_enabled)254 void OS_Android::set_keep_screen_on(bool p_enabled) {
255 	OS::set_keep_screen_on(p_enabled);
256 
257 	if (set_keep_screen_on_func) {
258 		set_keep_screen_on_func(p_enabled);
259 	}
260 }
261 
get_window_size() const262 Size2 OS_Android::get_window_size() const {
263 
264 	return Vector2(default_videomode.width, default_videomode.height);
265 }
266 
get_name()267 String OS_Android::get_name() {
268 
269 	return "Android";
270 }
271 
get_main_loop() const272 MainLoop *OS_Android::get_main_loop() const {
273 
274 	return main_loop;
275 }
276 
can_draw() const277 bool OS_Android::can_draw() const {
278 
279 	return true; //always?
280 }
281 
set_cursor_shape(CursorShape p_shape)282 void OS_Android::set_cursor_shape(CursorShape p_shape) {
283 
284 	//android really really really has no mouse.. how amazing..
285 }
286 
set_custom_mouse_cursor(const RES & p_cursor,CursorShape p_shape,const Vector2 & p_hotspot)287 void OS_Android::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
288 
289 	// Since android has no mouse, we do not need to change its texture (how amazing !)
290 }
291 
main_loop_begin()292 void OS_Android::main_loop_begin() {
293 
294 	if (main_loop)
295 		main_loop->init();
296 }
297 
main_loop_iterate()298 bool OS_Android::main_loop_iterate() {
299 
300 	if (!main_loop)
301 		return false;
302 	return Main::iteration();
303 }
304 
main_loop_end()305 void OS_Android::main_loop_end() {
306 
307 	if (main_loop)
308 		main_loop->finish();
309 }
310 
main_loop_focusout()311 void OS_Android::main_loop_focusout() {
312 
313 	if (main_loop)
314 		main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
315 	audio_driver_android.set_pause(true);
316 }
317 
main_loop_focusin()318 void OS_Android::main_loop_focusin() {
319 
320 	if (main_loop)
321 		main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
322 	audio_driver_android.set_pause(false);
323 }
324 
process_joy_event(OS_Android::JoystickEvent p_event)325 void OS_Android::process_joy_event(OS_Android::JoystickEvent p_event) {
326 
327 	switch (p_event.type) {
328 		case JOY_EVENT_BUTTON:
329 			last_id = input->joy_button(last_id, p_event.device, p_event.index, p_event.pressed);
330 			break;
331 		case JOY_EVENT_AXIS:
332 			InputDefault::JoyAxis value;
333 			value.min = -1;
334 			value.value = p_event.value;
335 			last_id = input->joy_axis(last_id, p_event.device, p_event.index, value);
336 			break;
337 		case JOY_EVENT_HAT:
338 			last_id = input->joy_hat(last_id, p_event.device, p_event.hat);
339 			break;
340 		default:
341 			return;
342 	}
343 }
344 
process_event(InputEvent p_event)345 void OS_Android::process_event(InputEvent p_event) {
346 
347 	p_event.ID = last_id++;
348 	input->parse_input_event(p_event);
349 }
350 
process_touch(int p_what,int p_pointer,const Vector<TouchPos> & p_points)351 void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points) {
352 
353 	//	print_line("ev: "+itos(p_what)+" pnt: "+itos(p_pointer)+" pointc: "+itos(p_points.size()));
354 
355 	switch (p_what) {
356 		case 0: { //gesture begin
357 
358 			if (touch.size()) {
359 				//end all if exist
360 				InputEvent ev;
361 				ev.type = InputEvent::MOUSE_BUTTON;
362 				ev.ID = last_id++;
363 				ev.mouse_button.button_index = BUTTON_LEFT;
364 				ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
365 				ev.mouse_button.pressed = false;
366 				ev.mouse_button.x = touch[0].pos.x;
367 				ev.mouse_button.y = touch[0].pos.y;
368 				ev.mouse_button.global_x = touch[0].pos.x;
369 				ev.mouse_button.global_y = touch[0].pos.y;
370 				input->parse_input_event(ev);
371 
372 				for (int i = 0; i < touch.size(); i++) {
373 
374 					InputEvent ev;
375 					ev.type = InputEvent::SCREEN_TOUCH;
376 					ev.ID = last_id++;
377 					ev.screen_touch.index = touch[i].id;
378 					ev.screen_touch.pressed = false;
379 					ev.screen_touch.x = touch[i].pos.x;
380 					ev.screen_touch.y = touch[i].pos.y;
381 					input->parse_input_event(ev);
382 				}
383 			}
384 
385 			touch.resize(p_points.size());
386 			for (int i = 0; i < p_points.size(); i++) {
387 				touch[i].id = p_points[i].id;
388 				touch[i].pos = p_points[i].pos;
389 			}
390 
391 			{
392 				//send mouse
393 				InputEvent ev;
394 				ev.type = InputEvent::MOUSE_BUTTON;
395 				ev.ID = last_id++;
396 				ev.mouse_button.button_index = BUTTON_LEFT;
397 				ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
398 				ev.mouse_button.pressed = true;
399 				ev.mouse_button.x = touch[0].pos.x;
400 				ev.mouse_button.y = touch[0].pos.y;
401 				ev.mouse_button.global_x = touch[0].pos.x;
402 				ev.mouse_button.global_y = touch[0].pos.y;
403 				input->set_mouse_pos(Point2(touch[0].pos.x, touch[0].pos.y));
404 				last_mouse = touch[0].pos;
405 				input->parse_input_event(ev);
406 			}
407 
408 			//send touch
409 			for (int i = 0; i < touch.size(); i++) {
410 
411 				InputEvent ev;
412 				ev.type = InputEvent::SCREEN_TOUCH;
413 				ev.ID = last_id++;
414 				ev.screen_touch.index = touch[i].id;
415 				ev.screen_touch.pressed = true;
416 				ev.screen_touch.x = touch[i].pos.x;
417 				ev.screen_touch.y = touch[i].pos.y;
418 				input->parse_input_event(ev);
419 			}
420 
421 		} break;
422 		case 1: { //motion
423 
424 			if (p_points.size()) {
425 				//send mouse, should look for point 0?
426 				InputEvent ev;
427 				ev.type = InputEvent::MOUSE_MOTION;
428 				ev.ID = last_id++;
429 				ev.mouse_motion.button_mask = BUTTON_MASK_LEFT;
430 				ev.mouse_motion.x = p_points[0].pos.x;
431 				ev.mouse_motion.y = p_points[0].pos.y;
432 				input->set_mouse_pos(Point2(ev.mouse_motion.x, ev.mouse_motion.y));
433 				ev.mouse_motion.speed_x = input->get_mouse_speed().x;
434 				ev.mouse_motion.speed_y = input->get_mouse_speed().y;
435 				ev.mouse_motion.relative_x = p_points[0].pos.x - last_mouse.x;
436 				ev.mouse_motion.relative_y = p_points[0].pos.y - last_mouse.y;
437 				last_mouse = p_points[0].pos;
438 				input->parse_input_event(ev);
439 			}
440 
441 			ERR_FAIL_COND(touch.size() != p_points.size());
442 
443 			for (int i = 0; i < touch.size(); i++) {
444 
445 				int idx = -1;
446 				for (int j = 0; j < p_points.size(); j++) {
447 
448 					if (touch[i].id == p_points[j].id) {
449 						idx = j;
450 						break;
451 					}
452 				}
453 
454 				ERR_CONTINUE(idx == -1);
455 
456 				if (touch[i].pos == p_points[idx].pos)
457 					continue; //no move unncesearily
458 
459 				InputEvent ev;
460 				ev.type = InputEvent::SCREEN_DRAG;
461 				ev.ID = last_id++;
462 				ev.screen_drag.index = touch[i].id;
463 				ev.screen_drag.x = p_points[idx].pos.x;
464 				ev.screen_drag.y = p_points[idx].pos.y;
465 				ev.screen_drag.relative_x = p_points[idx].pos.x - touch[i].pos.x;
466 				ev.screen_drag.relative_y = p_points[idx].pos.y - touch[i].pos.y;
467 				input->parse_input_event(ev);
468 				touch[i].pos = p_points[idx].pos;
469 			}
470 
471 		} break;
472 		case 2: { //release
473 
474 			if (touch.size()) {
475 				//end all if exist
476 				InputEvent ev;
477 				ev.type = InputEvent::MOUSE_BUTTON;
478 				ev.ID = last_id++;
479 				ev.mouse_button.button_index = BUTTON_LEFT;
480 				ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
481 				ev.mouse_button.pressed = false;
482 				ev.mouse_button.x = touch[0].pos.x;
483 				ev.mouse_button.y = touch[0].pos.y;
484 				ev.mouse_button.global_x = touch[0].pos.x;
485 				ev.mouse_button.global_y = touch[0].pos.y;
486 				input->set_mouse_pos(Point2(touch[0].pos.x, touch[0].pos.y));
487 				input->parse_input_event(ev);
488 
489 				for (int i = 0; i < touch.size(); i++) {
490 
491 					InputEvent ev;
492 					ev.type = InputEvent::SCREEN_TOUCH;
493 					ev.ID = last_id++;
494 					ev.screen_touch.index = touch[i].id;
495 					ev.screen_touch.pressed = false;
496 					ev.screen_touch.x = touch[i].pos.x;
497 					ev.screen_touch.y = touch[i].pos.y;
498 					input->parse_input_event(ev);
499 				}
500 				touch.clear();
501 			}
502 
503 		} break;
504 		case 3: { // add tuchi
505 
506 			ERR_FAIL_INDEX(p_pointer, p_points.size());
507 
508 			TouchPos tp = p_points[p_pointer];
509 			touch.push_back(tp);
510 
511 			InputEvent ev;
512 			ev.type = InputEvent::SCREEN_TOUCH;
513 			ev.ID = last_id++;
514 			ev.screen_touch.index = tp.id;
515 			ev.screen_touch.pressed = true;
516 			ev.screen_touch.x = tp.pos.x;
517 			ev.screen_touch.y = tp.pos.y;
518 			input->parse_input_event(ev);
519 
520 		} break;
521 		case 4: {
522 
523 			for (int i = 0; i < touch.size(); i++) {
524 				if (touch[i].id == p_pointer) {
525 
526 					InputEvent ev;
527 					ev.type = InputEvent::SCREEN_TOUCH;
528 					ev.ID = last_id++;
529 					ev.screen_touch.index = touch[i].id;
530 					ev.screen_touch.pressed = false;
531 					ev.screen_touch.x = touch[i].pos.x;
532 					ev.screen_touch.y = touch[i].pos.y;
533 					input->parse_input_event(ev);
534 					touch.remove(i);
535 					i--;
536 				}
537 			}
538 
539 		} break;
540 	}
541 }
542 
process_accelerometer(const Vector3 & p_accelerometer)543 void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) {
544 
545 	input->set_accelerometer(p_accelerometer);
546 }
547 
process_gravitymeter(const Vector3 & p_gravitymeter)548 void OS_Android::process_gravitymeter(const Vector3 &p_gravitymeter) {
549 
550 	input->set_gravity(p_gravitymeter);
551 }
552 
process_magnetometer(const Vector3 & p_magnetometer)553 void OS_Android::process_magnetometer(const Vector3 &p_magnetometer) {
554 
555 	input->set_magnetometer(p_magnetometer);
556 }
557 
process_gyroscope(const Vector3 & p_gyroscope)558 void OS_Android::process_gyroscope(const Vector3 &p_gyroscope) {
559 
560 	input->set_gyroscope(p_gyroscope);
561 }
562 
has_touchscreen_ui_hint() const563 bool OS_Android::has_touchscreen_ui_hint() const {
564 
565 	return true;
566 }
567 
has_virtual_keyboard() const568 bool OS_Android::has_virtual_keyboard() const {
569 
570 	return true;
571 }
572 
show_virtual_keyboard(const String & p_existing_text,const Rect2 & p_screen_rect)573 void OS_Android::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect) {
574 
575 	if (show_virtual_keyboard_func) {
576 		show_virtual_keyboard_func(p_existing_text);
577 	} else {
578 
579 		ERR_PRINT("Virtual keyboard not available");
580 	};
581 }
582 
hide_virtual_keyboard()583 void OS_Android::hide_virtual_keyboard() {
584 
585 	if (hide_virtual_keyboard_func) {
586 
587 		hide_virtual_keyboard_func();
588 	} else {
589 
590 		ERR_PRINT("Virtual keyboard not available");
591 	};
592 }
593 
init_video_mode(int p_video_width,int p_video_height)594 void OS_Android::init_video_mode(int p_video_width, int p_video_height) {
595 
596 	default_videomode.width = p_video_width;
597 	default_videomode.height = p_video_height;
598 	default_videomode.fullscreen = true;
599 	default_videomode.resizable = false;
600 }
601 
main_loop_request_quit()602 void OS_Android::main_loop_request_quit() {
603 
604 	if (main_loop)
605 		main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
606 }
607 
set_display_size(Size2 p_size)608 void OS_Android::set_display_size(Size2 p_size) {
609 
610 	default_videomode.width = p_size.x;
611 	default_videomode.height = p_size.y;
612 }
613 
reload_gfx()614 void OS_Android::reload_gfx() {
615 
616 	if (gfx_init_func)
617 		gfx_init_func(gfx_init_ud, use_gl2);
618 	if (rasterizer)
619 		rasterizer->reload_vram();
620 }
621 
shell_open(String p_uri)622 Error OS_Android::shell_open(String p_uri) {
623 
624 	if (open_uri_func)
625 		return open_uri_func(p_uri) ? ERR_CANT_OPEN : OK;
626 	return ERR_UNAVAILABLE;
627 }
628 
get_resource_dir() const629 String OS_Android::get_resource_dir() const {
630 
631 	return "/"; //android has it's own filesystem for resources inside the APK
632 }
633 
get_locale() const634 String OS_Android::get_locale() const {
635 
636 	if (get_locale_func)
637 		return get_locale_func();
638 	return OS_Unix::get_locale();
639 }
640 
set_clipboard(const String & p_text)641 void OS_Android::set_clipboard(const String &p_text) {
642 
643 	if (set_clipboard_func) {
644 		set_clipboard_func(p_text);
645 	} else {
646 		OS_Unix::set_clipboard(p_text);
647 	}
648 }
649 
get_clipboard() const650 String OS_Android::get_clipboard() const {
651 	if (get_clipboard_func) {
652 		return get_clipboard_func();
653 	}
654 
655 	return OS_Unix::get_clipboard();
656 }
657 
get_model_name() const658 String OS_Android::get_model_name() const {
659 
660 	if (get_model_func)
661 		return get_model_func();
662 	return OS_Unix::get_model_name();
663 }
664 
get_screen_dpi(int p_screen) const665 int OS_Android::get_screen_dpi(int p_screen) const {
666 
667 	if (get_screen_dpi_func) {
668 		return get_screen_dpi_func();
669 	}
670 	return 160;
671 }
672 
set_need_reload_hooks(bool p_needs_them)673 void OS_Android::set_need_reload_hooks(bool p_needs_them) {
674 
675 	use_reload_hooks = p_needs_them;
676 }
677 
get_data_dir() const678 String OS_Android::get_data_dir() const {
679 
680 	if (data_dir_cache != String())
681 		return data_dir_cache;
682 
683 	if (get_data_dir_func) {
684 		String data_dir = get_data_dir_func();
685 
686 		//store current dir
687 		char real_current_dir_name[2048];
688 		getcwd(real_current_dir_name, 2048);
689 
690 		//go to data dir
691 		chdir(data_dir.utf8().get_data());
692 
693 		//get actual data dir, so we resolve potential symlink (Android 6.0+ seems to use symlink)
694 		char data_current_dir_name[2048];
695 		getcwd(data_current_dir_name, 2048);
696 
697 		//cache by parsing utf8
698 		data_dir_cache.parse_utf8(data_current_dir_name);
699 
700 		//restore original dir so we don't mess things up
701 		chdir(real_current_dir_name);
702 
703 		return data_dir_cache;
704 	}
705 
706 	return ".";
707 	//return Globals::get_singleton()->get_singleton_object("GodotOS")->call("get_data_dir");
708 }
709 
set_screen_orientation(ScreenOrientation p_orientation)710 void OS_Android::set_screen_orientation(ScreenOrientation p_orientation) {
711 
712 	if (set_screen_orientation_func)
713 		set_screen_orientation_func(p_orientation);
714 }
715 
get_unique_ID() const716 String OS_Android::get_unique_ID() const {
717 
718 	if (get_unique_id_func)
719 		return get_unique_id_func();
720 	return OS::get_unique_ID();
721 }
722 
native_video_play(String p_path,float p_volume)723 Error OS_Android::native_video_play(String p_path, float p_volume) {
724 	if (video_play_func)
725 		video_play_func(p_path);
726 	return OK;
727 }
728 
native_video_is_playing()729 bool OS_Android::native_video_is_playing() {
730 	if (video_is_playing_func)
731 		return video_is_playing_func();
732 	return false;
733 }
734 
native_video_pause()735 void OS_Android::native_video_pause() {
736 	if (video_pause_func)
737 		video_pause_func();
738 }
739 
get_system_dir(SystemDir p_dir) const740 String OS_Android::get_system_dir(SystemDir p_dir) const {
741 
742 	if (get_system_dir_func)
743 		return get_system_dir_func(p_dir);
744 	return String(".");
745 }
746 
native_video_stop()747 void OS_Android::native_video_stop() {
748 	if (video_stop_func)
749 		video_stop_func();
750 }
751 
set_context_is_16_bits(bool p_is_16)752 void OS_Android::set_context_is_16_bits(bool p_is_16) {
753 
754 	use_16bits_fbo = p_is_16;
755 	if (rasterizer)
756 		rasterizer->set_force_16_bits_fbo(p_is_16);
757 }
758 
joy_connection_changed(int p_device,bool p_connected,String p_name)759 void OS_Android::joy_connection_changed(int p_device, bool p_connected, String p_name) {
760 	return input->joy_connection_changed(p_device, p_connected, p_name, "");
761 }
762 
is_joy_known(int p_device)763 bool OS_Android::is_joy_known(int p_device) {
764 	return input->is_joy_mapped(p_device);
765 }
766 
print_error(const char * p_function,const char * p_file,int p_line,const char * p_code,const char * p_rationale,ErrorType p_type)767 void OS_Android::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
768 	const char *err_details;
769 	if (p_rationale && p_rationale[0])
770 		err_details = p_rationale;
771 	else
772 		err_details = p_code;
773 
774 	switch (p_type) {
775 		case ERR_ERROR:
776 			print("ERROR: %s: %s\n", p_function, err_details);
777 			print("   At: %s:%i\n", p_file, p_line);
778 
779 			if (emit_error_signal) {
780 				emit_error_signal("Error", p_function, err_details, p_file, p_line);
781 			}
782 			break;
783 
784 		case ERR_WARNING:
785 			print("WARNING: %s: %s\n", p_function, err_details);
786 			print("   At: %s:%i\n", p_file, p_line);
787 
788 			if (emit_error_signal) {
789 				emit_error_signal("Warning", p_function, err_details, p_file, p_line);
790 			}
791 			break;
792 
793 		case ERR_SCRIPT:
794 			print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
795 			print("   At: %s:%i\n", p_file, p_line);
796 
797 			if (emit_error_signal) {
798 				emit_error_signal("Script error", p_function, err_details, p_file, p_line);
799 			}
800 			break;
801 	}
802 }
803 
get_joy_guid(int p_device) const804 String OS_Android::get_joy_guid(int p_device) const {
805 	return input->get_joy_guid_remapped(p_device);
806 }
807 
OS_Android(GFXInitFunc p_gfx_init_func,void * p_gfx_init_ud,OpenURIFunc p_open_uri_func,GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func,GetScreenDPIFunc p_get_screen_dpi_func,ShowVirtualKeyboardFunc p_show_vk,HideVirtualKeyboardFunc p_hide_vk,SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func,VideoPlayFunc p_video_play_func,VideoIsPlayingFunc p_video_is_playing_func,VideoPauseFunc p_video_pause_func,VideoStopFunc p_video_stop_func,SetKeepScreenOnFunc p_set_keep_screen_on_func,AlertFunc p_alert_func,bool p_use_apk_expansion,SetClipboardFunc p_set_clipboard_func,GetClipboardFunc p_get_clipboard_func,EmitErrorSignal p_emit_error_signal)808 OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion, SetClipboardFunc p_set_clipboard_func, GetClipboardFunc p_get_clipboard_func, EmitErrorSignal p_emit_error_signal) {
809 
810 	use_apk_expansion = p_use_apk_expansion;
811 	default_videomode.width = 800;
812 	default_videomode.height = 600;
813 	default_videomode.fullscreen = true;
814 	default_videomode.resizable = false;
815 
816 	gfx_init_func = p_gfx_init_func;
817 	gfx_init_ud = p_gfx_init_ud;
818 	main_loop = NULL;
819 	last_id = 1;
820 	gl_extensions = NULL;
821 	rasterizer = NULL;
822 	use_gl2 = false;
823 
824 	open_uri_func = p_open_uri_func;
825 	get_data_dir_func = p_get_data_dir_func;
826 	get_locale_func = p_get_locale_func;
827 	get_model_func = p_get_model_func;
828 	get_screen_dpi_func = p_get_screen_dpi_func;
829 	get_unique_id_func = p_get_unique_id;
830 	get_system_dir_func = p_get_sdir_func;
831 
832 	video_play_func = p_video_play_func;
833 	video_is_playing_func = p_video_is_playing_func;
834 	video_pause_func = p_video_pause_func;
835 	video_stop_func = p_video_stop_func;
836 
837 	show_virtual_keyboard_func = p_show_vk;
838 	hide_virtual_keyboard_func = p_hide_vk;
839 
840 	set_screen_orientation_func = p_screen_orient;
841 	set_keep_screen_on_func = p_set_keep_screen_on_func;
842 	alert_func = p_alert_func;
843 	use_reload_hooks = false;
844 
845 	set_clipboard_func = p_set_clipboard_func;
846 	get_clipboard_func = p_get_clipboard_func;
847 
848 	emit_error_signal = p_emit_error_signal;
849 }
850 
~OS_Android()851 OS_Android::~OS_Android() {
852 }
853