• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.compat.annotation.UnsupportedAppUsage;
20 import android.graphics.FrameInfo;
21 import android.os.Build;
22 import android.os.Looper;
23 import android.os.MessageQueue;
24 import android.util.Log;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 
28 import dalvik.annotation.optimization.FastNative;
29 
30 import java.lang.ref.WeakReference;
31 
32 /**
33  * Provides a low-level mechanism for an application to receive display events
34  * such as vertical sync.
35  *
36  * The display event receive is NOT thread safe.  Moreover, its methods must only
37  * be called on the Looper thread to which it is attached.
38  *
39  * @hide
40  */
41 public abstract class DisplayEventReceiver {
42 
43     /**
44      * When retrieving vsync events, this specifies that the vsync event should happen at the normal
45      * vsync-app tick.
46      * <p>
47      * Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
48      */
49     public static final int VSYNC_SOURCE_APP = 0;
50 
51     /**
52      * When retrieving vsync events, this specifies that the vsync event should happen whenever
53      * Surface Flinger is processing a frame.
54      * <p>
55      * Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
56      */
57     public static final int VSYNC_SOURCE_SURFACE_FLINGER = 1;
58 
59     /**
60      * Specifies to generate mode changed events from Surface Flinger.
61      * <p>
62      * Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
63      */
64     public static final int EVENT_REGISTRATION_MODE_CHANGED_FLAG = 0x1;
65 
66     /**
67      * Specifies to generate frame rate override events from Surface Flinger.
68      * <p>
69      * Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
70      */
71     public static final int EVENT_REGISTRATION_FRAME_RATE_OVERRIDE_FLAG = 0x2;
72 
73     private static final String TAG = "DisplayEventReceiver";
74 
75     @UnsupportedAppUsage
76     private long mReceiverPtr;
77 
78     // We keep a reference message queue object here so that it is not
79     // GC'd while the native peer of the receiver is using them.
80     private MessageQueue mMessageQueue;
81 
nativeInit(WeakReference<DisplayEventReceiver> receiver, MessageQueue messageQueue, int vsyncSource, int eventRegistration)82     private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
83             MessageQueue messageQueue, int vsyncSource, int eventRegistration);
nativeDispose(long receiverPtr)84     private static native void nativeDispose(long receiverPtr);
85     @FastNative
nativeScheduleVsync(long receiverPtr)86     private static native void nativeScheduleVsync(long receiverPtr);
87 
88     /**
89      * Creates a display event receiver.
90      *
91      * @param looper The looper to use when invoking callbacks.
92      */
93     @UnsupportedAppUsage
DisplayEventReceiver(Looper looper)94     public DisplayEventReceiver(Looper looper) {
95         this(looper, VSYNC_SOURCE_APP, 0);
96     }
97 
98     /**
99      * Creates a display event receiver.
100      *
101      * @param looper The looper to use when invoking callbacks.
102      * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
103      * @param eventRegistration Which events to dispatch. Must be a bitfield consist of the
104      * EVENT_REGISTRATION_*_FLAG values.
105      */
DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration)106     public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) {
107         if (looper == null) {
108             throw new IllegalArgumentException("looper must not be null");
109         }
110 
111         mMessageQueue = looper.getQueue();
112         mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
113                 vsyncSource, eventRegistration);
114     }
115 
116     @Override
finalize()117     protected void finalize() throws Throwable {
118         try {
119             dispose(true);
120         } finally {
121             super.finalize();
122         }
123     }
124 
125     /**
126      * Disposes the receiver.
127      */
dispose()128     public void dispose() {
129         dispose(false);
130     }
131 
dispose(boolean finalized)132     private void dispose(boolean finalized) {
133         if (mReceiverPtr != 0) {
134             nativeDispose(mReceiverPtr);
135             mReceiverPtr = 0;
136         }
137         mMessageQueue = null;
138     }
139 
140     static final class VsyncEventData {
141         // The frame timeline vsync id, used to correlate a frame
142         // produced by HWUI with the timeline data stored in Surface Flinger.
143         public final long id;
144 
145         // The frame deadline timestamp in {@link System#nanoTime()} timebase that it is
146         // allotted for the frame to be completed.
147         public final long frameDeadline;
148 
149         /**
150          * The current interval between frames in ns. This will be used to align
151          * {@link FrameInfo#VSYNC} to the current vsync in case Choreographer callback was heavily
152          * delayed by the app.
153          */
154         public final long frameInterval;
155 
VsyncEventData(long id, long frameDeadline, long frameInterval)156         VsyncEventData(long id, long frameDeadline, long frameInterval) {
157             this.id = id;
158             this.frameDeadline = frameDeadline;
159             this.frameInterval = frameInterval;
160         }
161 
VsyncEventData()162         VsyncEventData() {
163             this.id = FrameInfo.INVALID_VSYNC_ID;
164             this.frameDeadline = Long.MAX_VALUE;
165             this.frameInterval = -1;
166         }
167     }
168 
169     /**
170      * Called when a vertical sync pulse is received.
171      * The recipient should render a frame and then call {@link #scheduleVsync}
172      * to schedule the next vertical sync pulse.
173      *
174      * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
175      * timebase.
176      * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
177      * @param frame The frame number.  Increases by one for each vertical sync interval.
178      * @param vsyncEventData The vsync event data.
179      */
onVsync(long timestampNanos, long physicalDisplayId, int frame, VsyncEventData vsyncEventData)180     public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
181             VsyncEventData vsyncEventData) {
182     }
183 
184     /**
185      * Called when a display hotplug event is received.
186      *
187      * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
188      * timebase.
189      * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
190      * @param connected True if the display is connected, false if it disconnected.
191      */
192     @UnsupportedAppUsage
onHotplug(long timestampNanos, long physicalDisplayId, boolean connected)193     public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
194     }
195 
196     /**
197      * Called when a display mode changed event is received.
198      *
199      * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
200      * timebase.
201      * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
202      * @param modeId The new mode Id
203      */
onModeChanged(long timestampNanos, long physicalDisplayId, int modeId)204     public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId) {
205     }
206 
207     /**
208      * Represents a mapping between a UID and an override frame rate
209      */
210     public static class FrameRateOverride {
211         // The application uid
212         public final int uid;
213 
214         // The frame rate that this application runs at
215         public final float frameRateHz;
216 
217 
218         @VisibleForTesting
FrameRateOverride(int uid, float frameRateHz)219         public FrameRateOverride(int uid, float frameRateHz) {
220             this.uid = uid;
221             this.frameRateHz = frameRateHz;
222         }
223 
224         @Override
toString()225         public String toString() {
226             return "{uid=" + uid + " frameRateHz=" + frameRateHz + "}";
227         }
228     }
229 
230     /**
231      * Called when frame rate override event is received.
232      *
233      * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
234      * timebase.
235      * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
236      * @param overrides The mappings from uid to frame rates
237      */
onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, FrameRateOverride[] overrides)238     public void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
239             FrameRateOverride[] overrides) {
240     }
241 
242     /**
243      * Schedules a single vertical sync pulse to be delivered when the next
244      * display frame begins.
245      */
246     @UnsupportedAppUsage
scheduleVsync()247     public void scheduleVsync() {
248         if (mReceiverPtr == 0) {
249             Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
250                     + "receiver has already been disposed.");
251         } else {
252             nativeScheduleVsync(mReceiverPtr);
253         }
254     }
255 
256     // Called from native code.
257     @SuppressWarnings("unused")
dispatchVsync(long timestampNanos, long physicalDisplayId, int frame, long frameTimelineVsyncId, long frameDeadline, long frameInterval)258     private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
259             long frameTimelineVsyncId, long frameDeadline, long frameInterval) {
260         onVsync(timestampNanos, physicalDisplayId, frame,
261                 new VsyncEventData(frameTimelineVsyncId, frameDeadline, frameInterval));
262     }
263 
264     // Called from native code.
265     @SuppressWarnings("unused")
266     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchHotplug(long timestampNanos, long physicalDisplayId, boolean connected)267     private void dispatchHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
268         onHotplug(timestampNanos, physicalDisplayId, connected);
269     }
270 
271     // Called from native code.
272     @SuppressWarnings("unused")
dispatchModeChanged(long timestampNanos, long physicalDisplayId, int modeId)273     private void dispatchModeChanged(long timestampNanos, long physicalDisplayId, int modeId) {
274         onModeChanged(timestampNanos, physicalDisplayId, modeId);
275     }
276 
277     // Called from native code.
278     @SuppressWarnings("unused")
dispatchFrameRateOverrides(long timestampNanos, long physicalDisplayId, FrameRateOverride[] overrides)279     private void dispatchFrameRateOverrides(long timestampNanos, long physicalDisplayId,
280             FrameRateOverride[] overrides) {
281         onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides);
282     }
283 
284 }
285