/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view;

import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.FrameInfo;
import android.os.Build;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import dalvik.annotation.optimization.FastNative;

import libcore.util.NativeAllocationRegistry;

import java.lang.ref.WeakReference;

/**
 * Provides a low-level mechanism for an application to receive display events
 * such as vertical sync.
 *
 * The display event receive is NOT thread safe.  Moreover, its methods must only
 * be called on the Looper thread to which it is attached.
 *
 * @hide
 */
public abstract class DisplayEventReceiver {

    /**
     * When retrieving vsync events, this specifies that the vsync event should happen at the normal
     * vsync-app tick.
     * <p>
     * Keep in sync with frameworks/native/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
     */
    public static final int VSYNC_SOURCE_APP = 0;

    /**
     * When retrieving vsync events, this specifies that the vsync event should happen whenever
     * Surface Flinger is processing a frame.
     * <p>
     * Keep in sync with frameworks/native/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
     */
    public static final int VSYNC_SOURCE_SURFACE_FLINGER = 1;

    /**
     * Specifies to generate mode changed events from Surface Flinger.
     * <p>
     * Keep in sync with frameworks/native/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
     */
    public static final int EVENT_REGISTRATION_MODE_CHANGED_FLAG = 0x1;

    /**
     * Specifies to generate frame rate override events from Surface Flinger.
     * <p>
     * Keep in sync with frameworks/native/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
     */
    public static final int EVENT_REGISTRATION_FRAME_RATE_OVERRIDE_FLAG = 0x2;

    private static final String TAG = "DisplayEventReceiver";

    @UnsupportedAppUsage
    private long mReceiverPtr;

    // We keep a reference message queue object here so that it is not
    // GC'd while the native peer of the receiver is using them.
    private MessageQueue mMessageQueue;

    private final VsyncEventData mVsyncEventData = new VsyncEventData();

    private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
            WeakReference<VsyncEventData> vsyncEventData,
            MessageQueue messageQueue, int vsyncSource, int eventRegistration, long layerHandle);
    private static native long nativeGetDisplayEventReceiverFinalizer();
    @FastNative
    private static native void nativeScheduleVsync(long receiverPtr);
    private static native VsyncEventData nativeGetLatestVsyncEventData(long receiverPtr);

    private static final NativeAllocationRegistry sNativeAllocationRegistry =
            NativeAllocationRegistry.createMalloced(
                    DisplayEventReceiver.class.getClassLoader(),
                    nativeGetDisplayEventReceiverFinalizer());
    private Runnable mFreeNativeResources;

    /**
     * Creates a display event receiver.
     *
     * @param looper The looper to use when invoking callbacks.
     */
    @UnsupportedAppUsage
    public DisplayEventReceiver(Looper looper) {
        this(looper, VSYNC_SOURCE_APP, /* eventRegistration */ 0, /* layerHandle */ 0L);
    }

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

    /**
     * Creates a display event receiver.
     *
     * @param looper The looper to use when invoking callbacks.
     * @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,
            long layerHandle) {
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

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

    /**
     * Disposes the receiver.
     */
    public void dispose() {
        if (mReceiverPtr != 0) {
            mFreeNativeResources.run();
            mReceiverPtr = 0;
        }
        mMessageQueue = null;
    }

    /**
     * Class to capture all inputs required for syncing events data.
     *
     * @hide
     */
    public static final class VsyncEventData {
        // The max capacity of frame timeline choices.
        // Must be in sync with VsyncEventData::kFrameTimelinesCapacity in
        // frameworks/native/libs/gui/include/gui/VsyncEventData.h
        static final int FRAME_TIMELINES_CAPACITY = 7;

        public static class FrameTimeline {
            FrameTimeline() {
                // Some reasonable values (+10 ms) for default timestamps.
                deadline = System.nanoTime() + 10_000_000;
                expectedPresentationTime = deadline + 10_000_000;
            }

            // Called from native code.
            @SuppressWarnings("unused")
            FrameTimeline(long vsyncId, long expectedPresentationTime, long deadline) {
                this.vsyncId = vsyncId;
                this.expectedPresentationTime = expectedPresentationTime;
                this.deadline = deadline;
            }

            void copyFrom(FrameTimeline other) {
                vsyncId = other.vsyncId;
                expectedPresentationTime = other.expectedPresentationTime;
                deadline = other.deadline;
            }

            // The frame timeline vsync id, used to correlate a frame
            // produced by HWUI with the timeline data stored in Surface Flinger.
            public long vsyncId = FrameInfo.INVALID_VSYNC_ID;

            // The frame timestamp for when the frame is expected to be presented.
            public long expectedPresentationTime;

            // The frame deadline timestamp in {@link System#nanoTime()} timebase that it is
            // allotted for the frame to be completed.
            public long deadline;
        }

        /**
         * The current interval between frames in ns. This will be used to align
         * {@link FrameInfo#VSYNC} to the current vsync in case Choreographer callback was heavily
         * delayed by the app.
         */
        public long frameInterval = -1;

        public final FrameTimeline[] frameTimelines;

        public int preferredFrameTimelineIndex = 0;

        // The default FrameTimeline is a placeholder populated with invalid vsync ID and some
        // reasonable timestamps.
        public int frameTimelinesLength = 1;

        VsyncEventData() {
            frameTimelines = new FrameTimeline[FRAME_TIMELINES_CAPACITY];
            for (int i = 0; i < frameTimelines.length; i++) {
                frameTimelines[i] = new FrameTimeline();
            }
        }

        // Called from native code.
        @SuppressWarnings("unused")
        VsyncEventData(FrameTimeline[] frameTimelines, int preferredFrameTimelineIndex,
                int frameTimelinesLength, long frameInterval) {
            this.frameTimelines = frameTimelines;
            this.preferredFrameTimelineIndex = preferredFrameTimelineIndex;
            this.frameTimelinesLength = frameTimelinesLength;
            this.frameInterval = frameInterval;
        }

        void copyFrom(VsyncEventData other) {
            preferredFrameTimelineIndex = other.preferredFrameTimelineIndex;
            frameTimelinesLength = other.frameTimelinesLength;
            frameInterval = other.frameInterval;
            for (int i = 0; i < frameTimelines.length; i++) {
                frameTimelines[i].copyFrom(other.frameTimelines[i]);
            }
        }

        public FrameTimeline preferredFrameTimeline() {
            return frameTimelines[preferredFrameTimelineIndex];
        }
    }

    /**
     * Called when a vertical sync pulse is received.
     * The recipient should render a frame and then call {@link #scheduleVsync}
     * to schedule the next vertical sync pulse.
     *
     * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
     * timebase.
     * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
     * @param frame The frame number.  Increases by one for each vertical sync interval.
     * @param vsyncEventData The vsync event data.
     */
    public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
            VsyncEventData vsyncEventData) {
    }

    /**
     * Called when a display hotplug event is received.
     *
     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
     * timebase.
     * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
     * @param connected True if the display is connected, false if it disconnected.
     */
    @UnsupportedAppUsage
    public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
    }

    /**
     * Called when a display hotplug event with connection error is received.
     *
     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
     * timebase.
     * @param connectionError the hotplug connection error code.
     */
    public void onHotplugConnectionError(long timestampNanos, int connectionError) {
    }

    /**
     * Called when a display mode changed event is received.
     *
     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
     * timebase.
     * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
     * @param modeId The new mode Id
     * @param renderPeriod The render frame period, which is a multiple of the mode's vsync period
     */
    public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId,
            long renderPeriod) {
    }

    /**
     * Represents a mapping between a UID and an override frame rate
     */
    public static class FrameRateOverride {
        // The application uid
        public final int uid;

        // The frame rate that this application runs at
        public final float frameRateHz;


        @VisibleForTesting
        public FrameRateOverride(int uid, float frameRateHz) {
            this.uid = uid;
            this.frameRateHz = frameRateHz;
        }

        @Override
        public String toString() {
            return "{uid=" + uid + " frameRateHz=" + frameRateHz + "}";
        }
    }

    /**
     * Called when frame rate override event is received.
     *
     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
     * timebase.
     * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
     * @param overrides The mappings from uid to frame rates
     */
    public void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
            FrameRateOverride[] overrides) {
    }

    /**
     * Schedules a single vertical sync pulse to be delivered when the next
     * display frame begins.
     */
    @UnsupportedAppUsage
    public void scheduleVsync() {
        if (mReceiverPtr == 0) {
            Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
                    + "receiver has already been disposed.");
        } else {
            nativeScheduleVsync(mReceiverPtr);
        }
    }

    /**
     * Gets the latest vsync event data from surface flinger.
     */
    VsyncEventData getLatestVsyncEventData() {
        return nativeGetLatestVsyncEventData(mReceiverPtr);
    }

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
        onVsync(timestampNanos, physicalDisplayId, frame, mVsyncEventData);
    }

    // Called from native code.
    @SuppressWarnings("unused")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private void dispatchHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
        onHotplug(timestampNanos, physicalDisplayId, connected);
    }

    @SuppressWarnings("unused")
    private void dispatchHotplugConnectionError(long timestampNanos, int connectionError) {
        onHotplugConnectionError(timestampNanos, connectionError);
    }

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchModeChanged(long timestampNanos, long physicalDisplayId, int modeId,
            long renderPeriod) {
        onModeChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod);
    }

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchFrameRateOverrides(long timestampNanos, long physicalDisplayId,
            FrameRateOverride[] overrides) {
        onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides);
    }

}
