• 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);
nativeGetLatestVsyncEventData(long receiverPtr)87     private static native VsyncEventData nativeGetLatestVsyncEventData(long receiverPtr);
88 
89     /**
90      * Creates a display event receiver.
91      *
92      * @param looper The looper to use when invoking callbacks.
93      */
94     @UnsupportedAppUsage
DisplayEventReceiver(Looper looper)95     public DisplayEventReceiver(Looper looper) {
96         this(looper, VSYNC_SOURCE_APP, 0);
97     }
98 
99     /**
100      * Creates a display event receiver.
101      *
102      * @param looper The looper to use when invoking callbacks.
103      * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
104      * @param eventRegistration Which events to dispatch. Must be a bitfield consist of the
105      * EVENT_REGISTRATION_*_FLAG values.
106      */
DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration)107     public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) {
108         if (looper == null) {
109             throw new IllegalArgumentException("looper must not be null");
110         }
111 
112         mMessageQueue = looper.getQueue();
113         mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
114                 vsyncSource, eventRegistration);
115     }
116 
117     @Override
finalize()118     protected void finalize() throws Throwable {
119         try {
120             dispose(true);
121         } finally {
122             super.finalize();
123         }
124     }
125 
126     /**
127      * Disposes the receiver.
128      */
dispose()129     public void dispose() {
130         dispose(false);
131     }
132 
dispose(boolean finalized)133     private void dispose(boolean finalized) {
134         if (mReceiverPtr != 0) {
135             nativeDispose(mReceiverPtr);
136             mReceiverPtr = 0;
137         }
138         mMessageQueue = null;
139     }
140 
141     static final class VsyncEventData {
142 
143         static final FrameTimeline[] INVALID_FRAME_TIMELINES =
144                 {new FrameTimeline(FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE)};
145 
146         public static class FrameTimeline {
FrameTimeline(long vsyncId, long expectedPresentTime, long deadline)147             FrameTimeline(long vsyncId, long expectedPresentTime, long deadline) {
148                 this.vsyncId = vsyncId;
149                 this.expectedPresentTime = expectedPresentTime;
150                 this.deadline = deadline;
151             }
152 
153             // The frame timeline vsync id, used to correlate a frame
154             // produced by HWUI with the timeline data stored in Surface Flinger.
155             public final long vsyncId;
156 
157             // The frame timestamp for when the frame is expected to be presented.
158             public final long expectedPresentTime;
159 
160             // The frame deadline timestamp in {@link System#nanoTime()} timebase that it is
161             // allotted for the frame to be completed.
162             public final long deadline;
163         }
164 
165         /**
166          * The current interval between frames in ns. This will be used to align
167          * {@link FrameInfo#VSYNC} to the current vsync in case Choreographer callback was heavily
168          * delayed by the app.
169          */
170         public final long frameInterval;
171 
172         public final FrameTimeline[] frameTimelines;
173 
174         public final int preferredFrameTimelineIndex;
175 
176         // Called from native code.
177         @SuppressWarnings("unused")
VsyncEventData(FrameTimeline[] frameTimelines, int preferredFrameTimelineIndex, long frameInterval)178         VsyncEventData(FrameTimeline[] frameTimelines, int preferredFrameTimelineIndex,
179                 long frameInterval) {
180             this.frameTimelines = frameTimelines;
181             this.preferredFrameTimelineIndex = preferredFrameTimelineIndex;
182             this.frameInterval = frameInterval;
183         }
184 
VsyncEventData()185         VsyncEventData() {
186             this.frameInterval = -1;
187             this.frameTimelines = INVALID_FRAME_TIMELINES;
188             this.preferredFrameTimelineIndex = 0;
189         }
190 
preferredFrameTimeline()191         public FrameTimeline preferredFrameTimeline() {
192             return frameTimelines[preferredFrameTimelineIndex];
193         }
194     }
195 
196     /**
197      * Called when a vertical sync pulse is received.
198      * The recipient should render a frame and then call {@link #scheduleVsync}
199      * to schedule the next vertical sync pulse.
200      *
201      * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
202      * timebase.
203      * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
204      * @param frame The frame number.  Increases by one for each vertical sync interval.
205      * @param vsyncEventData The vsync event data.
206      */
onVsync(long timestampNanos, long physicalDisplayId, int frame, VsyncEventData vsyncEventData)207     public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
208             VsyncEventData vsyncEventData) {
209     }
210 
211     /**
212      * Called when a display hotplug event is received.
213      *
214      * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
215      * timebase.
216      * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
217      * @param connected True if the display is connected, false if it disconnected.
218      */
219     @UnsupportedAppUsage
onHotplug(long timestampNanos, long physicalDisplayId, boolean connected)220     public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
221     }
222 
223     /**
224      * Called when a display mode changed event is received.
225      *
226      * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
227      * timebase.
228      * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
229      * @param modeId The new mode Id
230      */
onModeChanged(long timestampNanos, long physicalDisplayId, int modeId)231     public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId) {
232     }
233 
234     /**
235      * Represents a mapping between a UID and an override frame rate
236      */
237     public static class FrameRateOverride {
238         // The application uid
239         public final int uid;
240 
241         // The frame rate that this application runs at
242         public final float frameRateHz;
243 
244 
245         @VisibleForTesting
FrameRateOverride(int uid, float frameRateHz)246         public FrameRateOverride(int uid, float frameRateHz) {
247             this.uid = uid;
248             this.frameRateHz = frameRateHz;
249         }
250 
251         @Override
toString()252         public String toString() {
253             return "{uid=" + uid + " frameRateHz=" + frameRateHz + "}";
254         }
255     }
256 
257     /**
258      * Called when frame rate override event is received.
259      *
260      * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
261      * timebase.
262      * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
263      * @param overrides The mappings from uid to frame rates
264      */
onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, FrameRateOverride[] overrides)265     public void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
266             FrameRateOverride[] overrides) {
267     }
268 
269     /**
270      * Schedules a single vertical sync pulse to be delivered when the next
271      * display frame begins.
272      */
273     @UnsupportedAppUsage
scheduleVsync()274     public void scheduleVsync() {
275         if (mReceiverPtr == 0) {
276             Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
277                     + "receiver has already been disposed.");
278         } else {
279             nativeScheduleVsync(mReceiverPtr);
280         }
281     }
282 
283     /**
284      * Gets the latest vsync event data from surface flinger.
285      */
getLatestVsyncEventData()286     VsyncEventData getLatestVsyncEventData() {
287         return nativeGetLatestVsyncEventData(mReceiverPtr);
288     }
289 
290     // Called from native code.
291     @SuppressWarnings("unused")
dispatchVsync(long timestampNanos, long physicalDisplayId, int frame, VsyncEventData vsyncEventData)292     private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
293             VsyncEventData vsyncEventData) {
294         onVsync(timestampNanos, physicalDisplayId, frame, vsyncEventData);
295     }
296 
297     // Called from native code.
298     @SuppressWarnings("unused")
299     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchHotplug(long timestampNanos, long physicalDisplayId, boolean connected)300     private void dispatchHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
301         onHotplug(timestampNanos, physicalDisplayId, connected);
302     }
303 
304     // Called from native code.
305     @SuppressWarnings("unused")
dispatchModeChanged(long timestampNanos, long physicalDisplayId, int modeId)306     private void dispatchModeChanged(long timestampNanos, long physicalDisplayId, int modeId) {
307         onModeChanged(timestampNanos, physicalDisplayId, modeId);
308     }
309 
310     // Called from native code.
311     @SuppressWarnings("unused")
dispatchFrameRateOverrides(long timestampNanos, long physicalDisplayId, FrameRateOverride[] overrides)312     private void dispatchFrameRateOverrides(long timestampNanos, long physicalDisplayId,
313             FrameRateOverride[] overrides) {
314         onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides);
315     }
316 
317 }
318