blob: de46a4a8f642ac138549d296729be2fda6cf0194 [file] [log] [blame]
Jeff Brown0a0a1242011-12-02 02:25:22 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import dalvik.system.CloseGuard;
20
21import android.os.Looper;
22import android.os.MessageQueue;
23import android.util.Log;
24
25/**
26 * Provides a low-level mechanism for an application to receive display events
27 * such as vertical sync.
Jeff Brown58aedbc2012-02-13 20:15:01 -080028 *
29 * The display event receive is NOT thread safe. Moreover, its methods must only
30 * be called on the Looper thread to which it is attached.
31 *
Jeff Brown0a0a1242011-12-02 02:25:22 -080032 * @hide
33 */
34public abstract class DisplayEventReceiver {
35 private static final String TAG = "DisplayEventReceiver";
36
37 private final CloseGuard mCloseGuard = CloseGuard.get();
38
Ashok Bhat27285822013-12-18 18:00:05 +000039 private long mReceiverPtr;
Jeff Brown0a0a1242011-12-02 02:25:22 -080040
41 // We keep a reference message queue object here so that it is not
42 // GC'd while the native peer of the receiver is using them.
43 private MessageQueue mMessageQueue;
44
Ashok Bhat27285822013-12-18 18:00:05 +000045 private static native long nativeInit(DisplayEventReceiver receiver,
Jeff Brown0a0a1242011-12-02 02:25:22 -080046 MessageQueue messageQueue);
Ashok Bhat27285822013-12-18 18:00:05 +000047 private static native void nativeDispose(long receiverPtr);
48 private static native void nativeScheduleVsync(long receiverPtr);
Jeff Brown0a0a1242011-12-02 02:25:22 -080049
50 /**
51 * Creates a display event receiver.
52 *
53 * @param looper The looper to use when invoking callbacks.
54 */
55 public DisplayEventReceiver(Looper looper) {
56 if (looper == null) {
57 throw new IllegalArgumentException("looper must not be null");
58 }
59
60 mMessageQueue = looper.getQueue();
61 mReceiverPtr = nativeInit(this, mMessageQueue);
62
63 mCloseGuard.open("dispose");
64 }
65
66 @Override
67 protected void finalize() throws Throwable {
68 try {
Jeff Brown3e7e7f02012-08-27 14:33:53 -070069 dispose(true);
Jeff Brown0a0a1242011-12-02 02:25:22 -080070 } finally {
71 super.finalize();
72 }
73 }
74
75 /**
76 * Disposes the receiver.
77 */
78 public void dispose() {
Jeff Brown3e7e7f02012-08-27 14:33:53 -070079 dispose(false);
80 }
81
82 private void dispose(boolean finalized) {
Jeff Brown0a0a1242011-12-02 02:25:22 -080083 if (mCloseGuard != null) {
Jeff Brown3e7e7f02012-08-27 14:33:53 -070084 if (finalized) {
85 mCloseGuard.warnIfOpen();
86 }
Jeff Brown0a0a1242011-12-02 02:25:22 -080087 mCloseGuard.close();
88 }
Jeff Brown3e7e7f02012-08-27 14:33:53 -070089
Jeff Brown0a0a1242011-12-02 02:25:22 -080090 if (mReceiverPtr != 0) {
91 nativeDispose(mReceiverPtr);
92 mReceiverPtr = 0;
93 }
94 mMessageQueue = null;
95 }
96
97 /**
98 * Called when a vertical sync pulse is received.
99 * The recipient should render a frame and then call {@link #scheduleVsync}
100 * to schedule the next vertical sync pulse.
101 *
102 * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
103 * timebase.
Jeff Browne87bf032012-09-20 18:30:13 -0700104 * @param builtInDisplayId The surface flinger built-in display id such as
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800105 * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}.
Jeff Brown0a0a1242011-12-02 02:25:22 -0800106 * @param frame The frame number. Increases by one for each vertical sync interval.
107 */
Jeff Browne87bf032012-09-20 18:30:13 -0700108 public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
109 }
110
111 /**
112 * Called when a display hotplug event is received.
113 *
114 * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
115 * timebase.
116 * @param builtInDisplayId The surface flinger built-in display id such as
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800117 * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_HDMI}.
Jeff Browne87bf032012-09-20 18:30:13 -0700118 * @param connected True if the display is connected, false if it disconnected.
119 */
120 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
Jeff Brown0a0a1242011-12-02 02:25:22 -0800121 }
122
123 /**
124 * Schedules a single vertical sync pulse to be delivered when the next
125 * display frame begins.
126 */
127 public void scheduleVsync() {
128 if (mReceiverPtr == 0) {
129 Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
130 + "receiver has already been disposed.");
131 } else {
132 nativeScheduleVsync(mReceiverPtr);
133 }
134 }
135
136 // Called from native code.
137 @SuppressWarnings("unused")
Jeff Browne87bf032012-09-20 18:30:13 -0700138 private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
139 onVsync(timestampNanos, builtInDisplayId, frame);
140 }
141
142 // Called from native code.
143 @SuppressWarnings("unused")
144 private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
145 onHotplug(timestampNanos, builtInDisplayId, connected);
Jeff Brown0a0a1242011-12-02 02:25:22 -0800146 }
147}