1/* 2 * Copyright 2020, 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// Find the index of the last element matching the predicate in a sorted array 18function findLastMatchingSorted(array, predicate) { 19 let a = 0; 20 let b = array.length - 1; 21 while (b - a > 1) { 22 const m = Math.floor((a + b) / 2); 23 if (predicate(array, m)) { 24 a = m; 25 } else { 26 b = m - 1; 27 } 28 } 29 30 return predicate(array, b) ? b : a; 31} 32 33// Make sure stableId is unique (makes old versions of proto compatible) 34function stableIdCompatibilityFixup(item) { 35 // For backwards compatibility 36 // (the only item that doesn't have a unique stable ID in the tree) 37 if (item.stableId === 'winToken|-|') { 38 return item.stableId + item.children[0].stableId; 39 } 40 41 return item.stableId; 42} 43 44const DIRECTION = Object.freeze({ 45 BACKWARD: -1, 46 FORWARD: 1, 47}); 48 49const TimeUnits = Object.freeze({ 50 NANO_SECONDS: 'ns', 51 MILLI_SECONDS: 'ms', 52 SECONDS: 's', 53 MINUTES: 'm', 54 HOURS: 'h', 55 DAYS: 'd', 56}); 57 58function nanosToString(elapsedRealtimeNanos, precision) { 59 const units = [ 60 [1000000, TimeUnits.NANO_SECONDS], 61 [1000, TimeUnits.MILLI_SECONDS], 62 [60, TimeUnits.SECONDS], 63 [60, TimeUnits.MINUTES], 64 [24, TimeUnits.HOURS], 65 [Infinity, TimeUnits.DAYS], 66 ]; 67 68 const parts = []; 69 70 let precisionThresholdReached = false; 71 units.some(([div, timeUnit], i) => { 72 const part = (elapsedRealtimeNanos % div).toFixed() 73 if (timeUnit === precision) { 74 precisionThresholdReached = true; 75 } 76 if (precisionThresholdReached) { 77 parts.push(part + timeUnit); 78 } 79 elapsedRealtimeNanos = Math.floor(elapsedRealtimeNanos / div); 80 81 return elapsedRealtimeNanos == 0; 82 }); 83 84 return parts.reverse().join(''); 85} 86 87/** Checks for match in window manager properties taskId, layerId, or windowToken, 88 * or surface flinger property id 89 */ 90function isPropertyMatch(flickerItem, entryItem) { 91 return flickerItem.taskId === entryItem.taskId || 92 (flickerItem.windowToken === entryItem.windowToken) || 93 ((flickerItem.layerId === entryItem.layerId) && flickerItem.layerId !== 0) || 94 flickerItem.layerId === entryItem.id; 95} 96 97export { 98 DIRECTION, 99 findLastMatchingSorted, 100 isPropertyMatch, 101 stableIdCompatibilityFixup, 102 nanosToString, 103 TimeUnits 104}