mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-01 12:46:12 +00:00
aux/android: Refactor MonadoView
This commit is contained in:
parent
7c02d466e2
commit
cf7e44b710
|
@ -9,42 +9,44 @@
|
|||
*/
|
||||
|
||||
#include "android_custom_surface.h"
|
||||
#include "android_globals.h"
|
||||
#include "android_load_class.hpp"
|
||||
|
||||
#include "xrt/xrt_config_android.h"
|
||||
#include "util/u_logging.h"
|
||||
|
||||
#include "wrap/android.app.h"
|
||||
#include "wrap/android.content.h"
|
||||
#include "wrap/android.hardware.display.h"
|
||||
#include "wrap/android.view.h"
|
||||
#include "org.freedesktop.monado.auxiliary.hpp"
|
||||
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
|
||||
using wrap::android::app::Activity;
|
||||
using wrap::android::content::Context;
|
||||
using wrap::android::hardware::display::DisplayManager;
|
||||
using wrap::android::view::Display;
|
||||
using wrap::android::view::SurfaceHolder;
|
||||
using wrap::android::view::WindowManager_LayoutParams;
|
||||
using wrap::org::freedesktop::monado::auxiliary::MonadoView;
|
||||
using xrt::auxiliary::android::loadClassFromRuntimeApk;
|
||||
|
||||
|
||||
struct android_custom_surface
|
||||
{
|
||||
explicit android_custom_surface(jobject act);
|
||||
explicit android_custom_surface();
|
||||
~android_custom_surface();
|
||||
Activity activity{};
|
||||
|
||||
MonadoView monadoView{};
|
||||
jni::Class monadoViewClass{};
|
||||
};
|
||||
|
||||
|
||||
android_custom_surface::android_custom_surface(jobject act) : activity(act) {}
|
||||
android_custom_surface::android_custom_surface() {}
|
||||
|
||||
android_custom_surface::~android_custom_surface()
|
||||
{
|
||||
// Tell Java that native code is done with this.
|
||||
try {
|
||||
MonadoView::removeFromWindow(monadoView);
|
||||
if (!monadoView.isNull()) {
|
||||
monadoView.markAsDiscardedByNative();
|
||||
}
|
||||
|
@ -55,11 +57,11 @@ android_custom_surface::~android_custom_surface()
|
|||
}
|
||||
|
||||
struct android_custom_surface *
|
||||
android_custom_surface_async_start(struct _JavaVM *vm, void *activity)
|
||||
android_custom_surface_async_start(struct _JavaVM *vm, void *context, int32_t display_id)
|
||||
{
|
||||
jni::init(vm);
|
||||
try {
|
||||
auto clazz = loadClassFromRuntimeApk((jobject)activity, MonadoView::getFullyQualifiedTypeName());
|
||||
auto clazz = loadClassFromRuntimeApk((jobject)context, MonadoView::getFullyQualifiedTypeName());
|
||||
if (clazz.isNull()) {
|
||||
U_LOG_E("Could not load class '%s' from package '%s'", MonadoView::getFullyQualifiedTypeName(),
|
||||
XRT_ANDROID_PACKAGE);
|
||||
|
@ -68,8 +70,7 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity)
|
|||
|
||||
// Teach the wrapper our class before we start to use it.
|
||||
MonadoView::staticInitClass((jclass)clazz.object().getHandle());
|
||||
std::unique_ptr<android_custom_surface> ret =
|
||||
std::make_unique<android_custom_surface>((jobject)activity);
|
||||
std::unique_ptr<android_custom_surface> ret = std::make_unique<android_custom_surface>();
|
||||
|
||||
// the 0 is to avoid this being considered "temporary" and to
|
||||
// create a global ref.
|
||||
|
@ -86,7 +87,26 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
ret->monadoView = MonadoView::attachToActivity(ret->activity, ret.get());
|
||||
Context ctx = Context((jobject)context);
|
||||
Context displayContext;
|
||||
int32_t type = 0;
|
||||
// Not focusable
|
||||
int32_t flags =
|
||||
WindowManager_LayoutParams::FLAG_FULLSCREEN() | WindowManager_LayoutParams::FLAG_NOT_FOCUSABLE();
|
||||
|
||||
if (android_globals_is_instance_of_activity(android_globals_get_vm(), context)) {
|
||||
displayContext = ctx;
|
||||
type = WindowManager_LayoutParams::TYPE_APPLICATION();
|
||||
} else {
|
||||
// Out of process mode, determine which display should be used.
|
||||
DisplayManager dm = DisplayManager(ctx.getSystemService(Context::DISPLAY_SERVICE()));
|
||||
Display display = dm.getDisplay(display_id);
|
||||
displayContext = ctx.createDisplayContext(display);
|
||||
type = WindowManager_LayoutParams::TYPE_APPLICATION_OVERLAY();
|
||||
}
|
||||
|
||||
WindowManager_LayoutParams lp = WindowManager_LayoutParams::construct(type, flags);
|
||||
ret->monadoView = MonadoView::attachToWindow(displayContext, ret.get(), lp);
|
||||
|
||||
return ret.release();
|
||||
} catch (std::exception const &e) {
|
||||
|
@ -99,7 +119,6 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
android_custom_surface_destroy(struct android_custom_surface **ptr_custom_surface)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Functions for adding a new Surface to an activity and otherwise
|
||||
* @brief Functions for adding a new Surface to a window and otherwise
|
||||
* interacting with an Android View.
|
||||
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||
* @ingroup aux_android
|
||||
|
@ -36,7 +36,7 @@ struct xrt_android_display_metrics
|
|||
};
|
||||
|
||||
/*!
|
||||
* Opaque type representing a custom surface added to an activity, and the async
|
||||
* Opaque type representing a custom surface added to a window, and the async
|
||||
* operation to perform this adding.
|
||||
*
|
||||
* @note You must keep this around for as long as you're using the surface.
|
||||
|
@ -44,7 +44,7 @@ struct xrt_android_display_metrics
|
|||
struct android_custom_surface;
|
||||
|
||||
/*!
|
||||
* Start adding a custom surface to an activity.
|
||||
* Start adding a custom surface to a window.
|
||||
*
|
||||
* This is an asynchronous operation, so this creates an opaque pointer for you
|
||||
* to check on the results and maintain a reference to the result.
|
||||
|
@ -52,8 +52,8 @@ struct android_custom_surface;
|
|||
* Uses org.freedesktop.monado.auxiliary.MonadoView
|
||||
*
|
||||
* @param vm Java VM pointer
|
||||
* @param activity An android.app.Activity jobject, cast to
|
||||
* `void *`.
|
||||
* @param context An android.content.Context jobject, cast to `void *`.
|
||||
* @param display_id Id of the display that the surface is attached to.
|
||||
*
|
||||
* @return An opaque handle for monitoring this operation and referencing the
|
||||
* surface, or NULL if there was an error.
|
||||
|
@ -61,7 +61,7 @@ struct android_custom_surface;
|
|||
* @public @memberof android_custom_surface
|
||||
*/
|
||||
struct android_custom_surface *
|
||||
android_custom_surface_async_start(struct _JavaVM *vm, void *activity);
|
||||
android_custom_surface_async_start(struct _JavaVM *vm, void *context, int32_t display_id);
|
||||
|
||||
/*!
|
||||
* Destroy the native handle for the custom surface.
|
||||
|
|
|
@ -14,10 +14,12 @@ namespace wrap {
|
|||
namespace org::freedesktop::monado::auxiliary {
|
||||
MonadoView::Meta::Meta(jni::jclass clazz)
|
||||
: MetaBase(MonadoView::getTypeName(), clazz),
|
||||
attachToActivity(classRef().getStaticMethod(
|
||||
"attachToActivity", "(Landroid/app/Activity;J)Lorg/freedesktop/monado/auxiliary/MonadoView;")),
|
||||
attachToActivity1(classRef().getStaticMethod(
|
||||
"attachToActivity", "(Landroid/app/Activity;)Lorg/freedesktop/monado/auxiliary/MonadoView;")),
|
||||
attachToWindow(classRef().getStaticMethod(
|
||||
"attachToWindow",
|
||||
"(Landroid/content/Context;JLandroid/view/WindowManager$LayoutParams;)Lorg/freedesktop/monado/"
|
||||
"auxiliary/MonadoView;")),
|
||||
removeFromWindow(
|
||||
classRef().getStaticMethod("removeFromWindow", "(Lorg/freedesktop/monado/auxiliary/MonadoView;)V")),
|
||||
getDisplayMetrics(classRef().getStaticMethod("getDisplayMetrics",
|
||||
"(Landroid/content/Context;)Landroid/util/DisplayMetrics;")),
|
||||
getDisplayRefreshRate(
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace android::content {
|
|||
|
||||
namespace android::view {
|
||||
class SurfaceHolder;
|
||||
class WindowManager_LayoutParams;
|
||||
} // namespace android::view
|
||||
|
||||
namespace org::freedesktop::monado::auxiliary {
|
||||
|
@ -54,29 +55,33 @@ namespace org::freedesktop::monado::auxiliary {
|
|||
}
|
||||
|
||||
/*!
|
||||
* Wrapper for the attachToActivity static method
|
||||
* Wrapper for the attachToWindow static method
|
||||
*
|
||||
* Java prototype:
|
||||
* `public static org.freedesktop.monado.auxiliary.MonadoView attachToActivity(android.app.Activity,
|
||||
* long);`
|
||||
* `public static org.freedesktop.monado.auxiliary.MonadoView attachToActivity(android.content.Context,
|
||||
* long, android.view.WindowManager.LayoutParams);`
|
||||
*
|
||||
* JNI signature: (Landroid/app/Activity;J)Lorg/freedesktop/monado/auxiliary/MonadoView;
|
||||
* JNI signature:
|
||||
* (Landroid/content/Context;JLandroid/view/WindowManager$LayoutParams;)Lorg/freedesktop/monado/auxiliary/MonadoView;
|
||||
*
|
||||
*/
|
||||
static MonadoView
|
||||
attachToActivity(android::app::Activity const &activity, void *nativePointer);
|
||||
attachToWindow(android::content::Context const &displayContext,
|
||||
void *nativePointer,
|
||||
android::view::WindowManager_LayoutParams const &lp);
|
||||
|
||||
/*!
|
||||
* Wrapper for the attachToActivity static method
|
||||
* Wrapper for the removeFromWindow static method
|
||||
*
|
||||
* Java prototype:
|
||||
* `public static org.freedesktop.monado.auxiliary.MonadoView attachToActivity(android.app.Activity);`
|
||||
* `public static void removeFromWindow(android.content.Context,
|
||||
* org.freedesktop.monado.auxiliary.MonadoView, int);`
|
||||
*
|
||||
* JNI signature: (Landroid/app/Activity;)Lorg/freedesktop/monado/auxiliary/MonadoView;
|
||||
* JNI signature: (Landroid/content/Context;Lorg/freedesktop/monado/auxiliary/MonadoView;I)V
|
||||
*
|
||||
*/
|
||||
static MonadoView
|
||||
attachToActivity(android::app::Activity const &activity);
|
||||
static void
|
||||
removeFromWindow(MonadoView const &view);
|
||||
|
||||
/*!
|
||||
* Wrapper for the getDisplayMetrics static method
|
||||
|
@ -153,8 +158,8 @@ namespace org::freedesktop::monado::auxiliary {
|
|||
*/
|
||||
struct Meta : public MetaBase
|
||||
{
|
||||
jni::method_t attachToActivity;
|
||||
jni::method_t attachToActivity1;
|
||||
jni::method_t attachToWindow;
|
||||
jni::method_t removeFromWindow;
|
||||
jni::method_t getDisplayMetrics;
|
||||
jni::method_t getDisplayRefreshRate;
|
||||
jni::method_t getNativePointer;
|
||||
|
|
|
@ -18,18 +18,19 @@
|
|||
namespace wrap {
|
||||
namespace org::freedesktop::monado::auxiliary {
|
||||
inline MonadoView
|
||||
MonadoView::attachToActivity(android::app::Activity const &activity, void *nativePointer)
|
||||
MonadoView::attachToWindow(android::content::Context const &displayContext,
|
||||
void *nativePointer,
|
||||
wrap::android::view::WindowManager_LayoutParams const &lp)
|
||||
{
|
||||
return MonadoView(Meta::data().clazz().call<jni::Object>(
|
||||
Meta::data().attachToActivity, activity.object(),
|
||||
static_cast<long long>(reinterpret_cast<uintptr_t>(nativePointer))));
|
||||
Meta::data().attachToWindow, displayContext.object(),
|
||||
static_cast<long long>(reinterpret_cast<uintptr_t>(nativePointer)), lp.object()));
|
||||
}
|
||||
|
||||
inline MonadoView
|
||||
MonadoView::attachToActivity(android::app::Activity const &activity)
|
||||
inline void
|
||||
MonadoView::removeFromWindow(const MonadoView &view)
|
||||
{
|
||||
return MonadoView(
|
||||
Meta::data().clazz().call<jni::Object>(Meta::data().attachToActivity1, activity.object()));
|
||||
Meta::data().clazz().call<void>(Meta::data().removeFromWindow, view.object());
|
||||
}
|
||||
|
||||
inline jni::Object
|
||||
|
|
|
@ -11,7 +11,8 @@ package org.freedesktop.monado.auxiliary;
|
|||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
@ -29,10 +30,6 @@ public class MonadoView extends SurfaceView
|
|||
implements SurfaceHolder.Callback, SurfaceHolder.Callback2 {
|
||||
private static final String TAG = "MonadoView";
|
||||
|
||||
@NonNull private final Context context;
|
||||
|
||||
/// The activity we've connected to.
|
||||
@Nullable private final Activity activity;
|
||||
private final Object currentSurfaceHolderSync = new Object();
|
||||
|
||||
public int width = -1;
|
||||
|
@ -47,28 +44,19 @@ public class MonadoView extends SurfaceView
|
|||
|
||||
public MonadoView(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
Activity activity;
|
||||
|
||||
if (context instanceof Activity) {
|
||||
activity = (Activity) context;
|
||||
Activity activity = (Activity) context;
|
||||
systemUiController = new SystemUiController(activity.getWindow().getDecorView());
|
||||
systemUiController.hide();
|
||||
} else {
|
||||
activity = null;
|
||||
}
|
||||
this.activity = activity;
|
||||
SurfaceHolder surfaceHolder = getHolder();
|
||||
surfaceHolder.addCallback(this);
|
||||
}
|
||||
|
||||
public MonadoView(Activity activity) {
|
||||
super(activity);
|
||||
this.context = activity;
|
||||
this.activity = activity;
|
||||
systemUiController = new SystemUiController(activity.getWindow().getDecorView());
|
||||
systemUiController.hide();
|
||||
}
|
||||
private MonadoView(Context context, long nativePointer) {
|
||||
this(context);
|
||||
|
||||
private MonadoView(Activity activity, long nativePointer) {
|
||||
this(activity);
|
||||
nativeCounterpart = new NativeCounterpart(nativePointer);
|
||||
}
|
||||
|
||||
|
@ -76,25 +64,73 @@ public class MonadoView extends SurfaceView
|
|||
* Construct and start attaching a MonadoView to a client application.
|
||||
*
|
||||
* @param activity The activity to attach to.
|
||||
* @param nativePointer The native android_custom_surface pointer, cast to a long.
|
||||
* @return The MonadoView instance created and asynchronously attached.
|
||||
*/
|
||||
@NonNull @Keep
|
||||
@SuppressWarnings("deprecation")
|
||||
public static MonadoView attachToActivity(
|
||||
@NonNull final Activity activity, long nativePointer) {
|
||||
final MonadoView view = new MonadoView(activity, nativePointer);
|
||||
view.createSurfaceInActivity();
|
||||
public static MonadoView attachToActivity(@NonNull final Activity activity) {
|
||||
final MonadoView view = new MonadoView(activity);
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
||||
lp.flags =
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
attachToWindow(activity, view, lp);
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct and start attaching a MonadoView to window.
|
||||
*
|
||||
* @param displayContext Display context used for looking for target window.
|
||||
* @param nativePointer The native android_custom_surface pointer, cast to a long.
|
||||
* @param lp Layout parameters associated with view.
|
||||
* @return The MonadoView instance created and asynchronously attached.
|
||||
*/
|
||||
@NonNull @Keep
|
||||
public static MonadoView attachToActivity(@NonNull final Activity activity) {
|
||||
final MonadoView view = new MonadoView(activity);
|
||||
view.createSurfaceInActivity();
|
||||
public static MonadoView attachToWindow(
|
||||
@NonNull final Context displayContext,
|
||||
long nativePointer,
|
||||
WindowManager.LayoutParams lp)
|
||||
throws IllegalArgumentException {
|
||||
final MonadoView view = new MonadoView(displayContext, nativePointer);
|
||||
attachToWindow(displayContext, view, lp);
|
||||
return view;
|
||||
}
|
||||
|
||||
private static void attachToWindow(
|
||||
@NonNull final Context context,
|
||||
@NonNull MonadoView view,
|
||||
@NonNull WindowManager.LayoutParams lp) {
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
handler.post(
|
||||
() -> {
|
||||
Log.d(TAG, "Start adding view to window");
|
||||
WindowManager wm =
|
||||
(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
wm.addView(view, lp);
|
||||
|
||||
SystemUiController systemUiController = new SystemUiController(view);
|
||||
systemUiController.hide();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove given MonadoView from window.
|
||||
*
|
||||
* @param view The view to remove.
|
||||
*/
|
||||
@Keep
|
||||
public static void removeFromWindow(@NonNull MonadoView view) {
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
handler.post(
|
||||
() -> {
|
||||
Log.d(TAG, "Start removing view from window");
|
||||
WindowManager wm =
|
||||
(WindowManager)
|
||||
view.getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||
wm.removeView(view);
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull @Keep
|
||||
public static DisplayMetrics getDisplayMetrics(@NonNull Context context) {
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
|
@ -117,45 +153,6 @@ public class MonadoView extends SurfaceView
|
|||
return nativeCounterpart.getNativePointer();
|
||||
}
|
||||
|
||||
private void createSurfaceInActivity() {
|
||||
createSurfaceInActivity(false);
|
||||
}
|
||||
|
||||
/** @param focusable Indicates MonadoView should be focusable or not */
|
||||
private void createSurfaceInActivity(boolean focusable) {
|
||||
Log.i(TAG, "Starting to add a new surface!");
|
||||
activity.runOnUiThread(
|
||||
() -> {
|
||||
Log.i(TAG, "Starting runOnUiThread");
|
||||
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
WindowManager windowManager = activity.getWindowManager();
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
||||
if (focusable) {
|
||||
lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
} else {
|
||||
// There are 2 problems if view is focusable on all-in-one device:
|
||||
// 1. Navigation bar won't go away because view gets focus.
|
||||
// 2. Underlying activity lost focus and cannot receive input.
|
||||
lp.flags =
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
lp.layoutInDisplayCutoutMode =
|
||||
WindowManager.LayoutParams
|
||||
.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
}
|
||||
windowManager.addView(this, lp);
|
||||
if (focusable) {
|
||||
requestFocus();
|
||||
}
|
||||
SurfaceHolder surfaceHolder = getHolder();
|
||||
surfaceHolder.addCallback(this);
|
||||
Log.i(TAG, "Registered callbacks!");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Block up to a specified amount of time, waiting for the surfaceCreated callback to be fired
|
||||
* and populate the currentSurfaceHolder.
|
||||
|
|
|
@ -87,8 +87,9 @@ comp_window_android_update_window_title(struct comp_target *ct, const char *titl
|
|||
static struct ANativeWindow *
|
||||
_create_android_window(struct comp_window_android *cwa)
|
||||
{
|
||||
// 0 means default display
|
||||
cwa->custom_surface =
|
||||
android_custom_surface_async_start(android_globals_get_vm(), android_globals_get_activity());
|
||||
android_custom_surface_async_start(android_globals_get_vm(), android_globals_get_activity(), 0);
|
||||
if (cwa->custom_surface == NULL) {
|
||||
COMP_ERROR(cwa->base.base.c,
|
||||
"comp_window_android_create_surface: could not "
|
||||
|
|
Loading…
Reference in a new issue