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 17 package android.tools.flicker.assertors.assertions 18 19 import android.graphics.Region 20 import android.tools.flicker.ScenarioInstance 21 import android.tools.flicker.assertions.FlickerTest 22 import android.tools.flicker.assertors.ComponentTemplate 23 import android.tools.flicker.config.splitscreen.Components.SPLIT_SCREEN_DIVIDER 24 import android.tools.flicker.subject.layers.LayerTraceEntrySubject 25 import android.tools.flicker.subject.layers.LayersTraceSubject 26 import android.tools.traces.component.IComponentMatcher 27 28 class SplitAppLayerBoundsBecomesVisible( 29 private val component: ComponentTemplate, 30 val isPrimaryApp: Boolean 31 ) : AssertionTemplateWithComponent(component) { doEvaluatenull32 override fun doEvaluate(scenarioInstance: ScenarioInstance, flicker: FlickerTest) { 33 val splitScreenDivider = SPLIT_SCREEN_DIVIDER.build(scenarioInstance) 34 val app = component.build(scenarioInstance) 35 36 val landscapePosLeft: Boolean 37 val portraitPosTop: Boolean 38 if (isPrimaryApp) { 39 landscapePosLeft = false 40 portraitPosTop = false 41 } else { 42 // secondaryApp 43 landscapePosLeft = true 44 portraitPosTop = true 45 } 46 47 flicker.assertLayers { 48 notContains(splitScreenDivider.or(app), isOptional = true) 49 .then() 50 .isInvisible(splitScreenDivider.or(app)) 51 .then() 52 .splitAppLayerBoundsSnapToDivider( 53 app, 54 splitScreenDivider, 55 landscapePosLeft, 56 portraitPosTop 57 ) 58 } 59 } 60 61 companion object { splitAppLayerBoundsSnapToDividernull62 fun LayersTraceSubject.splitAppLayerBoundsSnapToDivider( 63 component: IComponentMatcher, 64 splitScreenDivider: IComponentMatcher, 65 landscapePosLeft: Boolean, 66 portraitPosTop: Boolean 67 ): LayersTraceSubject { 68 return invoke("splitAppLayerBoundsSnapToDivider") { 69 it.splitAppLayerBoundsSnapToDivider( 70 component, 71 splitScreenDivider, 72 landscapePosLeft, 73 portraitPosTop 74 ) 75 } 76 } 77 LayerTraceEntrySubjectnull78 private fun LayerTraceEntrySubject.splitAppLayerBoundsSnapToDivider( 79 component: IComponentMatcher, 80 splitScreenDivider: IComponentMatcher, 81 landscapePosLeft: Boolean, 82 portraitPosTop: Boolean 83 ): LayerTraceEntrySubject { 84 val activeDisplay = 85 this.entry.displays.firstOrNull { it.isOn && !it.isVirtual } 86 ?: error("No non-virtual and on display found") 87 88 return invoke { 89 val dividerRegion = 90 layer(splitScreenDivider)?.visibleRegion?.region 91 ?: error("$splitScreenDivider component not found") 92 visibleRegion(component) 93 .coversAtMost( 94 if ( 95 activeDisplay.layerStackSpace.width() > 96 activeDisplay.layerStackSpace.height() 97 ) { 98 if (landscapePosLeft) { 99 Region( 100 0, 101 0, 102 (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2, 103 activeDisplay.layerStackSpace.bottom 104 ) 105 } else { 106 Region( 107 (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2, 108 0, 109 activeDisplay.layerStackSpace.right, 110 activeDisplay.layerStackSpace.bottom 111 ) 112 } 113 } else { 114 if (portraitPosTop) { 115 Region( 116 0, 117 0, 118 activeDisplay.layerStackSpace.right, 119 (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2 120 ) 121 } else { 122 Region( 123 0, 124 (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2, 125 activeDisplay.layerStackSpace.right, 126 activeDisplay.layerStackSpace.bottom 127 ) 128 } 129 } 130 ) 131 } 132 } 133 } 134 } 135