Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c42a3c75 authored by Patrick Williams's avatar Patrick Williams Committed by Android (Google) Code Review
Browse files

Merge "Replace syncInputWindows with addWindowInfosReportedListener"

parents 184c5fe5 ea66a1e9
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -233,7 +233,8 @@ public final class SurfaceControl implements Parcelable {
    private static native boolean nativeGetProtectedContentSupport();
    private static native void nativeSetMetadata(long transactionObj, long nativeObject, int key,
            Parcel data);
    private static native void nativeSyncInputWindows(long transactionObj);
    private static native void nativeAddWindowInfosReportedListener(long transactionObj,
            Runnable listener);
    private static native boolean nativeGetDisplayBrightnessSupport(IBinder displayToken);
    private static native boolean nativeSetDisplayBrightness(IBinder displayToken,
            float sdrBrightness, float sdrBrightnessNits, float displayBrightness,
@@ -3061,13 +3062,14 @@ public final class SurfaceControl implements Parcelable {
        }

        /**
         * Waits until any changes to input windows have been sent from SurfaceFlinger to
         * InputFlinger before returning.
         * Adds a callback that is called after WindowInfosListeners from the systems server are
         * complete. This is primarily used to ensure that InputDispatcher::setInputWindowsLocked
         * has been called before running the added callback.
         *
         * @hide
         */
        public Transaction syncInputWindows() {
            nativeSyncInputWindows(mNativeObject);
        public Transaction addWindowInfosReportedListener(@NonNull Runnable listener) {
            nativeAddWindowInfosReportedListener(mNativeObject, listener);
            return this;
        }

+55 −11
Original line number Diff line number Diff line
@@ -17,18 +17,12 @@
#define LOG_TAG "SurfaceControl"
#define LOG_NDEBUG 0

#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include "android_hardware_input_InputWindowHandle.h"
#include "core_jni_helpers.h"

#include <memory>

#include <aidl/android/hardware/graphics/common/PixelFormat.h>
#include <android-base/chrono_utils.h>
#include <android/graphics/properties.h>
#include <android/graphics/region.h>
#include <android/gui/BnScreenCaptureListener.h>
#include <android/gui/BnWindowInfosReportedListener.h>
#include <android/hardware/display/IDeviceProductInfoConstants.h>
#include <android/os/IInputConstants.h>
#include <android_runtime/AndroidRuntime.h>
@@ -60,6 +54,13 @@
#include <utils/LightRefBase.h>
#include <utils/Log.h>

#include <memory>

#include "android_hardware_input_InputWindowHandle.h"
#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include "core_jni_helpers.h"

// ----------------------------------------------------------------------------

namespace android {
@@ -87,6 +88,11 @@ static jobject toInteger(JNIEnv* env, int32_t i) {
    return env->NewObject(gIntegerClassInfo.clazz, gIntegerClassInfo.ctor, i);
}

static struct {
    jclass clazz;
    jmethodID run;
} gRunnableClassInfo;

static struct {
    jclass clazz;
    jmethodID ctor;
@@ -381,6 +387,38 @@ private:
    }
};

class WindowInfosReportedListenerWrapper : public gui::BnWindowInfosReportedListener {
public:
    explicit WindowInfosReportedListenerWrapper(JNIEnv* env, jobject listener) {
        env->GetJavaVM(&mVm);
        mListener = env->NewGlobalRef(listener);
        LOG_ALWAYS_FATAL_IF(!mListener, "Failed to make global ref");
    }

    ~WindowInfosReportedListenerWrapper() {
        if (mListener) {
            getenv()->DeleteGlobalRef(mListener);
            mListener = nullptr;
        }
    }

    binder::Status onWindowInfosReported() override {
        JNIEnv* env = getenv();
        env->CallVoidMethod(mListener, gRunnableClassInfo.run);
        return binder::Status::ok();
    }

private:
    jobject mListener;
    JavaVM* mVm;

    JNIEnv* getenv() {
        JNIEnv* env;
        mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
        return env;
    }
};

// ----------------------------------------------------------------------------

static jlong nativeCreateTransaction(JNIEnv* env, jclass clazz) {
@@ -890,9 +928,11 @@ static void nativeSetInputWindowInfo(JNIEnv* env, jclass clazz, jlong transactio
    transaction->setInputWindowInfo(ctrl, *handle->getInfo());
}

static void nativeSyncInputWindows(JNIEnv* env, jclass clazz, jlong transactionObj) {
static void nativeAddWindowInfosReportedListener(JNIEnv* env, jclass clazz, jlong transactionObj,
                                                 jobject runnable) {
    auto listener = sp<WindowInfosReportedListenerWrapper>::make(env, runnable);
    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
    transaction->syncInputWindows();
    transaction->addWindowInfosReportedListener(listener);
}

static void nativeSetMetadata(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -2258,8 +2298,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
    {"nativeSetBufferTransform", "(JJI)V", (void*) nativeSetBufferTransform},
    {"nativeSetDataSpace", "(JJI)V",
            (void*)nativeSetDataSpace },
    {"nativeSyncInputWindows", "(J)V",
            (void*)nativeSyncInputWindows },
    {"nativeAddWindowInfosReportedListener", "(JLjava/lang/Runnable;)V",
            (void*)nativeAddWindowInfosReportedListener },
    {"nativeGetDisplayBrightnessSupport", "(Landroid/os/IBinder;)Z",
            (void*)nativeGetDisplayBrightnessSupport },
    {"nativeSetDisplayBrightness", "(Landroid/os/IBinder;FFFF)Z",
@@ -2323,6 +2363,10 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    gIntegerClassInfo.clazz = MakeGlobalRefOrDie(env, integerClass);
    gIntegerClassInfo.ctor = GetMethodIDOrDie(env, gIntegerClassInfo.clazz, "<init>", "(I)V");

    jclass runnableClazz = FindClassOrDie(env, "java/lang/Runnable");
    gRunnableClassInfo.clazz = MakeGlobalRefOrDie(env, runnableClazz);
    gRunnableClassInfo.run = GetMethodIDOrDie(env, runnableClazz, "run", "()V");

    jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$StaticDisplayInfo");
    gStaticDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
    gStaticDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
+47 −30
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ import android.view.accessibility.AccessibilityManager;
import com.android.server.wm.WindowManagerInternal.IDragDropCallback;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
@@ -106,6 +108,8 @@ class DragDropController {
        final boolean callbackResult = mCallback.get().prePerformDrag(window, dragToken,
                touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
        try {
            DisplayContent displayContent = null;
            CompletableFuture<Boolean> touchFocusTransferredFuture = null;
            synchronized (mService.mGlobalLock) {
                try {
                    if (!callbackResult) {
@@ -137,7 +141,7 @@ class DragDropController {

                    // !!! TODO(multi-display): support other displays

                    final DisplayContent displayContent = callingWin.getDisplayContent();
                    displayContent = callingWin.getDisplayContent();
                    if (displayContent == null) {
                        Slog.w(TAG_WM, "display content is null");
                        return null;
@@ -158,10 +162,41 @@ class DragDropController {

                    if ((flags & View.DRAG_FLAG_ACCESSIBILITY_ACTION) == 0) {
                        final Display display = displayContent.getDisplay();
                        if (!mCallback.get().registerInputChannel(
                        touchFocusTransferredFuture = mCallback.get().registerInputChannel(
                                mDragState, display, mService.mInputManager,
                                callingWin.mInputChannel)) {
                                callingWin.mInputChannel);
                    } else {
                        // Skip surface logic for a drag triggered by an AccessibilityAction
                        mDragState.broadcastDragStartedLocked(touchX, touchY);

                        // Timeout for the user to drop the content
                        sendTimeoutMessage(MSG_DRAG_END_TIMEOUT, callingWin.mClient.asBinder(),
                                getAccessibilityManager().getRecommendedTimeoutMillis(
                                        A11Y_DRAG_TIMEOUT_DEFAULT_MS,
                                        AccessibilityManager.FLAG_CONTENT_CONTROLS));

                        return dragToken;
                    }
                } finally {
                    if (surface != null) {
                        surface.release();
                    }
                }
            }

            boolean touchFocusTransferred = false;
            try {
                touchFocusTransferred = touchFocusTransferredFuture.get(DRAG_TIMEOUT_MS,
                        TimeUnit.MILLISECONDS);
            } catch (Exception exception) {
                Slog.e(TAG_WM, "Exception thrown while waiting for touch focus transfer",
                        exception);
            }

            synchronized (mService.mGlobalLock) {
                if (!touchFocusTransferred) {
                    Slog.e(TAG_WM, "Unable to transfer touch focus");
                    mDragState.closeLocked();
                    return null;
                }

@@ -185,24 +220,6 @@ class DragDropController {
                if (SHOW_LIGHT_TRANSACTIONS) {
                    Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag");
                }
                    } else {
                        // Skip surface logic for a drag triggered by an AccessibilityAction
                        mDragState.broadcastDragStartedLocked(touchX, touchY);

                        // Timeout for the user to drop the content
                        sendTimeoutMessage(MSG_DRAG_END_TIMEOUT, callingWin.mClient.asBinder(),
                                getAccessibilityManager().getRecommendedTimeoutMillis(
                                        A11Y_DRAG_TIMEOUT_DEFAULT_MS,
                                        AccessibilityManager.FLAG_CONTENT_CONTROLS));
                    }
                } finally {
                    if (surface != null) {
                        surface.release();
                    }
                    if (mDragState != null && !mDragState.isInProgress()) {
                        mDragState.closeLocked();
                    }
                }
            }
            return dragToken;    // success!
        } finally {
+17 −7
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.MY_PID;
import static com.android.server.wm.WindowManagerService.MY_UID;

import static java.util.concurrent.CompletableFuture.completedFuture;

import android.animation.Animator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
@@ -70,6 +72,7 @@ import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;

import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;

/**
 * Drag/drop state
@@ -160,7 +163,10 @@ class DragState {
        return mIsClosing;
    }

    private void showInputSurface() {
    /**
     * @return a future that completes after window info is sent.
     */
    private CompletableFuture<Void> showInputSurface() {
        if (mInputSurface == null) {
            mInputSurface = mService.makeSurfaceBuilder(mDisplayContent.getSession())
                    .setContainerLayer()
@@ -173,7 +179,7 @@ class DragState {
        if (h == null) {
            Slog.w(TAG_WM, "Drag is in progress but there is no "
                    + "drag window handle.");
            return;
            return completedFuture(null);
        }

        // Crop the input surface to the display size.
@@ -184,10 +190,13 @@ class DragState {
                .setLayer(mInputSurface, Integer.MAX_VALUE)
                .setCrop(mInputSurface, mTmpClipRect);

        // syncInputWindows here to ensure the input window info is sent before the
        // A completableFuture is returned to ensure that input window info is sent before the
        // transferTouchFocus is called.
        mTransaction.syncInputWindows()
                .apply(true /*sync*/);
        CompletableFuture<Void> result = new CompletableFuture<>();
        mTransaction
            .addWindowInfosReportedListener(() -> result.complete(null))
            .apply();
        return result;
    }

    /**
@@ -416,14 +425,15 @@ class DragState {
    /**
     * @param display The Display that the window being dragged is on.
     */
    void register(Display display) {
    CompletableFuture<Void> register(Display display) {
        display.getRealSize(mDisplaySize);
        if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
        if (mInputInterceptor != null) {
            Slog.e(TAG_WM, "Duplicate register of drag input channel");
            return completedFuture(null);
        } else {
            mInputInterceptor = new InputInterceptor(display);
            showInputSurface();
            return showInputSurface();
        }
    }

+7 −7
Original line number Diff line number Diff line
@@ -150,13 +150,13 @@ final class InputMonitor {

    void onDisplayRemoved() {
        mHandler.removeCallbacks(mUpdateInputWindows);
        mHandler.post(() -> {
            // Make sure any pending setInputWindowInfo transactions are completed. That prevents
            // the timing of updating input info of removed display after cleanup.
            mService.mTransactionFactory.get().syncInputWindows().apply();
        mService.mTransactionFactory.get()
            // Make sure any pending setInputWindowInfo transactions are completed. That
            // prevents the timing of updating input info of removed display after cleanup.
            .addWindowInfosReportedListener(() ->
                // It calls InputDispatcher::setInputWindows directly.
            mService.mInputManager.onDisplayRemoved(mDisplayId);
        });
                mService.mInputManager.onDisplayRemoved(mDisplayId))
            .apply();
        mDisplayRemoved = true;
    }

Loading