diff --git a/.clang-format b/.clang-format
index f9aa6536d..e4310ac3c 100644
--- a/.clang-format
+++ b/.clang-format
@@ -6,3 +6,8 @@ SortIncludes: true
# Regroup causes unnecessary noise due to clang-format bug.
IncludeBlocks: Preserve
+
+---
+Language: Java
+DisableFormat: true
+SortIncludes: false
diff --git a/android/android_studio_project/app/src/main/AndroidManifest.xml b/android/android_studio_project/app/src/main/AndroidManifest.xml
index c5c7c703f..8f6d53cb0 100644
--- a/android/android_studio_project/app/src/main/AndroidManifest.xml
+++ b/android/android_studio_project/app/src/main/AndroidManifest.xml
@@ -2,12 +2,23 @@
-
-
-
+
+
+
+
+
-
-
+
+
-
+
+
+
\ No newline at end of file
diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/DemoActivity.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/DemoActivity.java
deleted file mode 100644
index 970bd9b03..000000000
--- a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/DemoActivity.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package jp.xenia.emulator;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class DemoActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_demo);
- }
-}
\ No newline at end of file
diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java
new file mode 100644
index 000000000..a0dd36f0e
--- /dev/null
+++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java
@@ -0,0 +1,8 @@
+package jp.xenia.emulator;
+
+public class WindowDemoActivity extends WindowedAppActivity {
+ @Override
+ protected String getWindowedAppIdentifier() {
+ return "xenia_ui_window_vulkan_demo";
+ }
+}
diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java
new file mode 100644
index 000000000..dd89881c3
--- /dev/null
+++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java
@@ -0,0 +1,45 @@
+package jp.xenia.emulator;
+
+import android.app.Activity;
+import android.content.res.AssetManager;
+import android.os.Bundle;
+import android.util.Log;
+
+public abstract class WindowedAppActivity extends Activity {
+ private static final String TAG = "WindowedAppActivity";
+
+ static {
+ // TODO(Triang3l): Move all demos to libxenia.so.
+ System.loadLibrary("xenia-ui-window-vulkan-demo");
+ }
+
+ private long mAppContext;
+
+ private native long initializeWindowedAppOnCreateNative(
+ String windowedAppIdentifier, AssetManager assetManager);
+
+ private native void onDestroyNative(long appContext);
+
+ protected abstract String getWindowedAppIdentifier();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mAppContext = initializeWindowedAppOnCreateNative(getWindowedAppIdentifier(), getAssets());
+ if (mAppContext == 0) {
+ Log.e(TAG, "Error initializing the windowed app");
+ finish();
+ return;
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (mAppContext != 0) {
+ onDestroyNative(mAppContext);
+ }
+ mAppContext = 0;
+ super.onDestroy();
+ }
+}
diff --git a/android/android_studio_project/app/src/main/res/layout/activity_demo.xml b/android/android_studio_project/app/src/main/res/layout/activity_window_demo.xml
similarity index 76%
rename from android/android_studio_project/app/src/main/res/layout/activity_demo.xml
rename to android/android_studio_project/app/src/main/res/layout/activity_window_demo.xml
index ed5456938..79f49f81a 100644
--- a/android/android_studio_project/app/src/main/res/layout/activity_demo.xml
+++ b/android/android_studio_project/app/src/main/res/layout/activity_window_demo.xml
@@ -3,6 +3,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context="jp.xenia.emulator.DemoActivity">
+ tools:context="jp.xenia.emulator.WindowDemoActivity">
\ No newline at end of file
diff --git a/src/xenia/ui/windowed_app.cc b/src/xenia/ui/windowed_app.cc
new file mode 100644
index 000000000..8e19674ec
--- /dev/null
+++ b/src/xenia/ui/windowed_app.cc
@@ -0,0 +1,25 @@
+/**
+ ******************************************************************************
+ * Xenia : Xbox 360 Emulator Research Project *
+ ******************************************************************************
+ * Copyright 2021 Ben Vanik. All rights reserved. *
+ * Released under the BSD license - see LICENSE in the root for more details. *
+ ******************************************************************************
+ */
+
+#include "xenia/ui/windowed_app.h"
+
+#include
+#include
+
+namespace xe {
+namespace ui {
+
+#if XE_UI_WINDOWED_APPS_IN_LIBRARY
+// A zero-initialized pointer to remove dependence on the initialization order
+// of the map relatively to the app creator proxies.
+std::unordered_map* WindowedApp::creators_;
+#endif // XE_UI_WINDOWED_APPS_IN_LIBRARY
+
+} // namespace ui
+} // namespace xe
diff --git a/src/xenia/ui/windowed_app.h b/src/xenia/ui/windowed_app.h
index b521a759e..89d4eff1f 100644
--- a/src/xenia/ui/windowed_app.h
+++ b/src/xenia/ui/windowed_app.h
@@ -13,15 +13,17 @@
#include
#include
#include
+#include
+#include
#include
+#include "xenia/base/assert.h"
#include "xenia/base/platform.h"
#include "xenia/ui/windowed_app_context.h"
#if XE_PLATFORM_ANDROID
-#include
-
-#include "xenia/ui/windowed_app_context_android.h"
+// Multiple apps in a single library instead of separate executables.
+#define XE_UI_WINDOWED_APPS_IN_LIBRARY 1
#endif
namespace xe {
@@ -36,6 +38,9 @@ class WindowedApp {
// initialization of platform-specific parts, should preferably be as simple
// as possible).
+ using Creator = std::unique_ptr (*)(
+ xe::ui::WindowedAppContext& app_context);
+
WindowedApp(const WindowedApp& app) = delete;
WindowedApp& operator=(const WindowedApp& app) = delete;
virtual ~WindowedApp() = default;
@@ -101,27 +106,67 @@ class WindowedApp {
std::string name_;
std::string positional_options_usage_;
std::vector positional_options_;
+
+#if XE_UI_WINDOWED_APPS_IN_LIBRARY
+ public:
+ class CreatorRegistration {
+ public:
+ CreatorRegistration(const std::string_view identifier, Creator creator) {
+ if (!creators_) {
+ // Will be deleted by the last creator registration's destructor, no
+ // need for a library destructor.
+ creators_ = new std::unordered_map;
+ }
+ iterator_inserted_ = creators_->emplace(identifier, creator);
+ assert_true(iterator_inserted_.second);
+ }
+
+ ~CreatorRegistration() {
+ if (iterator_inserted_.second) {
+ creators_->erase(iterator_inserted_.first);
+ if (creators_->empty()) {
+ delete creators_;
+ }
+ }
+ }
+
+ private:
+ std::pair::iterator, bool>
+ iterator_inserted_;
+ };
+
+ static Creator GetCreator(const std::string& identifier) {
+ if (!creators_) {
+ return nullptr;
+ }
+ auto it = creators_->find(identifier);
+ return it != creators_->end() ? it->second : nullptr;
+ }
+
+ private:
+ static std::unordered_map* creators_;
+#endif // XE_UI_WINDOWED_APPS_IN_LIBRARY
};
-#if XE_PLATFORM_ANDROID
-// Multiple apps in a single library. ANativeActivity_onCreate chosen via
-// android.app.func_name of the NativeActivity of each app.
-#define XE_DEFINE_WINDOWED_APP(export_name, creator) \
- __attribute__((visibility("default"))) extern "C" void export_name( \
- ANativeActivity* activity, void* saved_state, size_t saved_state_size) { \
- xe::ui::AndroidWindowedAppContext::StartAppOnActivityCreate( \
- activity, saved_state, saved_state_size, creator); \
+#if XE_UI_WINDOWED_APPS_IN_LIBRARY
+// Multiple apps in a single library.
+#define XE_DEFINE_WINDOWED_APP(identifier, creator) \
+ namespace xe { \
+ namespace ui { \
+ namespace windowed_app_creator_registrations { \
+ xe::ui::WindowedApp::CreatorRegistration identifier(#identifier, creator); \
+ } \
+ } \
}
#else
// Separate executables for each app.
std::unique_ptr (*GetWindowedAppCreator())(
WindowedAppContext& app_context);
-#define XE_DEFINE_WINDOWED_APP(export_name, creator) \
- std::unique_ptr (*xe::ui::GetWindowedAppCreator())( \
- xe::ui::WindowedAppContext & app_context) { \
- return creator; \
+#define XE_DEFINE_WINDOWED_APP(identifier, creator) \
+ xe::ui::WindowedApp::Creator xe::ui::GetWindowedAppCreator() { \
+ return creator; \
}
-#endif
+#endif // XE_UI_WINDOWED_APPS_IN_LIBRARY
} // namespace ui
} // namespace xe
diff --git a/src/xenia/ui/windowed_app_context_android.cc b/src/xenia/ui/windowed_app_context_android.cc
index fcab4f5fd..5af4efad6 100644
--- a/src/xenia/ui/windowed_app_context_android.cc
+++ b/src/xenia/ui/windowed_app_context_android.cc
@@ -9,10 +9,12 @@
#include "xenia/ui/windowed_app_context_android.h"
+#include
#include
+#include
#include
-#include
#include
+#include
#include
#include
#include
@@ -25,30 +27,6 @@
namespace xe {
namespace ui {
-void AndroidWindowedAppContext::StartAppOnActivityCreate(
- ANativeActivity* activity, [[maybe_unused]] void* saved_state,
- [[maybe_unused]] size_t saved_state_size,
- std::unique_ptr (*app_creator)(
- WindowedAppContext& app_context)) {
- // TODO(Triang3l): Pass the launch options from the Intent or the saved
- // instance state.
- AndroidWindowedAppContext* app_context = new AndroidWindowedAppContext;
- if (!app_context->Initialize(activity)) {
- delete app_context;
- ANativeActivity_finish(activity);
- return;
- }
- // The pointer is now held by the Activity as its ANativeActivity::instance,
- // until the destruction.
- if (!app_context->InitializeApp(app_creator)) {
- // InitializeApp might have sent commands to the UI thread looper callback
- // pipe, perform deferred destruction.
- app_context->RequestDestruction();
- ANativeActivity_finish(activity);
- return;
- }
-}
-
void AndroidWindowedAppContext::NotifyUILoopOfPendingFunctions() {
// Don't check ui_thread_looper_callback_registered_, as it's owned
// exclusively by the UI thread, while this may be called by any, and in case
@@ -69,22 +47,145 @@ void AndroidWindowedAppContext::NotifyUILoopOfPendingFunctions() {
void AndroidWindowedAppContext::PlatformQuitFromUIThread() {
// All the shutdown will be done in onDestroy of the activity.
- ANativeActivity_finish(activity_);
+ if (activity_ && activity_method_finish_) {
+ ui_thread_jni_env_->CallVoidMethod(activity_, activity_method_finish_);
+ }
+}
+
+AndroidWindowedAppContext*
+AndroidWindowedAppContext::JniActivityInitializeWindowedAppOnCreate(
+ JNIEnv* jni_env, jobject activity, jstring windowed_app_identifier,
+ jobject asset_manager) {
+ WindowedApp::Creator app_creator;
+ {
+ const char* windowed_app_identifier_c_str =
+ jni_env->GetStringUTFChars(windowed_app_identifier, nullptr);
+ if (!windowed_app_identifier_c_str) {
+ __android_log_write(
+ ANDROID_LOG_ERROR, "AndroidWindowedAppContext",
+ "Failed to get the UTF-8 string for the windowed app identifier");
+ return nullptr;
+ }
+ app_creator = WindowedApp::GetCreator(windowed_app_identifier_c_str);
+ if (!app_creator) {
+ __android_log_print(ANDROID_LOG_ERROR, "AndroidWindowedAppContext",
+ "Failed to get the creator for the windowed app %s",
+ windowed_app_identifier_c_str);
+ jni_env->ReleaseStringUTFChars(windowed_app_identifier,
+ windowed_app_identifier_c_str);
+ return nullptr;
+ }
+ jni_env->ReleaseStringUTFChars(windowed_app_identifier,
+ windowed_app_identifier_c_str);
+ }
+
+ AndroidWindowedAppContext* app_context = new AndroidWindowedAppContext;
+ if (!app_context->Initialize(jni_env, activity, asset_manager)) {
+ delete app_context;
+ return nullptr;
+ }
+
+ if (!app_context->InitializeApp(app_creator)) {
+ // InitializeApp might have sent commands to the UI thread looper callback
+ // pipe, perform deferred destruction.
+ app_context->RequestDestruction();
+ return nullptr;
+ }
+
+ return app_context;
+}
+
+void AndroidWindowedAppContext::JniActivityOnDestroy() {
+ if (app_) {
+ app_->InvokeOnDestroy();
+ app_.reset();
+ }
+ RequestDestruction();
}
AndroidWindowedAppContext::~AndroidWindowedAppContext() { Shutdown(); }
-bool AndroidWindowedAppContext::Initialize(ANativeActivity* activity) {
- int32_t api_level;
- {
- AConfiguration* configuration = AConfiguration_new();
- AConfiguration_fromAssetManager(configuration, activity->assetManager);
- api_level = AConfiguration_getSdkVersion(configuration);
- AConfiguration_delete(configuration);
+bool AndroidWindowedAppContext::Initialize(JNIEnv* ui_thread_jni_env,
+ jobject activity,
+ jobject asset_manager) {
+ // Xenia logging is not initialized yet - use __android_log_write or
+ // __android_log_print until InitializeAndroidAppFromMainThread is done.
+
+ ui_thread_jni_env_ = ui_thread_jni_env;
+
+ // Initialize the asset manager for retrieving the current configuration.
+ asset_manager_jobject_ = ui_thread_jni_env_->NewGlobalRef(asset_manager);
+ if (!asset_manager_jobject_) {
+ __android_log_write(
+ ANDROID_LOG_ERROR, "AndroidWindowedAppContext",
+ "Failed to create a global reference to the asset manager");
+ Shutdown();
+ return false;
}
- xe::InitializeAndroidAppFromMainThread(api_level);
+ asset_manager_ =
+ AAssetManager_fromJava(ui_thread_jni_env_, asset_manager_jobject_);
+ if (!asset_manager_) {
+ __android_log_write(ANDROID_LOG_ERROR, "AndroidWindowedAppContext",
+ "Failed to create get the AAssetManager");
+ Shutdown();
+ return false;
+ }
+
+ // Get the initial configuration.
+ configuration_ = AConfiguration_new();
+ if (!configuration_) {
+ __android_log_write(ANDROID_LOG_ERROR, "AndroidWindowedAppContext",
+ "Failed to create an AConfiguration");
+ Shutdown();
+ return false;
+ }
+ AConfiguration_fromAssetManager(configuration_, asset_manager_);
+
+ // Initialize Xenia globals that may depend on the API level, as well as
+ // logging.
+ xe::InitializeAndroidAppFromMainThread(
+ AConfiguration_getSdkVersion(configuration_));
android_base_initialized_ = true;
+ // Initialize interfacing with the WindowedAppActivity.
+ activity_ = ui_thread_jni_env_->NewGlobalRef(activity);
+ if (!activity_) {
+ XELOGE(
+ "AndroidWindowedAppContext: Failed to create a global reference to the "
+ "activity");
+ Shutdown();
+ return false;
+ }
+ {
+ jclass activity_class_local_ref =
+ ui_thread_jni_env_->GetObjectClass(activity);
+ if (!activity_class_local_ref) {
+ XELOGE("AndroidWindowedAppContext: Failed to get the activity class");
+ Shutdown();
+ return false;
+ }
+ activity_class_ = reinterpret_cast(ui_thread_jni_env_->NewGlobalRef(
+ reinterpret_cast(activity_class_local_ref)));
+ ui_thread_jni_env_->DeleteLocalRef(
+ reinterpret_cast(activity_class_local_ref));
+ }
+ if (!activity_class_) {
+ XELOGE(
+ "AndroidWindowedAppContext: Failed to create a global reference to the "
+ "activity class");
+ Shutdown();
+ return false;
+ }
+ bool activity_ids_obtained = true;
+ activity_ids_obtained &=
+ (activity_method_finish_ = ui_thread_jni_env_->GetMethodID(
+ activity_class_, "finish", "()V")) != nullptr;
+ if (!activity_ids_obtained) {
+ XELOGE("AndroidWindowedAppContext: Failed to get the activity class IDs");
+ Shutdown();
+ return false;
+ }
+
// Initialize sending commands to the UI thread looper callback, for
// requesting function calls in the UI thread.
ui_thread_looper_ = ALooper_forThread();
@@ -117,10 +218,6 @@ bool AndroidWindowedAppContext::Initialize(ANativeActivity* activity) {
}
ui_thread_looper_callback_registered_ = true;
- activity_ = activity;
- activity_->instance = this;
- activity_->callbacks->onDestroy = OnActivityDestroy;
-
return true;
}
@@ -135,12 +232,6 @@ void AndroidWindowedAppContext::Shutdown() {
assert_null(activity_window_);
activity_window_ = nullptr;
- if (activity_) {
- activity_->callbacks->onDestroy = nullptr;
- activity_->instance = nullptr;
- activity_ = nullptr;
- }
-
if (ui_thread_looper_callback_registered_) {
ALooper_removeFd(ui_thread_looper_, ui_thread_looper_callback_pipe_[0]);
ui_thread_looper_callback_registered_ = false;
@@ -157,10 +248,34 @@ void AndroidWindowedAppContext::Shutdown() {
ui_thread_looper_ = nullptr;
}
+ activity_method_finish_ = nullptr;
+ if (activity_class_) {
+ ui_thread_jni_env_->DeleteGlobalRef(
+ reinterpret_cast(activity_class_));
+ activity_class_ = nullptr;
+ }
+ if (activity_) {
+ ui_thread_jni_env_->DeleteGlobalRef(activity_);
+ activity_ = nullptr;
+ }
+
if (android_base_initialized_) {
xe::ShutdownAndroidAppFromMainThread();
android_base_initialized_ = false;
}
+
+ if (configuration_) {
+ AConfiguration_delete(configuration_);
+ configuration_ = nullptr;
+ }
+
+ asset_manager_ = nullptr;
+ if (asset_manager_jobject_) {
+ ui_thread_jni_env_->DeleteGlobalRef(asset_manager_jobject_);
+ asset_manager_jobject_ = nullptr;
+ }
+
+ ui_thread_jni_env_ = nullptr;
}
void AndroidWindowedAppContext::RequestDestruction() {
@@ -260,15 +375,26 @@ bool AndroidWindowedAppContext::InitializeApp(std::unique_ptr (
return true;
}
-void AndroidWindowedAppContext::OnActivityDestroy(ANativeActivity* activity) {
- auto& app_context =
- *static_cast(activity->instance);
- if (app_context.app_) {
- app_context.app_->InvokeOnDestroy();
- app_context.app_.reset();
- }
- app_context.RequestDestruction();
-}
-
} // namespace ui
} // namespace xe
+
+extern "C" {
+
+JNIEXPORT jlong JNICALL
+Java_jp_xenia_emulator_WindowedAppActivity_initializeWindowedAppOnCreateNative(
+ JNIEnv* jni_env, jobject activity, jstring windowed_app_identifier,
+ jobject asset_manager) {
+ return reinterpret_cast(
+ xe::ui::AndroidWindowedAppContext ::
+ JniActivityInitializeWindowedAppOnCreate(
+ jni_env, activity, windowed_app_identifier, asset_manager));
+}
+
+JNIEXPORT void JNICALL
+Java_jp_xenia_emulator_WindowedAppActivity_onDestroyNative(
+ JNIEnv* jni_env, jobject activity, jlong app_context_ptr) {
+ reinterpret_cast(app_context_ptr)
+ ->JniActivityOnDestroy();
+}
+
+} // extern "C"
diff --git a/src/xenia/ui/windowed_app_context_android.h b/src/xenia/ui/windowed_app_context_android.h
index 64e45372d..91cd10427 100644
--- a/src/xenia/ui/windowed_app_context_android.h
+++ b/src/xenia/ui/windowed_app_context_android.h
@@ -10,8 +10,10 @@
#ifndef XENIA_UI_WINDOWED_APP_CONTEXT_ANDROID_H_
#define XENIA_UI_WINDOWED_APP_CONTEXT_ANDROID_H_
+#include
+#include
#include
-#include
+#include
#include
#include
@@ -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 (*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 (*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 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 app_;