1 /* 2 * Copyright (C) 2023 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 android.tools.flicker.subject.layers 17 18 import android.tools.Timestamp 19 import android.tools.datatypes.Size 20 import android.tools.flicker.assertions.Fact 21 import android.tools.flicker.subject.FlickerSubject 22 import android.tools.flicker.subject.region.RegionSubject 23 import android.tools.io.Reader 24 import android.tools.traces.surfaceflinger.Layer 25 26 /** 27 * Subject for [Layer] objects, used to make assertions over behaviors that occur on a single layer 28 * of a SurfaceFlinger state. 29 * 30 * To make assertions over a layer from a state it is recommended to create a subject using 31 * [LayerTraceEntrySubject.layer](layerName) 32 * 33 * Alternatively, it is also possible to use [LayerSubject](myLayer). 34 * 35 * Example: 36 * ``` 37 * val trace = LayersTraceParser().parse(myTraceFile) 38 * val subject = LayersTraceSubject(trace).first() 39 * .layer("ValidLayer") 40 * .exists() 41 * .hasBufferSize(BUFFER_SIZE) 42 * .invoke { myCustomAssertion(this) } 43 * ``` 44 */ 45 class LayerSubject( 46 public override val reader: Reader? = null, 47 override val timestamp: Timestamp, 48 val layer: Layer 49 ) : FlickerSubject() { 50 val isVisible: Boolean 51 get() = layer.isVisible 52 val isInvisible: Boolean 53 get() = !layer.isVisible 54 val name: String 55 get() = layer.name 56 57 /** Visible region calculated by the Composition Engine */ 58 val visibleRegion: RegionSubject 59 get() = RegionSubject(layer.visibleRegion, timestamp, reader) 60 61 val visibilityReason: Collection<String> 62 get() = layer.visibilityReason 63 64 /** 65 * Visible region calculated by the Composition Engine (when available) or calculated based on 66 * the layer bounds and transform 67 */ 68 val screenBounds: RegionSubject 69 get() = RegionSubject(layer.screenBounds, timestamp, reader) 70 71 override val selfFacts = listOf(Fact("Frame", layer.currFrame), Fact("Layer", layer.name)) 72 73 /** If the [layer] exists, executes a custom [assertion] on the current subject */ <lambda>null74 operator fun invoke(assertion: (Layer) -> Unit): LayerSubject = apply { assertion(this.layer) } 75 76 /** 77 * Asserts that current subject has an [Layer.activeBuffer] 78 * 79 * @param expected expected buffer size 80 */ <lambda>null81 fun hasBufferSize(expected: Size): LayerSubject = apply { 82 val bufferSize = Size.from(layer.activeBuffer.width, layer.activeBuffer.height) 83 check { "Buffer size" }.that(bufferSize).isEqual(expected) 84 } 85 86 /** 87 * Asserts that current subject has an [Layer.screenBounds] 88 * 89 * @param expected expected layer bounds size 90 */ <lambda>null91 fun hasLayerSize(expected: Size): LayerSubject = apply { 92 val layerSize = 93 Size.from(layer.screenBounds.width().toInt(), layer.screenBounds.height().toInt()) 94 check { "Number of layers" }.that(layerSize).isEqual(expected) 95 } 96 97 /** Asserts that current subject has an [Layer.effectiveScalingMode] equals to [expected] */ <lambda>null98 fun hasScalingMode(expected: Int): LayerSubject = apply { 99 check { "Scaling mode" }.that(layer.effectiveScalingMode).isEqual(expected) 100 } 101 102 /** 103 * Asserts that current subject has an [Layer.bufferTransform] orientation equals to [expected] 104 */ <lambda>null105 fun hasBufferOrientation(expected: Int): LayerSubject = apply { 106 // see Transform::getOrientation 107 val bufferTransformType = layer.bufferTransform.type ?: 0 108 val actualOrientation = (bufferTransformType shr 8) and 0xFF 109 check { "Buffer orientation" }.that(actualOrientation).isEqual(expected) 110 } 111 toStringnull112 override fun toString(): String { 113 return "Layer:${layer.name} frame#${layer.currFrame}" 114 } 115 } 116