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.common.flicker.assertors.assertions 18 19 import android.tools.common.datatypes.Region 20 import android.tools.common.flicker.ScenarioInstance 21 import android.tools.common.flicker.assertions.FlickerTest 22 import android.tools.common.flicker.assertors.ComponentTemplate 23 import android.tools.common.flicker.config.splitscreen.Components.SPLIT_SCREEN_DIVIDER 24 import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject 25 import android.tools.common.flicker.subject.layers.LayersTraceSubject 26 import android.tools.common.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 (activeDisplay.bounds.width > activeDisplay.bounds.height) { 95 if (landscapePosLeft) { 96 Region.from( 97 0, 98 0, 99 (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2, 100 activeDisplay.bounds.bottom 101 ) 102 } else { 103 Region.from( 104 (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2, 105 0, 106 activeDisplay.bounds.right, 107 activeDisplay.bounds.bottom 108 ) 109 } 110 } else { 111 if (portraitPosTop) { 112 Region.from( 113 0, 114 0, 115 activeDisplay.bounds.right, 116 (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2 117 ) 118 } else { 119 Region.from( 120 0, 121 (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2, 122 activeDisplay.bounds.right, 123 activeDisplay.bounds.bottom 124 ) 125 } 126 } 127 ) 128 } 129 } 130 } 131 } 132