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