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