blob: a4d4fed9f6699cab45f938476fe76d237dc7f1bc [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:JvmName("Extensions")
package com.android.server.wm.traces.parser
import android.app.UiAutomation
import android.content.ComponentName
import android.os.ParcelFileDescriptor
import android.os.Trace
import android.util.Log
import com.android.server.wm.traces.common.CrossPlatform
import com.android.server.wm.traces.common.DeviceStateDump
import com.android.server.wm.traces.common.LoggerBuilder
import com.android.server.wm.traces.common.NullableDeviceStateDump
import com.android.server.wm.traces.common.Rect
import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import com.android.server.wm.traces.common.layers.BaseLayerTraceEntry
import com.android.server.wm.traces.common.windowmanager.WindowManagerState
internal const val LOG_TAG = "AMWM_FLICKER"
val ANDROID_LOGGER =
LoggerBuilder()
.setD { tag, msg -> Log.d(tag, msg) }
.setI { tag, msg -> Log.i(tag, msg) }
.setW { tag, msg -> Log.w(tag, msg) }
.setE { tag, msg, error -> Log.e(tag, msg, error) }
.setOnTracing { name, predicate ->
try {
Trace.beginSection(name)
predicate()
} finally {
Trace.endSection()
}
}
.build()
fun Rect.toAndroidRect(): android.graphics.Rect {
return android.graphics.Rect(left, top, right, bottom)
}
fun android.graphics.Rect.toFlickerRect(): Rect {
return Rect.from(left, top, right, bottom)
}
private fun executeCommand(uiAutomation: UiAutomation, cmd: String): ByteArray {
val fileDescriptor = uiAutomation.executeShellCommand(cmd)
ParcelFileDescriptor.AutoCloseInputStream(fileDescriptor).use { inputStream ->
return inputStream.readBytes()
}
}
private fun getCurrentWindowManagerState(uiAutomation: UiAutomation) =
executeCommand(uiAutomation, "dumpsys window --proto")
private fun getCurrentLayersState(uiAutomation: UiAutomation) =
executeCommand(uiAutomation, "dumpsys SurfaceFlinger --proto")
/**
* Gets the current device state dump containing the [WindowManagerState] (optional) and the
* [BaseLayerTraceEntry] (optional) in raw (byte) data.
*
* @param dumpFlags Flags determining which types of traces should be included in the dump
*/
@JvmOverloads
fun getCurrentState(
uiAutomation: UiAutomation,
@WmStateDumpFlags dumpFlags: Int = FLAG_STATE_DUMP_FLAG_WM.or(FLAG_STATE_DUMP_FLAG_LAYERS)
): Pair<ByteArray, ByteArray> {
if (dumpFlags == 0) {
throw IllegalArgumentException("No dump specified")
}
CrossPlatform.log.d(LOG_TAG, "Requesting new device state dump")
val wmTraceData =
if (dumpFlags.and(FLAG_STATE_DUMP_FLAG_WM) > 0) {
getCurrentWindowManagerState(uiAutomation)
} else {
ByteArray(0)
}
val layersTraceData =
if (dumpFlags.and(FLAG_STATE_DUMP_FLAG_LAYERS) > 0) {
getCurrentLayersState(uiAutomation)
} else {
ByteArray(0)
}
return Pair(wmTraceData, layersTraceData)
}
/**
* Gets the current device state dump containing the [WindowManagerState] (optional) and the
* [BaseLayerTraceEntry] (optional) parsed
*
* @param dumpFlags Flags determining which types of traces should be included in the dump
* @param clearCacheAfterParsing If the caching used while parsing the proto should be
* ```
* cleared or remain in memory
* ```
*/
@JvmOverloads
fun getCurrentStateDumpNullable(
uiAutomation: UiAutomation,
@WmStateDumpFlags dumpFlags: Int = FLAG_STATE_DUMP_FLAG_WM.or(FLAG_STATE_DUMP_FLAG_LAYERS),
clearCacheAfterParsing: Boolean
): NullableDeviceStateDump {
val currentStateDump = getCurrentState(uiAutomation, dumpFlags)
return DeviceDumpParser.fromNullableDump(
currentStateDump.first,
currentStateDump.second,
clearCacheAfterParsing = clearCacheAfterParsing
)
}
fun getCurrentStateDump(
uiAutomation: UiAutomation,
clearCacheAfterParsing: Boolean
): DeviceStateDump {
val currentStateDump = getCurrentState(uiAutomation)
return DeviceDumpParser.fromDump(
currentStateDump.first,
currentStateDump.second,
clearCacheAfterParsing = clearCacheAfterParsing
)
}
/** Converts an Android [ComponentName] into a flicker [ComponentNameMatcher] */
fun ComponentName.toFlickerComponent(): ComponentNameMatcher =
ComponentNameMatcher(this.packageName, this.className)