[UI] android.app.NativeActivity > WindowedAppActivity + code style

This commit is contained in:
Triang3l
2021-09-18 20:32:24 +03:00
parent 347c9f01fd
commit 26a2d814da
10 changed files with 377 additions and 106 deletions

View File

@@ -10,8 +10,10 @@
#ifndef XENIA_UI_WINDOWED_APP_CONTEXT_ANDROID_H_
#define XENIA_UI_WINDOWED_APP_CONTEXT_ANDROID_H_
#include <android/asset_manager.h>
#include <android/configuration.h>
#include <android/looper.h>
#include <android/native_activity.h>
#include <jni.h>
#include <array>
#include <memory>
@@ -25,13 +27,6 @@ class WindowedApp;
class AndroidWindowedAppContext final : public WindowedAppContext {
public:
// For calling from android.app.func_name exports.
static void StartAppOnActivityCreate(
ANativeActivity* activity, void* saved_state, size_t saved_state_size,
std::unique_ptr<WindowedApp> (*app_creator)(
WindowedAppContext& app_context));
ANativeActivity* activity() const { return activity_; }
WindowedApp* app() const { return app_.get(); }
void NotifyUILoopOfPendingFunctions() override;
@@ -45,6 +40,12 @@ class AndroidWindowedAppContext final : public WindowedAppContext {
AndroidWindow* GetActivityWindow() const { return activity_window_; }
void SetActivityWindow(AndroidWindow* window) { activity_window_ = window; }
// For calling from WindowedAppActivity native methods.
static AndroidWindowedAppContext* JniActivityInitializeWindowedAppOnCreate(
JNIEnv* jni_env, jobject activity, jstring windowed_app_identifier,
jobject asset_manager);
void JniActivityOnDestroy();
private:
enum class UIThreadLooperCallbackCommand : uint8_t {
kDestroy,
@@ -55,13 +56,14 @@ class AndroidWindowedAppContext final : public WindowedAppContext {
// 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.
// external ALooper_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);
bool Initialize(JNIEnv* ui_thread_jni_env, jobject activity,
jobject asset_manager);
void Shutdown();
// Call this function instead of deleting the object directly, so if needed,
@@ -75,10 +77,29 @@ class AndroidWindowedAppContext final : public WindowedAppContext {
bool InitializeApp(std::unique_ptr<WindowedApp> (*app_creator)(
WindowedAppContext& app_context));
static void OnActivityDestroy(ANativeActivity* activity);
// Useful notes about JNI usage on Android within Xenia:
// - All static libraries defining JNI native functions must be linked to
// shared libraries via LOCAL_WHOLE_STATIC_LIBRARIES.
// - If method or field IDs are cached, a global reference to the class needs
// to be held - it prevents the class from being unloaded by the class
// loaders (in a way that would make the IDs invalid when it's reloaded).
// - GetStringUTFChars (UTF-8) returns null-terminated strings, GetStringChars
// (UTF-16) does not.
JNIEnv* ui_thread_jni_env_ = nullptr;
// The object reference must be held by the app according to
// AAssetManager_fromJava documentation.
jobject asset_manager_jobject_ = nullptr;
AAssetManager* asset_manager_ = nullptr;
AConfiguration* configuration_ = nullptr;
bool android_base_initialized_ = false;
jobject activity_ = nullptr;
jclass activity_class_ = nullptr;
jmethodID activity_method_finish_ = nullptr;
// 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
@@ -86,11 +107,6 @@ class AndroidWindowedAppContext final : public WindowedAppContext {
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_ = nullptr;
AndroidWindow* activity_window_ = nullptr;
std::unique_ptr<WindowedApp> app_;