[UI] Android CallInUIThread and activity onDestroy

This commit is contained in:
Triang3l
2021-09-15 22:58:11 +03:00
parent d4f2bef6c8
commit 0335571354
3 changed files with 249 additions and 28 deletions

View File

@@ -10,7 +10,9 @@
#ifndef XENIA_UI_WINDOWED_APP_CONTEXT_ANDROID_H_
#define XENIA_UI_WINDOWED_APP_CONTEXT_ANDROID_H_
#include <android/looper.h>
#include <android/native_activity.h>
#include <array>
#include <memory>
#include "xenia/ui/windowed_app_context.h"
@@ -24,15 +26,11 @@ class WindowedApp;
class AndroidWindowedAppContext final : public WindowedAppContext {
public:
// For calling from android.app.func_name exports.
static void StartAppOnNativeActivityCreate(
static void StartAppOnActivityCreate(
ANativeActivity* activity, void* saved_state, size_t saved_state_size,
std::unique_ptr<WindowedApp> (*app_creator)(
WindowedAppContext& app_context));
// Defined in the translation unit where WindowedApp is complete because of
// std::unique_ptr.
~AndroidWindowedAppContext();
ANativeActivity* activity() const { return activity_; }
WindowedApp* app() const { return app_.get(); }
@@ -48,21 +46,54 @@ class AndroidWindowedAppContext final : public WindowedAppContext {
void SetActivityWindow(AndroidWindow* window) { activity_window_ = window; }
private:
explicit AndroidWindowedAppContext(ANativeActivity* activity);
enum class UIThreadLooperCallbackCommand : uint8_t {
kDestroy,
kExecutePendingFunctions,
};
AndroidWindowedAppContext() = default;
// Don't delete this object directly externally if successfully initialized as
// the looper may still execute the callback for pending commands after an
// external ANativeActivity_removeFd, and the callback receives a pointer to
// the context - deletion must be deferred and done in the callback itself.
// Defined in the translation unit where WindowedApp is complete because of
// std::unique_ptr.
~AndroidWindowedAppContext();
bool Initialize(ANativeActivity* activity);
void Shutdown();
// Call this function instead of deleting the object directly, so if needed,
// deletion will be deferred until the callback (receiving a pointer to the
// context) can no longer be executed by the looper (will be done inside the
// callback).
void RequestDestruction();
static int UIThreadLooperCallback(int fd, int events, void* data);
bool InitializeApp(std::unique_ptr<WindowedApp> (*app_creator)(
WindowedAppContext& app_context));
static void OnActivityDestroy(ANativeActivity* activity);
bool android_base_initialized_ = false;
// May be read by non-UI threads in NotifyUILoopOfPendingFunctions.
ALooper* ui_thread_looper_ = nullptr;
// [1] (the write file descriptor) may be referenced as read-only by non-UI
// threads in NotifyUILoopOfPendingFunctions.
std::array<int, 2> ui_thread_looper_callback_pipe_{-1, -1};
bool ui_thread_looper_callback_registered_ = false;
// TODO(Triang3l): Switch from ANativeActivity to the context itself being the
// object for communication with the Java code when NativeActivity isn't used
// anymore as its functionality is heavily limited.
ANativeActivity* activity_;
std::unique_ptr<WindowedApp> app_;
ANativeActivity* activity_ = nullptr;
AndroidWindow* activity_window_ = nullptr;
// TODO(Triang3l): The rest of the context, including quit handler (and the
// destructor) calling `finish` on the activity, UI looper notification
// posting, etc.
std::unique_ptr<WindowedApp> app_;
};
} // namespace ui