[6] Fix infinite loop for IME processing
Previously, some Winscope traces and ADB captures will go into an
infinite loop after IME processing was introduced.
The issue was a loop in filtering the SF Layer node that did not
account for multi-windowing mode or cases where the expected parent
could not be found. This commit fixes this issue.
Bug: 236679852
Test: manual with previously failing traces
Change-Id: I8d3fe42802efa195926b5be0d4242a0bb0696988
diff --git a/tools/winscope/src/ime_processing.js b/tools/winscope/src/ime_processing.js
index 2670ee3..98a48d7 100644
--- a/tools/winscope/src/ime_processing.js
+++ b/tools/winscope/src/ime_processing.js
@@ -46,11 +46,13 @@
filetype.includes('ImeTrace'))).map(([k, v]) => v);
for (const imeTraceFile of imeTraceFiles) {
if (filesAsDict[TRACE_TYPES.WINDOW_MANAGER]) {
+ console.log('combining WM file to', imeTraceFile.type, 'file');
combineWmSfPropertiesIntoImeData(imeTraceFile,
filesAsDict[TRACE_TYPES.WINDOW_MANAGER]);
}
if (filesAsDict[TRACE_TYPES.SURFACE_FLINGER] &&
imeTraceFile.type !== TRACE_TYPES.IME_MANAGERSERVICE) {
+ console.log('combining SF file to', imeTraceFile.type, 'file');
// don't need SF properties for ime manager service
combineWmSfPropertiesIntoImeData(imeTraceFile,
filesAsDict[TRACE_TYPES.SURFACE_FLINGER]);
@@ -61,25 +63,14 @@
function combineWmSfPropertiesIntoImeData(imeTraceFile, wmOrSfTraceFile) {
const imeTimestamps = imeTraceFile.timeline;
- const wmOrSfData = wmOrSfTraceFile.data;
const wmOrSfTimestamps = wmOrSfTraceFile.timeline;
+ const intersectWmOrSfIndices =
+ matchCorrespondingTimestamps(imeTimestamps, wmOrSfTimestamps);
- // find the latest sf / wm timestamp that comes before current ime timestamp
- let wmOrSfIndex = 0;
- const intersectWmOrSfIndices = [];
- for (let imeIndex = 0; imeIndex < imeTimestamps.length; imeIndex++) {
- const currImeTimestamp = imeTimestamps[imeIndex];
+ const wmOrSfData = wmOrSfTraceFile.data;
- let currWmOrSfTimestamp = wmOrSfTimestamps[wmOrSfIndex];
- while (currWmOrSfTimestamp < currImeTimestamp) {
- wmOrSfIndex++;
- currWmOrSfTimestamp = wmOrSfTimestamps[wmOrSfIndex];
- }
- intersectWmOrSfIndices.push(wmOrSfIndex - 1);
- }
-
+ console.log('number of entries:', imeTimestamps.length);
for (let i = 0; i < imeTimestamps.length; i++) {
- // TODO: abstract into one function
const wmOrSfIntersectIndex = intersectWmOrSfIndices[i];
let wmStateOrSfLayer = wmOrSfData[wmOrSfIntersectIndex];
if (wmStateOrSfLayer) {
@@ -106,6 +97,23 @@
}
}
+function matchCorrespondingTimestamps(imeTimestamps, wmOrSfTimestamps) {
+ // find the latest sf / wm timestamp that comes before current ime timestamp
+ let wmOrSfIndex = 0;
+ const intersectWmOrSfIndices = [];
+ for (let imeIndex = 0; imeIndex < imeTimestamps.length; imeIndex++) {
+ const currImeTimestamp = imeTimestamps[imeIndex];
+
+ let currWmOrSfTimestamp = wmOrSfTimestamps[wmOrSfIndex];
+ while (currWmOrSfTimestamp < currImeTimestamp) {
+ wmOrSfIndex++;
+ currWmOrSfTimestamp = wmOrSfTimestamps[wmOrSfIndex];
+ }
+ intersectWmOrSfIndices.push(wmOrSfIndex - 1);
+ }
+ console.log('done matching corresponding timestamps');
+ return intersectWmOrSfIndices;
+}
function filterWmStateForIme(wmState) {
// create and return a custom entry that just contains relevant properties
@@ -131,9 +139,11 @@
let resultLayer;
if (parentTaskName === '') {
// there is no ImeContainer; check for ime-snapshot
+ console.log('there is no ImeContainer; checking for IME-snapshot');
const snapshotFilter = getFilter('IME-snapshot');
resultLayer = pruneChildrenByFilter(sfLayer, snapshotFilter);
} else {
+ console.log('found parent task of ImeContainer:', parentTaskName);
const imeParentTaskFilter = getFilter(parentTaskName);
// prune all children that are not part of the "parent task" of ImeContainer
resultLayer = pruneChildrenByFilter(sfLayer, imeParentTaskFilter);
@@ -145,13 +155,14 @@
function findParentTaskNameOfImeContainer(curr) {
const isImeContainer = getFilter('ImeContainer');
if (isImeContainer(curr)) {
+ console.log('found ImeContainer; searching for parent');
let parent = curr.parent;
- const isTask = getFilter('Task');
- while (parent && !isTask(parent)) {
+ const isTask = getFilter('Task, ImePlaceholder');
+ while (parent.parent && !isTask(parent)) {
+ // if parent.parent is null, 'parent' is already the root node -- use it
if (parent.parent != null) {
parent = parent.parent;
}
- // else 'parent' is already the root node; use it
}
return parent.name;
}
diff --git a/tools/winscope/src/utils/utils.js b/tools/winscope/src/utils/utils.js
index db6afcc..5ee25d6 100644
--- a/tools/winscope/src/utils/utils.js
+++ b/tools/winscope/src/utils/utils.js
@@ -110,6 +110,7 @@
const positive = [];
const negative = [];
filterStrings.forEach((f) => {
+ f = f.trim();
if (f.startsWith('!')) {
const regex = new RegExp(f.substring(1), "i");
negative.push((s) => !regex.test(s));