blob: 5a9a1eacbef616eeb8141ca09550ef540f6f432b [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
Jeff Brown3b4049e2015-04-17 15:22:27 -070025import java.lang.ref.WeakReference;
26
Jeff Brown0a0a1242011-12-02 02:25:22 -080027/**
28 * Provides a low-level mechanism for an application to receive display events
29 * such as vertical sync.
Jeff Brown58aedbc2012-02-13 20:15:01 -080030 *
31 * The display event receive is NOT thread safe. Moreover, its methods must only
32 * be called on the Looper thread to which it is attached.
33 *
Jeff Brown0a0a1242011-12-02 02:25:22 -080034 * @hide
35 */
36public abstract class DisplayEventReceiver {
37 private static final String TAG = "DisplayEventReceiver";
38
39 private final CloseGuard mCloseGuard = CloseGuard.get();
40
Ashok Bhat27285822013-12-18 18:00:05 +000041 private long mReceiverPtr;
Jeff Brown0a0a1242011-12-02 02:25:22 -080042
43 // We keep a reference message queue object here so that it is not
44 // GC'd while the native peer of the receiver is using them.
45 private MessageQueue mMessageQueue;
46
Jeff Brown3b4049e2015-04-17 15:22:27 -070047 private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
Jeff Brown0a0a1242011-12-02 02:25:22 -080048 MessageQueue messageQueue);
Ashok Bhat27285822013-12-18 18:00:05 +000049 private static native void nativeDispose(long receiverPtr);
50 private static native void nativeScheduleVsync(long receiverPtr);
Jeff Brown0a0a1242011-12-02 02:25:22 -080051
52 /**
53 * Creates a display event receiver.
54 *
55 * @param looper The looper to use when invoking callbacks.
56 */
57 public DisplayEventReceiver(Looper looper) {
58 if (looper == null) {
59 throw new IllegalArgumentException("looper must not be null");
60 }
61
62 mMessageQueue = looper.getQueue();
Jeff Brown3b4049e2015-04-17 15:22:27 -070063 mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue);
Jeff Brown0a0a1242011-12-02 02:25:22 -080064
65 mCloseGuard.open("dispose");
66 }
67
68 @Override
69 protected void finalize() throws Throwable {
70 try {
Jeff Brown3e7e7f02012-08-27 14:33:53 -070071 dispose(true);
Jeff Brown0a0a1242011-12-02 02:25:22 -080072 } finally {
73 super.finalize();
74 }
75 }
76
77 /**
78 * Disposes the receiver.
79 */
80 public void dispose() {
Jeff Brown3e7e7f02012-08-27 14:33:53 -070081 dispose(false);
82 }
83
84 private void dispose(boolean finalized) {
Jeff Brown0a0a1242011-12-02 02:25:22 -080085 if (mCloseGuard != null) {
Jeff Brown3e7e7f02012-08-27 14:33:53 -070086 if (finalized) {
87 mCloseGuard.warnIfOpen();
88 }
Jeff Brown0a0a1242011-12-02 02:25:22 -080089 mCloseGuard.close();
90 }
Jeff Brown3e7e7f02012-08-27 14:33:53 -070091
Jeff Brown0a0a1242011-12-02 02:25:22 -080092 if (mReceiverPtr != 0) {
93 nativeDispose(mReceiverPtr);
94 mReceiverPtr = 0;
95 }
96 mMessageQueue = null;
97 }
98
99 /**
100 * Called when a vertical sync pulse is received.
101 * The recipient should render a frame and then call {@link #scheduleVsync}
102 * to schedule the next vertical sync pulse.
103 *
104 * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
105 * timebase.
Jeff Browne87bf032012-09-20 18:30:13 -0700106 * @param builtInDisplayId The surface flinger built-in display id such as
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800107 * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}.
Jeff Brown0a0a1242011-12-02 02:25:22 -0800108 * @param frame The frame number. Increases by one for each vertical sync interval.
109 */
Jeff Browne87bf032012-09-20 18:30:13 -0700110 public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
111 }
112
113 /**
114 * Called when a display hotplug event is received.
115 *
116 * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
117 * timebase.
118 * @param builtInDisplayId The surface flinger built-in display id such as
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800119 * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_HDMI}.
Jeff Browne87bf032012-09-20 18:30:13 -0700120 * @param connected True if the display is connected, false if it disconnected.
121 */
122 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
Jeff Brown0a0a1242011-12-02 02:25:22 -0800123 }
124
125 /**
126 * Schedules a single vertical sync pulse to be delivered when the next
127 * display frame begins.
128 */
129 public void scheduleVsync() {
130 if (mReceiverPtr == 0) {
131 Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
132 + "receiver has already been disposed.");
133 } else {
134 nativeScheduleVsync(mReceiverPtr);
135 }
136 }
137
138 // Called from native code.
139 @SuppressWarnings("unused")
Jeff Browne87bf032012-09-20 18:30:13 -0700140 private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
141 onVsync(timestampNanos, builtInDisplayId, frame);
142 }
143
144 // Called from native code.
145 @SuppressWarnings("unused")
146 private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
147 onHotplug(timestampNanos, builtInDisplayId, connected);
Jeff Brown0a0a1242011-12-02 02:25:22 -0800148 }
149}