EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.content.browser]

COVERAGE SUMMARY FOR SOURCE FILE [VSyncMonitor.java]

nameclass, %method, %block, %line, %
VSyncMonitor.java67%  (2/3)78%  (14/18)77%  (229/299)77%  (51/66)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class VSyncMonitor$10%   (0/1)0%   (0/2)0%   (0/13)0%   (0/4)
VSyncMonitor$1 (VSyncMonitor): void 0%   (0/1)0%   (0/6)0%   (0/1)
doFrame (long): void 0%   (0/1)0%   (0/7)0%   (0/3)
     
class VSyncMonitor100% (1/1)86%  (12/14)79%  (216/273)80%  (48/60)
setVSyncPointForICS (long): void 0%   (0/1)0%   (0/4)0%   (0/2)
unregisterListener (): void 0%   (0/1)0%   (0/6)0%   (0/3)
postCallback (): void 100% (1/1)68%  (13/19)83%  (5/6)
isVSyncSignalAvailable (): boolean 100% (1/1)71%  (5/7)71%  (0.7/1)
<static initializer> 100% (1/1)75%  (6/8)75%  (0.8/1)
VSyncMonitor (Context, VSyncMonitor$Listener, boolean): void 100% (1/1)75%  (55/73)77%  (13.9/18)
postRunnableCallback (): void 100% (1/1)84%  (76/91)91%  (10/11)
onVSyncCallback (long): void 100% (1/1)88%  (30/34)94%  (7.6/8)
VSyncMonitor (Context, VSyncMonitor$Listener): void 100% (1/1)100% (6/6)100% (2/2)
access$000 (VSyncMonitor, long): void 100% (1/1)100% (4/4)100% (1/1)
getCurrentNanoTime (): long 100% (1/1)100% (2/2)100% (1/1)
getVSyncPeriodInMicroseconds (): long 100% (1/1)100% (5/5)100% (1/1)
requestUpdate (): void 100% (1/1)100% (10/10)100% (4/4)
stop (): void 100% (1/1)100% (4/4)100% (2/2)
     
class VSyncMonitor$2100% (1/1)100% (2/2)100% (13/13)100% (4/4)
VSyncMonitor$2 (VSyncMonitor): void 100% (1/1)100% (6/6)100% (1/1)
run (): void 100% (1/1)100% (7/7)100% (3/3)

1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4 
5package org.chromium.content.browser;
6 
7import android.content.Context;
8import android.os.Build;
9import android.os.Handler;
10import android.view.Choreographer;
11import android.view.WindowManager;
12 
13import org.chromium.content.common.TraceEvent;
14 
15/**
16 * Notifies clients of the default displays's vertical sync pulses.
17 * This class works in "burst" mode: once the update is requested, the listener will be
18 * called MAX_VSYNC_COUNT times on the vertical sync pulses (on JB) or on every refresh
19 * period (on ICS, see below), unless stop() is called.
20 * On ICS, VSyncMonitor relies on setVSyncPointForICS() being called to set a reasonable
21 * approximation of a vertical sync starting point; see also http://crbug.com/156397.
22 */
23public class VSyncMonitor {
24    private static final String TAG = "VSyncMonitor";
25 
26    public interface Listener {
27        /**
28         * Called very soon after the start of the display's vertical sync period.
29         * @param monitor The VSyncMonitor that triggered the signal.
30         * @param vsyncTimeMicros Absolute frame time in microseconds.
31         */
32        public void onVSync(VSyncMonitor monitor, long vsyncTimeMicros);
33    }
34 
35    private static final long NANOSECONDS_PER_SECOND = 1000000000;
36    private static final long NANOSECONDS_PER_MILLISECOND = 1000000;
37    private static final long NANOSECONDS_PER_MICROSECOND = 1000;
38 
39    private Listener mListener;
40 
41    // Display refresh rate as reported by the system.
42    private final long mRefreshPeriodNano;
43 
44    // Last time requestUpdate() was called.
45    private long mLastUpdateRequestNano;
46 
47    private boolean mHaveRequestInFlight;
48 
49    private int mTriggerNextVSyncCount;
50    private static final int MAX_VSYNC_COUNT = 5;
51 
52    // Choreographer is used to detect vsync on >= JB.
53    private final Choreographer mChoreographer;
54    private final Choreographer.FrameCallback mVSyncFrameCallback;
55 
56    // On ICS we just post a task through the handler (http://crbug.com/156397)
57    private final Handler mHandler;
58    private final Runnable mVSyncRunnableCallback;
59    private long mGoodStartingPointNano;
60    private long mLastPostedNano;
61 
62    public VSyncMonitor(Context context, VSyncMonitor.Listener listener) {
63        this(context, listener, true);
64    }
65 
66    VSyncMonitor(Context context, VSyncMonitor.Listener listener, boolean enableJBVSync) {
67        mListener = listener;
68        float refreshRate = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
69                .getDefaultDisplay().getRefreshRate();
70        if (refreshRate <= 0) refreshRate = 60;
71        mRefreshPeriodNano = (long) (NANOSECONDS_PER_SECOND / refreshRate);
72        mTriggerNextVSyncCount = 0;
73 
74        if (enableJBVSync && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
75            // Use Choreographer on JB+ to get notified of vsync.
76            mChoreographer = Choreographer.getInstance();
77            mVSyncFrameCallback = new Choreographer.FrameCallback() {
78                @Override
79                public void doFrame(long frameTimeNanos) {
80                    TraceEvent.instant("VSync");
81                    onVSyncCallback(frameTimeNanos);
82                }
83            };
84            mHandler = null;
85            mVSyncRunnableCallback = null;
86        } else {
87            // On ICS we just hope that running tasks is relatively predictable.
88            mChoreographer = null;
89            mVSyncFrameCallback = null;
90            mHandler = new Handler();
91            mVSyncRunnableCallback = new Runnable() {
92                @Override
93                public void run() {
94                    TraceEvent.instant("VSyncTimer");
95                    onVSyncCallback(System.nanoTime());
96                }
97            };
98            mGoodStartingPointNano = getCurrentNanoTime();
99            mLastPostedNano = 0;
100        }
101    }
102 
103    /**
104     * Returns the time interval between two consecutive vsync pulses in microseconds.
105     */
106    public long getVSyncPeriodInMicroseconds() {
107        return mRefreshPeriodNano / NANOSECONDS_PER_MICROSECOND;
108    }
109 
110    /**
111     * Determine whether a true vsync signal is available on this platform.
112     */
113    public boolean isVSyncSignalAvailable() {
114        return mChoreographer != null;
115    }
116 
117    /**
118     * Stop reporting vsync events. Note that at most one pending vsync event can still be delivered
119     * after this function is called.
120     */
121    public void stop() {
122        mTriggerNextVSyncCount = 0;
123    }
124 
125    /**
126     * Unregister the listener.
127     * No vsync events will be reported afterwards.
128     */
129    public void unregisterListener() {
130        stop();
131        mListener = null;
132    }
133 
134    /**
135     * Request to be notified of the closest display vsync events.
136     * Listener.onVSync() will be called soon after the upcoming vsync pulses.
137     * It will be called at most MAX_VSYNC_COUNT times unless requestUpdate() is called again.
138     */
139    public void requestUpdate() {
140        mTriggerNextVSyncCount = MAX_VSYNC_COUNT;
141        mLastUpdateRequestNano = getCurrentNanoTime();
142        postCallback();
143    }
144 
145    /**
146     * Set the best guess of the point in the past when the vsync has happened.
147     * @param goodStartingPointNano Known vsync point in the past.
148     */
149    public void setVSyncPointForICS(long goodStartingPointNano) {
150        mGoodStartingPointNano = goodStartingPointNano;
151    }
152 
153    private long getCurrentNanoTime() {
154        return System.nanoTime();
155    }
156 
157    private void onVSyncCallback(long frameTimeNanos) {
158        assert mHaveRequestInFlight;
159        mHaveRequestInFlight = false;
160        if (mTriggerNextVSyncCount > 0) {
161            mTriggerNextVSyncCount--;
162            postCallback();
163        }
164        if (mListener != null) {
165            mListener.onVSync(this, frameTimeNanos / NANOSECONDS_PER_MICROSECOND);
166        }
167    }
168 
169    private void postCallback() {
170        if (mHaveRequestInFlight) return;
171        mHaveRequestInFlight = true;
172        if (isVSyncSignalAvailable()) {
173            mChoreographer.postFrameCallback(mVSyncFrameCallback);
174        } else {
175            postRunnableCallback();
176        }
177    }
178 
179    private void postRunnableCallback() {
180        assert !isVSyncSignalAvailable();
181        final long currentTime = mLastUpdateRequestNano;
182        final long lastRefreshTime = mGoodStartingPointNano +
183                ((currentTime - mGoodStartingPointNano) / mRefreshPeriodNano) * mRefreshPeriodNano;
184        long delay = (lastRefreshTime + mRefreshPeriodNano) - currentTime;
185        assert delay >= 0 && delay < mRefreshPeriodNano;
186 
187        if (currentTime + delay <= mLastPostedNano + mRefreshPeriodNano / 2) {
188            delay += mRefreshPeriodNano;
189        }
190 
191        mLastPostedNano = currentTime + delay;
192        if (delay == 0) mHandler.post(mVSyncRunnableCallback);
193        else mHandler.postDelayed(mVSyncRunnableCallback, delay / NANOSECONDS_PER_MILLISECOND);
194    }
195}

[all classes][org.chromium.content.browser]
EMMA 2.0.5312 (C) Vladimir Roubtsov