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.core.telecom 18 19 import android.os.Build.VERSION_CODES 20 import android.os.ParcelUuid 21 import androidx.annotation.IntDef 22 import androidx.annotation.RequiresApi 23 import androidx.annotation.RestrictTo 24 import androidx.core.telecom.internal.CallEndpointUuidTracker 25 import androidx.core.telecom.internal.utils.EndpointUtils 26 import java.util.Objects 27 28 /** 29 * Constructor for a [CallEndpointCompat] object. 30 * 31 * @param name Human-readable name associated with the endpoint 32 * @param type The type of endpoint through which call media being routed Allowed values: 33 * [TYPE_EARPIECE] , [TYPE_BLUETOOTH] , [TYPE_WIRED_HEADSET] , [TYPE_SPEAKER] , [TYPE_STREAMING] , 34 * [TYPE_UNKNOWN] 35 * @param identifier A unique identifier for this endpoint on the device 36 */ 37 @RequiresApi(VERSION_CODES.O) 38 public class CallEndpointCompat( 39 public val name: CharSequence, 40 public val type: Int, 41 public val identifier: ParcelUuid 42 ) : Comparable<CallEndpointCompat> { 43 internal var mMackAddress: String = UNKNOWN_MAC_ADDRESS 44 toStringnull45 override fun toString(): String { 46 return "CallEndpoint(" + 47 "name=[$name]," + 48 "type=[${EndpointUtils.endpointTypeToString(type)}]," + 49 "identifier=[$identifier])" 50 } 51 52 /** 53 * Compares this [CallEndpointCompat] to the other [CallEndpointCompat] for order. Returns a 54 * positive number if this type rank is greater than the other value. Returns a negative number 55 * if this type rank is less than the other value. Sort the CallEndpoint by type. Ranking them 56 * by: 57 * 1. TYPE_WIRED_HEADSET 58 * 2. TYPE_BLUETOOTH 59 * 3. TYPE_SPEAKER 60 * 4. TYPE_EARPIECE 61 * 5. TYPE_STREAMING 62 * 6. TYPE_UNKNOWN If two endpoints have the same type, the name is compared to determine the 63 * value. 64 */ compareTonull65 override fun compareTo(other: CallEndpointCompat): Int { 66 // sort by type 67 val res = this.getTypeRank().compareTo(other.getTypeRank()) 68 if (res != 0) { 69 return res 70 } 71 // break ties using alphabetic order 72 return this.name.toString().compareTo(other.name.toString()) 73 } 74 equalsnull75 override fun equals(other: Any?): Boolean { 76 return other is CallEndpointCompat && 77 name == other.name && 78 type == other.type && 79 identifier == other.identifier 80 } 81 hashCodenull82 override fun hashCode(): Int { 83 return Objects.hash(name, type, identifier) 84 } 85 86 public companion object { 87 @RestrictTo(RestrictTo.Scope.LIBRARY) 88 @Retention(AnnotationRetention.SOURCE) 89 @IntDef( 90 TYPE_UNKNOWN, 91 TYPE_EARPIECE, 92 TYPE_BLUETOOTH, 93 TYPE_WIRED_HEADSET, 94 TYPE_SPEAKER, 95 TYPE_STREAMING 96 ) 97 @Target(AnnotationTarget.TYPE, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER) 98 public annotation class EndpointType 99 100 /** Indicates that the type of endpoint through which call media flows is unknown type. */ 101 public const val TYPE_UNKNOWN: Int = -1 102 103 /** Indicates that the type of endpoint through which call media flows is an earpiece. */ 104 public const val TYPE_EARPIECE: Int = 1 105 106 /** Indicates that the type of endpoint through which call media flows is a Bluetooth. */ 107 public const val TYPE_BLUETOOTH: Int = 2 108 109 /** 110 * Indicates that the type of endpoint through which call media flows is a wired headset. 111 */ 112 public const val TYPE_WIRED_HEADSET: Int = 3 113 114 /** Indicates that the type of endpoint through which call media flows is a speakerphone. */ 115 public const val TYPE_SPEAKER: Int = 4 116 117 /** Indicates that the type of endpoint through which call media flows is an external. */ 118 public const val TYPE_STREAMING: Int = 5 119 120 internal const val UNKNOWN_MAC_ADDRESS: String = "-1" 121 } 122 123 internal constructor( 124 name: String, 125 @EndpointType type: Int, 126 sessionId: Int, 127 mackAddress: String = "-1" 128 ) : this(name, type, CallEndpointUuidTracker.getUuid(sessionId, type, name)) { 129 mMackAddress = mackAddress 130 } 131 132 /** Internal helper to determine if this [CallEndpointCompat] is EndpointType#TYPE_BLUETOOTH */ isBluetoothTypenull133 internal fun isBluetoothType(): Boolean { 134 return type == TYPE_BLUETOOTH 135 } 136 getTypeRanknull137 private fun getTypeRank(): Int { 138 return when (this.type) { 139 TYPE_WIRED_HEADSET -> return 0 140 TYPE_BLUETOOTH -> return 1 141 TYPE_SPEAKER -> return 2 142 TYPE_EARPIECE -> return 3 143 TYPE_STREAMING -> return 4 144 else -> 5 145 } 146 } 147 } 148