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 package com.android.server.wm.flicker.traces.layers 17 18 import android.graphics.Point 19 import com.android.server.wm.flicker.assertions.Assertion 20 import com.android.server.wm.flicker.assertions.FlickerSubject 21 import com.android.server.wm.flicker.traces.FlickerFailureStrategy 22 import com.android.server.wm.flicker.traces.region.RegionSubject 23 import com.android.server.wm.traces.common.Size 24 import com.android.server.wm.traces.common.layers.Layer 25 import com.google.common.truth.Fact 26 import com.google.common.truth.FailureMetadata 27 import com.google.common.truth.FailureStrategy 28 import com.google.common.truth.StandardSubjectBuilder 29 import com.google.common.truth.Subject.Factory 30 31 /** 32 * Truth subject for [Layer] objects, used to make assertions over behaviors that occur on a 33 * single layer of a SurfaceFlinger state. 34 * 35 * To make assertions over a layer from a state it is recommended to create a subject 36 * using [LayerTraceEntrySubject.layer](layerName) 37 * 38 * Alternatively, it is also possible to use [LayerSubject.assertThat](myLayer) or 39 * Truth.assertAbout([LayerSubject.getFactory]), however they will provide less debug 40 * information because it uses Truth's default [FailureStrategy]. 41 * 42 * Example: 43 * val trace = LayersTraceParser.parseFromTrace(myTraceFile) 44 * val subject = LayersTraceSubject.assertThat(trace).first() 45 * .layer("ValidLayer") 46 * .exists() 47 * .hasBufferSize(BUFFER_SIZE) 48 * .invoke { myCustomAssertion(this) } 49 */ 50 class LayerSubject private constructor( 51 fm: FailureMetadata, 52 override val parent: FlickerSubject, 53 override val timestamp: Long, 54 val layer: Layer?, 55 private val layerName: String? = null 56 ) : FlickerSubject(fm, layer) { 57 val isEmpty: Boolean get() = layer == null 58 val isNotEmpty: Boolean get() = !isEmpty 59 val isVisible: Boolean get() = layer?.isVisible == true 60 val isInvisible: Boolean get() = layer?.isVisible == false 61 val name: String get() = layer?.name ?: "" 62 63 /** 64 * Visible region calculated by the Composition Engine 65 */ 66 val visibleRegion: RegionSubject get() = 67 RegionSubject.assertThat(layer?.visibleRegion, this, timestamp) 68 69 /** 70 * Visible region calculated by the Composition Engine (when available) or calculated 71 * based on the layer bounds and transform 72 */ 73 val screenBounds: RegionSubject get() = 74 RegionSubject.assertThat(layer?.screenBounds, this, timestamp) 75 76 override val selfFacts = if (layer != null) { 77 listOf(Fact.fact("Frame", layer.currFrame), Fact.fact("Layer", layer.name)) 78 } else { 79 listOf(Fact.fact("Layer name", layerName)) 80 } 81 82 /** 83 * If the [layer] exists, executes a custom [assertion] on the current subject 84 */ 85 operator fun invoke(assertion: Assertion<Layer>): LayerSubject = apply { 86 layer ?: return exists() 87 assertion(this.layer) 88 } 89 90 /** 91 * Asserts that current subject doesn't exist in the layer hierarchy 92 */ 93 fun doesNotExist(): LayerSubject = apply { 94 check("doesNotExist").that(layer).isNull() 95 } 96 97 /** 98 * Asserts that current subject exists in the layer hierarchy 99 */ 100 fun exists(): LayerSubject = apply { 101 check("$layerName does not exists").that(layer).isNotNull() 102 } 103 104 @Deprecated("Prefer hasBufferSize(bounds)") 105 fun hasBufferSize(size: Point): LayerSubject = apply { 106 val bounds = Size(size.x, size.y) 107 hasBufferSize(bounds) 108 } 109 110 /** 111 * Asserts that current subject has an [Layer.activeBuffer] with width equals to [Point.x] 112 * and height equals to [Point.y] 113 * 114 * @param size expected buffer size 115 */ 116 fun hasBufferSize(size: Size): LayerSubject = apply { 117 layer ?: return exists() 118 val bufferSize = Size(layer.activeBuffer.width, layer.activeBuffer.height) 119 check("Incorrect buffer size").that(bufferSize).isEqualTo(size) 120 } 121 122 /** 123 * Asserts that current subject has an [Layer.screenBounds] with width equals to [Point.x] 124 * and height equals to [Point.y] 125 * 126 * @param size expected layer bounds size 127 */ 128 fun hasLayerSize(size: Point): LayerSubject = apply { 129 layer ?: return exists() 130 val layerSize = Point(layer.screenBounds.width.toInt(), layer.screenBounds.height.toInt()) 131 check("Incorrect number of layers").that(layerSize).isEqualTo(size) 132 } 133 134 /** 135 * Asserts that current subject has an [Layer.effectiveScalingMode] equals to 136 * [expectedScalingMode] 137 */ 138 fun hasScalingMode(expectedScalingMode: Int): LayerSubject = apply { 139 layer ?: return exists() 140 val actualScalingMode = layer.effectiveScalingMode 141 check("Incorrect scaling mode").that(actualScalingMode).isEqualTo(expectedScalingMode) 142 } 143 144 /** 145 * Asserts that current subject has an [Layer.bufferTransform] orientation equals to 146 * [expectedOrientation] 147 */ 148 fun hasBufferOrientation(expectedOrientation: Int): LayerSubject = apply { 149 layer ?: return exists() 150 // see Transform::getOrientation 151 val bufferTransformType = layer.bufferTransform.type ?: 0 152 val actualOrientation = (bufferTransformType shr 8) and 0xFF 153 check("hasBufferTransformOrientation()") 154 .that(actualOrientation).isEqualTo(expectedOrientation) 155 } 156 157 override fun toString(): String { 158 return "Layer:${layer?.name} frame#${layer?.currFrame}" 159 } 160 161 companion object { 162 /** 163 * Boiler-plate Subject.Factory for LayerSubject 164 */ 165 @JvmStatic 166 fun getFactory(parent: FlickerSubject, timestamp: Long, name: String?) = 167 Factory { fm: FailureMetadata, subject: Layer? -> 168 LayerSubject(fm, parent, timestamp, subject, name) 169 } 170 171 /** 172 * User-defined parent point for existing layers 173 */ 174 @JvmStatic 175 fun assertThat( 176 layer: Layer?, 177 parent: FlickerSubject, 178 timestamp: Long 179 ): LayerSubject { 180 val strategy = FlickerFailureStrategy() 181 val subject = StandardSubjectBuilder.forCustomFailureStrategy(strategy) 182 .about(getFactory(parent, timestamp, name = null)) 183 .that(layer) as LayerSubject 184 strategy.init(subject) 185 return subject 186 } 187 188 /** 189 * User-defined parent point for non existing layers 190 */ 191 @JvmStatic 192 internal fun assertThat( 193 name: String, 194 parent: FlickerSubject, 195 timestamp: Long 196 ): LayerSubject { 197 val strategy = FlickerFailureStrategy() 198 val subject = StandardSubjectBuilder.forCustomFailureStrategy(strategy) 199 .about(getFactory(parent, timestamp, name)) 200 .that(null) as LayerSubject 201 strategy.init(subject) 202 return subject 203 } 204 } 205 }