1 /* 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 17 package android.view; 18 19 import dalvik.system.CloseGuard; 20 21 import android.os.Looper; 22 import android.os.MessageQueue; 23 import android.util.Log; 24 25 /** 26 * Provides a low-level mechanism for an application to receive display events 27 * such as vertical sync. 28 * 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 * 32 * @hide 33 */ 34 public abstract class DisplayEventReceiver { 35 private static final String TAG = "DisplayEventReceiver"; 36 37 private final CloseGuard mCloseGuard = CloseGuard.get(); 38 39 private int mReceiverPtr; 40 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 45 private static native int nativeInit(DisplayEventReceiver receiver, 46 MessageQueue messageQueue); 47 private static native void nativeDispose(int receiverPtr); 48 private static native void nativeScheduleVsync(int receiverPtr); 49 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 { 69 dispose(true); 70 } finally { 71 super.finalize(); 72 } 73 } 74 75 /** 76 * Disposes the receiver. 77 */ 78 public void dispose() { 79 dispose(false); 80 } 81 82 private void dispose(boolean finalized) { 83 if (mCloseGuard != null) { 84 if (finalized) { 85 mCloseGuard.warnIfOpen(); 86 } 87 mCloseGuard.close(); 88 } 89 90 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. 104 * @param builtInDisplayId The surface flinger built-in display id such as 105 * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}. 106 * @param frame The frame number. Increases by one for each vertical sync interval. 107 */ 108 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 117 * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_HDMI}. 118 * @param connected True if the display is connected, false if it disconnected. 119 */ 120 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) { 121 } 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") 138 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); 146 } 147 } 148