1<!DOCTYPE html> 2<!-- 3Copyright (c) 2015 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="import" href="/tracing/base/sorted_array_utils.html"> 9 10<script> 11'use strict'; 12 13/** 14 * @fileoverview Class for representing SurfaceFlinger process and its Vsyncs. 15 */ 16tr.exportTo('tr.model.helpers', function() { 17 var findLowIndexInSortedArray = tr.b.findLowIndexInSortedArray; 18 19 var VSYNC_SF_NAME = 'android.VSYNC-sf'; 20 var VSYNC_APP_NAME = 'android.VSYNC-app'; 21 var VSYNC_FALLBACK_NAME = 'android.VSYNC'; 22 23 // when sampling vsync, push samples back by this much to ensure 24 // frame start samples *between* vsyncs 25 var TIMESTAMP_FUDGE_MS = 0.01; 26 27 function getVsyncTimestamps(process, counterName) { 28 29 var vsync = process.counters[counterName]; 30 if (!vsync) 31 vsync = process.counters[VSYNC_FALLBACK_NAME]; 32 33 if (vsync && vsync.numSeries == 1 && vsync.numSamples > 1) 34 return vsync.series[0].timestamps; 35 return undefined; 36 } 37 38 /** 39 * Model for SurfaceFlinger specific data. 40 * @constructor 41 */ 42 function AndroidSurfaceFlinger(process, thread) { 43 this.process = process; 44 this.thread = thread; 45 46 this.appVsync_ = undefined; 47 this.sfVsync_ = undefined; 48 49 this.appVsyncTimestamps_ = getVsyncTimestamps(process, VSYNC_APP_NAME); 50 this.sfVsyncTimestamps_ = getVsyncTimestamps(process, VSYNC_SF_NAME); 51 }; 52 53 AndroidSurfaceFlinger.createForProcessIfPossible = function(process) { 54 var mainThread = process.getThread(process.pid); 55 56 // newer versions - main thread, lowercase name, preceeding forward slash 57 if (mainThread && mainThread.name && 58 /surfaceflinger/.test(mainThread.name)) 59 return new AndroidSurfaceFlinger(process, mainThread); 60 61 // older versions - another thread is named SurfaceFlinger 62 var primaryThreads = process.findAllThreadsNamed('SurfaceFlinger'); 63 if (primaryThreads.length == 1) 64 return new AndroidSurfaceFlinger(process, primaryThreads[0]); 65 return undefined; 66 }; 67 68 AndroidSurfaceFlinger.prototype = { 69 get hasVsyncs() { 70 return !!this.appVsyncTimestamps_ && !!this.sfVsyncTimestamps_; 71 }, 72 73 getFrameKickoff: function(timestamp) { 74 if (!this.hasVsyncs) 75 throw new Error('cannot query vsync info without vsyncs'); 76 77 var firstGreaterIndex = 78 findLowIndexInSortedArray(this.appVsyncTimestamps_, 79 function(x) { return x; }, 80 timestamp + TIMESTAMP_FUDGE_MS); 81 82 if (firstGreaterIndex < 1) 83 return undefined; 84 return this.appVsyncTimestamps_[firstGreaterIndex - 1]; 85 }, 86 87 getFrameDeadline: function(timestamp) { 88 if (!this.hasVsyncs) 89 throw new Error('cannot query vsync info without vsyncs'); 90 91 var firstGreaterIndex = 92 findLowIndexInSortedArray(this.sfVsyncTimestamps_, 93 function(x) { return x; }, 94 timestamp + TIMESTAMP_FUDGE_MS); 95 if (firstGreaterIndex >= this.sfVsyncTimestamps_.length) 96 return undefined; 97 return this.sfVsyncTimestamps_[firstGreaterIndex]; 98 } 99 }; 100 101 return { 102 AndroidSurfaceFlinger: AndroidSurfaceFlinger 103 }; 104}); 105</script> 106