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