1 /* <lambda>null2 * Copyright (C) 2021 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 package com.android.server.wm.traces.common.service.processors 18 19 import com.android.server.wm.traces.common.DeviceStateDump 20 import com.android.server.wm.traces.common.layers.LayerTraceEntry 21 import com.android.server.wm.traces.common.layers.LayersTrace 22 import com.android.server.wm.traces.common.service.ITagProcessor 23 import com.android.server.wm.traces.common.tags.Tag 24 import com.android.server.wm.traces.common.tags.TagState 25 import com.android.server.wm.traces.common.tags.TagTrace 26 import com.android.server.wm.traces.common.tags.Transition 27 import com.android.server.wm.traces.common.windowmanager.WindowManagerState 28 import com.android.server.wm.traces.common.windowmanager.WindowManagerTrace 29 30 /** 31 * This class implements the relevant methods such as generating tags, creating dumps for the 32 * WindowManager and SurfaceFlinger traces, and ensuring the 1:1 correspondence between the start 33 * and end tags invariant is maintained by [BaseFsmState]. 34 */ 35 abstract class TransitionProcessor(internal val logger: (String) -> Unit) : ITagProcessor { 36 abstract val transition: Transition 37 abstract fun getInitialState(tags: MutableMap<Long, MutableList<Tag>>): BaseState 38 39 abstract inner class BaseState( 40 tags: MutableMap<Long, MutableList<Tag>> 41 ) : BaseFsmState(tags, logger, transition) { 42 abstract override fun doProcessState( 43 previous: DeviceStateDump<WindowManagerState, LayerTraceEntry>?, 44 current: DeviceStateDump<WindowManagerState, LayerTraceEntry>, 45 next: DeviceStateDump<WindowManagerState, LayerTraceEntry> 46 ): FSMState 47 } 48 49 /** 50 * Add the start and end tags corresponding to the transition from 51 * the WindowManager and SurfaceFlinger traces 52 * @param wmTrace - WindowManager trace 53 * @param layersTrace - SurfaceFlinger trace 54 * @return [TagTrace] - containing all the newly generated tags in states with 55 * timestamps 56 */ 57 override fun generateTags( 58 wmTrace: WindowManagerTrace, 59 layersTrace: LayersTrace 60 ): TagTrace { 61 val tags = mutableMapOf<Long, MutableList<Tag>>() 62 var currPosition: FSMState? = getInitialState(tags) 63 64 val dumpList = createDumpList(wmTrace, layersTrace) 65 val dumpIterator = dumpList.iterator() 66 67 // keep always a reference to previous, current and next states 68 var previous: DeviceStateDump<WindowManagerState, LayerTraceEntry>? 69 var current: DeviceStateDump<WindowManagerState, LayerTraceEntry>? = null 70 var next: DeviceStateDump<WindowManagerState, LayerTraceEntry>? = dumpIterator.next() 71 while (currPosition != null) { 72 previous = current 73 current = next 74 next = if (dumpIterator.hasNext()) dumpIterator.next() else null 75 requireNotNull(current) { "Current state shouldn't be null" } 76 val newPosition = currPosition.process(previous, current, next) 77 currPosition = newPosition 78 } 79 80 return buildTagTrace(tags) 81 } 82 83 private fun buildTagTrace(tags: MutableMap<Long, MutableList<Tag>>): TagTrace { 84 val tagStates = tags.map { entry -> 85 val timestamp = entry.key 86 val stateTags = entry.value 87 TagState(timestamp.toString(), stateTags.toTypedArray()) 88 } 89 return TagTrace(tagStates.toTypedArray(), source = "") 90 } 91 92 companion object { 93 internal fun createDumpList( 94 wmTrace: WindowManagerTrace, 95 layersTrace: LayersTrace 96 ): List<DeviceStateDump<WindowManagerState, LayerTraceEntry>> { 97 val wmTimestamps = wmTrace.map { it.timestamp }.toTypedArray() 98 val layersTimestamps = layersTrace.map { it.timestamp }.toTypedArray() 99 val fullTimestamps = setOf(*wmTimestamps, *layersTimestamps).sorted() 100 101 return fullTimestamps.map { baseTimestamp -> 102 val wmState = wmTrace 103 .lastOrNull { it.timestamp <= baseTimestamp } 104 ?: wmTrace.first() 105 val layerState = layersTrace 106 .lastOrNull { it.timestamp <= baseTimestamp } 107 ?: layersTrace.first() 108 DeviceStateDump(wmState, layerState) 109 }.distinctBy { Pair(it.wmState.timestamp, it.layerState.timestamp) } 110 } 111 } 112 } 113