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

Commit b13f16cf authored by ramindani's avatar ramindani Committed by Rachel Lee
Browse files

Attach the Choreographer instance with SurfaceControl

The attached choreographer will register with the
event receiver through native api.

Test: atest ChoreographerTest SurfaceControlTest
BUG: 258235154
Change-Id: I33c0e686a1fd42becc0bfb1ae0185efd673e7b5a
parent 94d42cc7
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -3132,6 +3132,9 @@ package android.view {

  public final class SurfaceControl implements android.os.Parcelable {
    ctor public SurfaceControl(@NonNull android.view.SurfaceControl, @NonNull String);
    method @NonNull public android.view.Choreographer getChoreographer();
    method @NonNull public android.view.Choreographer getChoreographer(@NonNull android.os.Looper);
    method public boolean hasChoreographer();
    method public boolean isSameSurface(@NonNull android.view.SurfaceControl);
  }

+36 −3
Original line number Diff line number Diff line
@@ -270,10 +270,14 @@ public final class Choreographer {
    private static final int CALLBACK_LAST = CALLBACK_COMMIT;

    private Choreographer(Looper looper, int vsyncSource) {
        this(looper, vsyncSource, /* layerHandle */ 0L);
    }

    private Choreographer(Looper looper, int vsyncSource, long layerHandle) {
        mLooper = looper;
        mHandler = new FrameHandler(looper);
        mDisplayEventReceiver = USE_VSYNC
                ? new FrameDisplayEventReceiver(looper, vsyncSource)
                ? new FrameDisplayEventReceiver(looper, vsyncSource, layerHandle)
                : null;
        mLastFrameTimeNanos = Long.MIN_VALUE;

@@ -312,6 +316,26 @@ public final class Choreographer {
        return sSfThreadInstance.get();
    }

    /**
     * Gets the choreographer associated with the SurfaceControl.
     *
     * @param layerHandle to which the choreographer will be attached.
     * @param looper      the choreographer is attached on this looper.
     *
     * @return The choreographer for the looper which is attached
     * to the sourced SurfaceControl::mNativeHandle.
     * @throws IllegalStateException if the looper sourced is null.
     * @hide
     */
    @NonNull
    static Choreographer getInstanceForSurfaceControl(long layerHandle,
            @NonNull Looper looper) {
        if (looper == null) {
            throw new IllegalStateException("The current thread must have a looper!");
        }
        return new Choreographer(looper, VSYNC_SOURCE_APP, layerHandle);
    }

    /**
     * @return The Choreographer of the main thread, if it exists, or {@code null} otherwise.
     * @hide
@@ -333,6 +357,15 @@ public final class Choreographer {
        mDisplayEventReceiver.dispose();
    }

    /**
     * Dispose the DisplayEventReceiver on the Choreographer.
     * @hide
     */
    @UnsupportedAppUsage
    void invalidate() {
        dispose();
    }

    /**
     * The amount of time, in milliseconds, between each frame of the animation.
     * <p>
@@ -1166,8 +1199,8 @@ public final class Choreographer {
        private int mFrame;
        private VsyncEventData mLastVsyncEventData = new VsyncEventData();

        public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
            super(looper, vsyncSource, 0);
        FrameDisplayEventReceiver(Looper looper, int vsyncSource, long layerHandle) {
            super(looper, vsyncSource, /* eventRegistration */ 0, layerHandle);
        }

        // TODO(b/116025192): physicalDisplayId is ignored because SF only emits VSYNC events for
+10 −4
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ public abstract class DisplayEventReceiver {
    private MessageQueue mMessageQueue;

    private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
            MessageQueue messageQueue, int vsyncSource, int eventRegistration);
            MessageQueue messageQueue, int vsyncSource, int eventRegistration, long layerHandle);
    private static native void nativeDispose(long receiverPtr);
    @FastNative
    private static native void nativeScheduleVsync(long receiverPtr);
@@ -93,7 +93,11 @@ public abstract class DisplayEventReceiver {
     */
    @UnsupportedAppUsage
    public DisplayEventReceiver(Looper looper) {
        this(looper, VSYNC_SOURCE_APP, 0);
        this(looper, VSYNC_SOURCE_APP, /* eventRegistration */ 0, /* layerHandle */ 0L);
    }

    public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) {
        this(looper, vsyncSource, eventRegistration, /* layerHandle */ 0L);
    }

    /**
@@ -103,15 +107,17 @@ public abstract class DisplayEventReceiver {
     * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
     * @param eventRegistration Which events to dispatch. Must be a bitfield consist of the
     * EVENT_REGISTRATION_*_FLAG values.
     * @param layerHandle Layer to which the current instance is attached to
     */
    public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) {
    public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration,
            long layerHandle) {
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
                vsyncSource, eventRegistration);
                vsyncSource, eventRegistration, layerHandle);
    }

    @Override
+65 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import android.opengl.EGLDisplay;
import android.opengl.EGLSync;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
@@ -463,6 +464,10 @@ public final class SurfaceControl implements Parcelable {
    public long mNativeObject;
    private long mNativeHandle;

    private final Object mChoreographerLock = new Object();
    @GuardedBy("mChoreographerLock")
    private Choreographer mChoreographer;

    // TODO: Move width/height to native and fix locking through out.
    private final Object mLock = new Object();
    @GuardedBy("mLock")
@@ -1268,6 +1273,59 @@ public final class SurfaceControl implements Parcelable {
        return other.mNativeHandle == mNativeHandle;
    }

    /**
     * Returns the associated {@link Choreographer} instance with the
     * current instance of the SurfaceControl.
     * Must be called from a thread that already has a {@link android.os.Looper}
     * associated with it.
     * If there is no {@link Choreographer} associated with the SurfaceControl then a new instance
     * of the {@link Choreographer} is created.
     *
     * @hide
     */
    @TestApi
    public @NonNull Choreographer getChoreographer() {
        return getChoreographer(Looper.myLooper());
    }

    /**
     * Returns the associated {@link Choreographer} instance with the
     * current instance of the SurfaceControl.
     * If there is no {@link Choreographer} associated with the SurfaceControl then a new instance
     * of the {@link Choreographer} is created.
     *
     * @param looper the choreographer is attached on this looper
     *
     * @hide
     */
    @TestApi
    public @NonNull Choreographer getChoreographer(@NonNull Looper looper) {
        checkNotReleased();
        synchronized (mChoreographerLock) {
            if (mChoreographer != null) {
                return mChoreographer;
            }

            mChoreographer = Choreographer.getInstanceForSurfaceControl(mNativeHandle, looper);
            return mChoreographer;
        }
    }

    /**
     * Returns true if {@link Choreographer} is present otherwise false.
     * To check the validity use {@link #isValid} on the SurfaceControl, a valid SurfaceControl with
     * choreographer will have the valid Choreographer.
     *
     * @hide
     */
    @TestApi
    @UnsupportedAppUsage
    public boolean hasChoreographer() {
        synchronized (mChoreographerLock) {
            return mChoreographer != null;
        }
    }

    /**
     * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
     * android.view.SurfaceControlProto}.
@@ -1325,6 +1383,13 @@ public final class SurfaceControl implements Parcelable {
            mNativeObject = 0;
            mNativeHandle = 0;
            mCloseGuard.close();
            synchronized (mChoreographerLock) {
                if (mChoreographer != null) {
                    mChoreographer.invalidate();
                    // TODO(b/266121235): Use NativeAllocationRegistry to clean up Choreographer.
                    mChoreographer = null;
                }
            }
        }
    }

+10 −6
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ class NativeDisplayEventReceiver : public DisplayEventDispatcher {
public:
    NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
                               const sp<MessageQueue>& messageQueue, jint vsyncSource,
                               jint eventRegistration);
                               jint eventRegistration, jlong layerHandle);

    void dispose();

@@ -88,11 +88,15 @@ private:

NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
                                                       const sp<MessageQueue>& messageQueue,
                                                       jint vsyncSource, jint eventRegistration)
                                                       jint vsyncSource, jint eventRegistration,
                                                       jlong layerHandle)
      : DisplayEventDispatcher(messageQueue->getLooper(),
                               static_cast<gui::ISurfaceComposer::VsyncSource>(vsyncSource),
                               static_cast<gui::ISurfaceComposer::EventRegistration>(
                                       eventRegistration)),
                                       eventRegistration),
                               layerHandle != 0 ? sp<IBinder>::fromExisting(
                                                          reinterpret_cast<IBinder*>(layerHandle))
                                                : nullptr),
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mMessageQueue(messageQueue) {
    ALOGV("receiver %p ~ Initializing display event receiver.", this);
@@ -214,7 +218,7 @@ void NativeDisplayEventReceiver::dispatchFrameRateOverrides(
}

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj,
                        jint vsyncSource, jint eventRegistration) {
                        jint vsyncSource, jint eventRegistration, jlong layerHandle) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
@@ -223,7 +227,7 @@ static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject

    sp<NativeDisplayEventReceiver> receiver =
            new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource,
                                           eventRegistration);
                                           eventRegistration, layerHandle);
    status_t status = receiver->initialize();
    if (status) {
        String8 message;
@@ -268,7 +272,7 @@ static jobject nativeGetLatestVsyncEventData(JNIEnv* env, jclass clazz, jlong re

static const JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        {"nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;II)J",
        {"nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;IIJ)J",
         (void*)nativeInit},
        {"nativeDispose", "(J)V", (void*)nativeDispose},
        // @FastNative