1 /* 2 * Copyright 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 androidx.window.area 18 19 import android.os.Binder 20 import androidx.window.area.WindowAreaCapability.Operation.Companion.OPERATION_PRESENT_ON_AREA 21 import androidx.window.area.WindowAreaCapability.Operation.Companion.OPERATION_TRANSFER_ACTIVITY_TO_AREA 22 import androidx.window.area.WindowAreaCapability.Status.Companion.WINDOW_AREA_STATUS_ACTIVE 23 import androidx.window.area.WindowAreaCapability.Status.Companion.WINDOW_AREA_STATUS_UNSUPPORTED 24 import androidx.window.core.ExperimentalWindowApi 25 import androidx.window.core.ExtensionsUtil 26 import androidx.window.extensions.area.WindowAreaComponent 27 import androidx.window.layout.WindowMetrics 28 29 /** 30 * The current state of a window area. The [WindowAreaInfo] can represent a part of or an entire 31 * display in the system. These values can be used to modify the UI to show/hide controls and 32 * determine when features can be enabled. 33 */ 34 @ExperimentalWindowApi 35 class WindowAreaInfo 36 internal constructor( 37 38 /** 39 * The [WindowMetrics] that represent the size of the area. Used to determine if the behavior 40 * desired fits the size of the window area available. 41 */ 42 var metrics: WindowMetrics, 43 44 /** The [Type] of this window area */ 45 val type: Type, 46 47 /** [Binder] token to identify the specific WindowArea */ 48 val token: Binder, 49 private val windowAreaComponent: WindowAreaComponent 50 ) { 51 52 internal val capabilityMap = HashMap<WindowAreaCapability.Operation, WindowAreaCapability>() 53 54 /** 55 * Returns the [WindowAreaCapability] corresponding to the [operation] provided. If this 56 * [WindowAreaCapability] does not exist for this [WindowAreaInfo], a [WindowAreaCapability] 57 * with a [WINDOW_AREA_STATUS_UNSUPPORTED] value is returned. 58 */ getCapabilitynull59 fun getCapability(operation: WindowAreaCapability.Operation): WindowAreaCapability { 60 return capabilityMap[operation] 61 ?: WindowAreaCapability(operation, WINDOW_AREA_STATUS_UNSUPPORTED) 62 } 63 64 /** 65 * Returns the current active [WindowAreaSession] is one is currently active for the provided 66 * [operation] 67 * 68 * @throws IllegalStateException if there is no active session for the provided [operation] 69 */ getActiveSessionnull70 fun getActiveSession(operation: WindowAreaCapability.Operation): WindowAreaSession? { 71 if (getCapability(operation).status != WINDOW_AREA_STATUS_ACTIVE) { 72 throw IllegalStateException("No session is currently active") 73 } 74 75 if (type == Type.TYPE_REAR_FACING) { 76 // TODO(b/273807246) We should cache instead of always creating a new session 77 return createRearFacingSession(operation) 78 } 79 return null 80 } 81 createRearFacingSessionnull82 private fun createRearFacingSession( 83 operation: WindowAreaCapability.Operation 84 ): WindowAreaSession { 85 return when (operation) { 86 OPERATION_TRANSFER_ACTIVITY_TO_AREA -> RearDisplaySessionImpl(windowAreaComponent) 87 OPERATION_PRESENT_ON_AREA -> 88 RearDisplayPresentationSessionPresenterImpl( 89 windowAreaComponent, 90 windowAreaComponent.rearDisplayPresentation!!, 91 ExtensionsUtil.safeVendorApiLevel 92 ) 93 else -> { 94 throw IllegalArgumentException("Invalid operation provided") 95 } 96 } 97 } 98 99 /** Represents a type of [WindowAreaInfo] */ 100 @ExperimentalWindowApi 101 class Type private constructor(private val description: String) { toStringnull102 override fun toString(): String { 103 return description 104 } 105 106 companion object { 107 /** 108 * Type of window area that is facing the same direction as the rear camera(s) on the 109 * device. 110 */ 111 @JvmField val TYPE_REAR_FACING = Type("REAR FACING") 112 } 113 } 114 equalsnull115 override fun equals(other: Any?): Boolean { 116 return other is WindowAreaInfo && 117 metrics == other.metrics && 118 type == other.type && 119 capabilityMap.entries == other.capabilityMap.entries 120 } 121 hashCodenull122 override fun hashCode(): Int { 123 var result = metrics.hashCode() 124 result = 31 * result + type.hashCode() 125 result = 31 * result + capabilityMap.entries.hashCode() 126 return result 127 } 128 toStringnull129 override fun toString(): String { 130 return "WindowAreaInfo{ Metrics: $metrics, type: $type, " + 131 "Capabilities: ${capabilityMap.entries} }" 132 } 133 } 134