10a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown/*
20a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * Copyright (C) 2011 The Android Open Source Project
30a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown *
40a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
50a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * you may not use this file except in compliance with the License.
60a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * You may obtain a copy of the License at
70a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown *
80a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
90a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown *
100a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * Unless required by applicable law or agreed to in writing, software
110a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
120a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * See the License for the specific language governing permissions and
140a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * limitations under the License.
150a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown */
160a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
170a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownpackage android.view;
180a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
190a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownimport dalvik.system.CloseGuard;
200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownimport android.os.Looper;
220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownimport android.os.MessageQueue;
230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownimport android.util.Log;
240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown/**
260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * Provides a low-level mechanism for an application to receive display events
270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * such as vertical sync.
2858aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown *
2958aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown * The display event receive is NOT thread safe.  Moreover, its methods must only
3058aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown * be called on the Looper thread to which it is attached.
3158aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown *
320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * @hide
330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown */
340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownpublic abstract class DisplayEventReceiver {
350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    private static final String TAG = "DisplayEventReceiver";
360a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
370a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    private final CloseGuard mCloseGuard = CloseGuard.get();
380a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
390a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    private int mReceiverPtr;
400a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
410a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    // We keep a reference message queue object here so that it is not
420a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    // GC'd while the native peer of the receiver is using them.
430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    private MessageQueue mMessageQueue;
440a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    private static native int nativeInit(DisplayEventReceiver receiver,
460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            MessageQueue messageQueue);
470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    private static native void nativeDispose(int receiverPtr);
480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    private static native void nativeScheduleVsync(int receiverPtr);
490a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    /**
510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * Creates a display event receiver.
520a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     *
530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * @param looper The looper to use when invoking callbacks.
540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     */
550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    public DisplayEventReceiver(Looper looper) {
560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        if (looper == null) {
570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            throw new IllegalArgumentException("looper must not be null");
580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        }
590a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
600a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mMessageQueue = looper.getQueue();
610a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mReceiverPtr = nativeInit(this, mMessageQueue);
620a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
630a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mCloseGuard.open("dispose");
640a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
650a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
660a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    @Override
670a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    protected void finalize() throws Throwable {
680a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        try {
693e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown            dispose(true);
700a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        } finally {
710a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            super.finalize();
720a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        }
730a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
740a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
750a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    /**
760a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * Disposes the receiver.
770a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     */
780a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    public void dispose() {
793e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown        dispose(false);
803e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown    }
813e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown
823e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown    private void dispose(boolean finalized) {
830a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        if (mCloseGuard != null) {
843e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown            if (finalized) {
853e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown                mCloseGuard.warnIfOpen();
863e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown            }
870a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            mCloseGuard.close();
880a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        }
893e7e7f025e8d7dc6ab8c361118c8e949bdf3e451Jeff Brown
900a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        if (mReceiverPtr != 0) {
910a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            nativeDispose(mReceiverPtr);
920a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            mReceiverPtr = 0;
930a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        }
940a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mMessageQueue = null;
950a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
960a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
970a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    /**
980a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * Called when a vertical sync pulse is received.
990a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * The recipient should render a frame and then call {@link #scheduleVsync}
1000a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * to schedule the next vertical sync pulse.
1010a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     *
1020a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
1030a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * timebase.
104e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     * @param builtInDisplayId The surface flinger built-in display id such as
105e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     * {@link Surface#BUILT_IN_DISPLAY_ID_MAIN}.
1060a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * @param frame The frame number.  Increases by one for each vertical sync interval.
1070a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     */
108e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
109e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    }
110e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
111e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    /**
112e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     * Called when a display hotplug event is received.
113e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     *
114e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
115e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     * timebase.
116e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     * @param builtInDisplayId The surface flinger built-in display id such as
117e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     * {@link Surface#BUILT_IN_DISPLAY_ID_HDMI}.
118e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     * @param connected True if the display is connected, false if it disconnected.
119e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown     */
120e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
1210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    /**
1240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * Schedules a single vertical sync pulse to be delivered when the next
1250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     * display frame begins.
1260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown     */
1270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    public void scheduleVsync() {
1280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        if (mReceiverPtr == 0) {
1290a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
1300a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown                    + "receiver has already been disposed.");
1310a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        } else {
1320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            nativeScheduleVsync(mReceiverPtr);
1330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        }
1340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1360a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    // Called from native code.
1370a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    @SuppressWarnings("unused")
138e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
139e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        onVsync(timestampNanos, builtInDisplayId, frame);
140e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    }
141e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
142e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    // Called from native code.
143e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    @SuppressWarnings("unused")
144e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
145e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        onHotplug(timestampNanos, builtInDisplayId, connected);
1460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
148