From 277f1608bea9f018c65e690f797fd18146a20b07 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 8 Mar 2022 11:44:31 -0600 Subject: [PATCH] Store last data received from WindowInfosListener Store the last data received from WindowInfoListener on the client so it can easily be retrieved when a new caller registers to listen for updates. This will help with accessibility since they won't need to register their listener all the time and instead just get the last data that was sent, immediately. From the system server process, the data is constantly being updated because WindowInfo is sent to InputDispatcher when any geometry in SF changes. If a different process registers for the WindowInfoListener, it's possible the initial data will be empty since we won't explicitly request the latest data immediately. Bug: 222767081 Test: Accessibility register only when enabled Change-Id: Ib87edde7a14be8584504d5d8d6c41f20bde5c698 --- .../android/window/WindowInfosListener.java | 11 ++- .../android_window_WindowInfosListener.cpp | 70 +++++++++++++------ .../wm/AccessibilityWindowsPopulator.java | 7 +- 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/core/java/android/window/WindowInfosListener.java b/core/java/android/window/WindowInfosListener.java index 9d4545c6e25d8..8db5a5eb0e471 100644 --- a/core/java/android/window/WindowInfosListener.java +++ b/core/java/android/window/WindowInfosListener.java @@ -17,6 +17,7 @@ package android.window; import android.graphics.Matrix; +import android.util.Pair; import android.util.Size; import android.view.InputWindowHandle; @@ -47,9 +48,13 @@ public abstract class WindowInfosListener { /** * Register the WindowInfosListener. + * + * @return The cached values for InputWindowHandles and DisplayInfos. This is the last updated + * value that was sent from SurfaceFlinger to this particular process. If there was nothing + * registered previously, then the data can be empty. */ - public void register() { - nativeRegister(mNativeListener); + public Pair register() { + return nativeRegister(mNativeListener); } /** @@ -60,7 +65,7 @@ public abstract class WindowInfosListener { } private static native long nativeCreate(WindowInfosListener thiz); - private static native void nativeRegister(long ptr); + private static native Pair nativeRegister(long ptr); private static native void nativeUnregister(long ptr); private static native long nativeGetFinalizer(); diff --git a/core/jni/android_window_WindowInfosListener.cpp b/core/jni/android_window_WindowInfosListener.cpp index 08c9f20b0815d..aae2549df4290 100644 --- a/core/jni/android_window_WindowInfosListener.cpp +++ b/core/jni/android_window_WindowInfosListener.cpp @@ -44,6 +44,11 @@ static struct { jmethodID ctor; } gDisplayInfoClassInfo; +static struct { + jclass clazz; + jmethodID ctor; +} gPairClassInfo; + static jclass gInputWindowHandleClass; jobject fromDisplayInfo(JNIEnv* env, gui::DisplayInfo displayInfo) { @@ -57,6 +62,30 @@ jobject fromDisplayInfo(JNIEnv* env, gui::DisplayInfo displayInfo) { displayInfo.logicalHeight, matrixObj.get()); } +static jobjectArray fromWindowInfos(JNIEnv* env, const std::vector& windowInfos) { + jobjectArray jWindowHandlesArray = + env->NewObjectArray(windowInfos.size(), gInputWindowHandleClass, nullptr); + for (int i = 0; i < windowInfos.size(); i++) { + ScopedLocalRef + jWindowHandle(env, + android_view_InputWindowHandle_fromWindowInfo(env, windowInfos[i])); + env->SetObjectArrayElement(jWindowHandlesArray, i, jWindowHandle.get()); + } + + return jWindowHandlesArray; +} + +static jobjectArray fromDisplayInfos(JNIEnv* env, const std::vector& displayInfos) { + jobjectArray jDisplayInfoArray = + env->NewObjectArray(displayInfos.size(), gDisplayInfoClassInfo.clazz, nullptr); + for (int i = 0; i < displayInfos.size(); i++) { + ScopedLocalRef jDisplayInfo(env, fromDisplayInfo(env, displayInfos[i])); + env->SetObjectArrayElement(jDisplayInfoArray, i, jDisplayInfo.get()); + } + + return jDisplayInfoArray; +} + struct WindowInfosListener : public gui::WindowInfosListener { WindowInfosListener(JNIEnv* env, jobject listener) : mListener(env->NewWeakGlobalRef(listener)) {} @@ -72,26 +101,8 @@ struct WindowInfosListener : public gui::WindowInfosListener { return; } - ScopedLocalRef - jWindowHandlesArray(env, - env->NewObjectArray(windowInfos.size(), gInputWindowHandleClass, - nullptr)); - for (int i = 0; i < windowInfos.size(); i++) { - ScopedLocalRef - jWindowHandle(env, - android_view_InputWindowHandle_fromWindowInfo(env, - windowInfos[i])); - env->SetObjectArrayElement(jWindowHandlesArray.get(), i, jWindowHandle.get()); - } - - ScopedLocalRef - jDisplayInfoArray(env, - env->NewObjectArray(displayInfos.size(), - gDisplayInfoClassInfo.clazz, nullptr)); - for (int i = 0; i < displayInfos.size(); i++) { - ScopedLocalRef jDisplayInfo(env, fromDisplayInfo(env, displayInfos[i])); - env->SetObjectArrayElement(jDisplayInfoArray.get(), i, jDisplayInfo.get()); - } + ScopedLocalRef jWindowHandlesArray(env, fromWindowInfos(env, windowInfos)); + ScopedLocalRef jDisplayInfoArray(env, fromDisplayInfos(env, displayInfos)); env->CallVoidMethod(listener, gListenerClassInfo.onWindowInfosChanged, jWindowHandlesArray.get(), jDisplayInfoArray.get()); @@ -124,9 +135,16 @@ void destroyNativeService(void* ptr) { listener->decStrong((void*)nativeCreate); } -void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) { +jobject nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) { sp listener = reinterpret_cast(ptr); - SurfaceComposerClient::getDefault()->addWindowInfosListener(listener); + std::pair, std::vector> initialInfo; + SurfaceComposerClient::getDefault()->addWindowInfosListener(listener, &initialInfo); + + ScopedLocalRef jWindowHandlesArray(env, fromWindowInfos(env, initialInfo.first)); + ScopedLocalRef jDisplayInfoArray(env, fromDisplayInfos(env, initialInfo.second)); + + return env->NewObject(gPairClassInfo.clazz, gPairClassInfo.ctor, jWindowHandlesArray.get(), + jDisplayInfoArray.get()); } void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) { @@ -141,7 +159,7 @@ static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) { const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ {"nativeCreate", "(Landroid/window/WindowInfosListener;)J", (void*)nativeCreate}, - {"nativeRegister", "(J)V", (void*)nativeRegister}, + {"nativeRegister", "(J)Landroid/util/Pair;", (void*)nativeRegister}, {"nativeUnregister", "(J)V", (void*)nativeUnregister}, {"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer}}; @@ -166,6 +184,12 @@ int register_android_window_WindowInfosListener(JNIEnv* env) { gDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); gDisplayInfoClassInfo.ctor = env->GetMethodID(gDisplayInfoClassInfo.clazz, "", "(IIILandroid/graphics/Matrix;)V"); + + clazz = env->FindClass("android/util/Pair"); + gPairClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); + gPairClassInfo.ctor = env->GetMethodID(gPairClassInfo.clazz, "", + "(Ljava/lang/Object;Ljava/lang/Object;)V"); + return 0; } diff --git a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java index d4648a4f313c9..11ddac6a97403 100644 --- a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java +++ b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java @@ -30,6 +30,7 @@ import android.os.IBinder; import android.os.InputConfig; import android.os.Looper; import android.os.Message; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.view.IWindow; @@ -94,8 +95,6 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { mService = service; mAccessibilityController = accessibilityController; mHandler = new MyHandler(mService.mH.getLooper()); - - register(); } /** @@ -219,8 +218,10 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { } mWindowsNotificationEnabled = register; if (mWindowsNotificationEnabled) { - populateVisibleWindowHandlesAndNotifyWindowsChangeIfNeeded(); + Pair info = register(); + onWindowInfosChangedInternal(info.first, info.second); } else { + unregister(); releaseResources(); } }