blob: 0ecc05f1054b93b5975bee61da9db22c506456e1 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/tracing/base/sorted_array_utils.html">
<script>
'use strict';
/**
* @fileoverview Class for representing SurfaceFlinger process and its Vsyncs.
*/
tr.exportTo('tr.model.helpers', function() {
var findLowIndexInSortedArray = tr.b.findLowIndexInSortedArray;
var VSYNC_SF_NAME = 'android.VSYNC-sf';
var VSYNC_APP_NAME = 'android.VSYNC-app';
var VSYNC_FALLBACK_NAME = 'android.VSYNC';
// when sampling vsync, push samples back by this much to ensure
// frame start samples *between* vsyncs
var TIMESTAMP_FUDGE_MS = 0.01;
function getVsyncTimestamps(process, counterName) {
var vsync = process.counters[counterName];
if (!vsync)
vsync = process.counters[VSYNC_FALLBACK_NAME];
if (vsync && vsync.numSeries == 1 && vsync.numSamples > 1)
return vsync.series[0].timestamps;
return undefined;
}
/**
* Model for SurfaceFlinger specific data.
* @constructor
*/
function AndroidSurfaceFlinger(process, thread) {
this.process = process;
this.thread = thread;
this.appVsync_ = undefined;
this.sfVsync_ = undefined;
this.appVsyncTimestamps_ = getVsyncTimestamps(process, VSYNC_APP_NAME);
this.sfVsyncTimestamps_ = getVsyncTimestamps(process, VSYNC_SF_NAME);
};
AndroidSurfaceFlinger.createForProcessIfPossible = function(process) {
var mainThread = process.getThread(process.pid);
// newer versions - main thread, lowercase name, preceeding forward slash
if (mainThread && mainThread.name &&
/surfaceflinger/.test(mainThread.name))
return new AndroidSurfaceFlinger(process, mainThread);
// older versions - another thread is named SurfaceFlinger
var primaryThreads = process.findAllThreadsNamed('SurfaceFlinger');
if (primaryThreads.length == 1)
return new AndroidSurfaceFlinger(process, primaryThreads[0]);
return undefined;
};
AndroidSurfaceFlinger.prototype = {
get hasVsyncs() {
return !!this.appVsyncTimestamps_ && !!this.sfVsyncTimestamps_;
},
getFrameKickoff: function(timestamp) {
if (!this.hasVsyncs)
throw new Error('cannot query vsync info without vsyncs');
var firstGreaterIndex =
findLowIndexInSortedArray(this.appVsyncTimestamps_,
function(x) { return x; },
timestamp + TIMESTAMP_FUDGE_MS);
if (firstGreaterIndex < 1)
return undefined;
return this.appVsyncTimestamps_[firstGreaterIndex - 1];
},
getFrameDeadline: function(timestamp) {
if (!this.hasVsyncs)
throw new Error('cannot query vsync info without vsyncs');
var firstGreaterIndex =
findLowIndexInSortedArray(this.sfVsyncTimestamps_,
function(x) { return x; },
timestamp + TIMESTAMP_FUDGE_MS);
if (firstGreaterIndex >= this.sfVsyncTimestamps_.length)
return undefined;
return this.sfVsyncTimestamps_[firstGreaterIndex];
}
};
return {
AndroidSurfaceFlinger: AndroidSurfaceFlinger
};
});
</script>