1 /* 2 * Copyright (C) 2022 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.telecom; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.os.Parcel; 22 import android.os.ParcelUuid; 23 import android.os.Parcelable; 24 import android.text.TextUtils; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.Objects; 29 import java.util.UUID; 30 31 /** 32 * Encapsulates the endpoint where call media can flow 33 */ 34 public final class CallEndpoint implements Parcelable { 35 /** @hide */ 36 public static final int ENDPOINT_OPERATION_SUCCESS = 0; 37 /** @hide */ 38 public static final int ENDPOINT_OPERATION_FAILED = 1; 39 40 /** @hide */ 41 @Retention(RetentionPolicy.SOURCE) 42 @IntDef({TYPE_UNKNOWN, TYPE_EARPIECE, TYPE_BLUETOOTH, TYPE_WIRED_HEADSET, TYPE_SPEAKER, 43 TYPE_STREAMING}) 44 public @interface EndpointType {} 45 46 /** Indicates that the type of endpoint through which call media flows is unknown type. */ 47 public static final int TYPE_UNKNOWN = -1; 48 49 /** Indicates that the type of endpoint through which call media flows is an earpiece. */ 50 public static final int TYPE_EARPIECE = 1; 51 52 /** Indicates that the type of endpoint through which call media flows is a Bluetooth. */ 53 public static final int TYPE_BLUETOOTH = 2; 54 55 /** Indicates that the type of endpoint through which call media flows is a wired headset. */ 56 public static final int TYPE_WIRED_HEADSET = 3; 57 58 /** Indicates that the type of endpoint through which call media flows is a speakerphone. */ 59 public static final int TYPE_SPEAKER = 4; 60 61 /** Indicates that the type of endpoint through which call media flows is an external. */ 62 public static final int TYPE_STREAMING = 5; 63 64 private final CharSequence mName; 65 private final int mType; 66 private final ParcelUuid mIdentifier; 67 68 /** 69 * Constructor for a {@link CallEndpoint} object. 70 * 71 * @param name Human-readable name associated with the endpoint 72 * @param type The type of endpoint through which call media being routed 73 * Allowed values: 74 * {@link #TYPE_EARPIECE} 75 * {@link #TYPE_BLUETOOTH} 76 * {@link #TYPE_WIRED_HEADSET} 77 * {@link #TYPE_SPEAKER} 78 * {@link #TYPE_STREAMING} 79 * {@link #TYPE_UNKNOWN} 80 * @param id A unique identifier for this endpoint on the device 81 */ CallEndpoint(@onNull CharSequence name, @EndpointType int type, @NonNull ParcelUuid id)82 public CallEndpoint(@NonNull CharSequence name, @EndpointType int type, 83 @NonNull ParcelUuid id) { 84 this.mName = name; 85 this.mType = type; 86 this.mIdentifier = id; 87 } 88 89 /** @hide */ CallEndpoint(@onNull CharSequence name, @EndpointType int type)90 public CallEndpoint(@NonNull CharSequence name, @EndpointType int type) { 91 this(name, type, new ParcelUuid(UUID.randomUUID())); 92 } 93 94 /** @hide */ CallEndpoint(CallEndpoint endpoint)95 public CallEndpoint(CallEndpoint endpoint) { 96 mName = endpoint.getEndpointName(); 97 mType = endpoint.getEndpointType(); 98 mIdentifier = endpoint.getIdentifier(); 99 } 100 101 /** 102 * {@inheritDoc} 103 */ 104 @Override equals(Object obj)105 public boolean equals(Object obj) { 106 if (obj == null) { 107 return false; 108 } 109 if (!(obj instanceof CallEndpoint)) { 110 return false; 111 } 112 CallEndpoint endpoint = (CallEndpoint) obj; 113 return getEndpointName().toString().contentEquals(endpoint.getEndpointName()) 114 && getEndpointType() == endpoint.getEndpointType() 115 && getIdentifier().equals(endpoint.getIdentifier()); 116 } 117 118 /** 119 * {@inheritDoc} 120 */ 121 @Override hashCode()122 public int hashCode() { 123 return Objects.hash(mName, mType, mIdentifier); 124 } 125 126 /** 127 * {@inheritDoc} 128 */ 129 @Override toString()130 public String toString() { 131 return TextUtils.formatSimple("[CallEndpoint Name: %s, Type: %s, Identifier: %s]", 132 mName.toString(), endpointTypeToString(mType), mIdentifier.toString()); 133 } 134 135 /** 136 * @return Human-readable name associated with the endpoint 137 */ 138 @NonNull getEndpointName()139 public CharSequence getEndpointName() { 140 return mName; 141 } 142 143 /** 144 * @return The type of endpoint through which call media being routed 145 */ 146 @EndpointType getEndpointType()147 public int getEndpointType() { 148 return mType; 149 } 150 151 /** 152 * @return A unique identifier for this endpoint on the device 153 */ 154 @NonNull getIdentifier()155 public ParcelUuid getIdentifier() { 156 return mIdentifier; 157 } 158 159 /** 160 * Converts the provided endpoint type into a human-readable string representation. 161 * 162 * @param endpointType to convert into a string. 163 * @return String representation of the provided endpoint type. 164 * @hide 165 */ 166 @NonNull endpointTypeToString(int endpointType)167 public static String endpointTypeToString(int endpointType) { 168 switch (endpointType) { 169 case TYPE_EARPIECE: 170 return "EARPIECE"; 171 case TYPE_BLUETOOTH: 172 return "BLUETOOTH"; 173 case TYPE_WIRED_HEADSET: 174 return "WIRED_HEADSET"; 175 case TYPE_SPEAKER: 176 return "SPEAKER"; 177 case TYPE_STREAMING: 178 return "EXTERNAL"; 179 default: 180 return "UNKNOWN (" + endpointType + ")"; 181 } 182 } 183 184 /** 185 * Responsible for creating CallEndpoint objects for deserialized Parcels. 186 */ 187 public static final @android.annotation.NonNull Parcelable.Creator<CallEndpoint> CREATOR = 188 new Parcelable.Creator<CallEndpoint>() { 189 190 @Override 191 public CallEndpoint createFromParcel(Parcel source) { 192 CharSequence name = source.readCharSequence(); 193 int type = source.readInt(); 194 ParcelUuid id = ParcelUuid.CREATOR.createFromParcel(source); 195 196 return new CallEndpoint(name, type, id); 197 } 198 199 @Override 200 public CallEndpoint[] newArray(int size) { 201 return new CallEndpoint[size]; 202 } 203 }; 204 205 /** 206 * {@inheritDoc} 207 */ 208 @Override describeContents()209 public int describeContents() { 210 return 0; 211 } 212 213 /** 214 * {@inheritDoc} 215 */ 216 @Override writeToParcel(@onNull Parcel destination, int flags)217 public void writeToParcel(@NonNull Parcel destination, int flags) { 218 destination.writeCharSequence(mName); 219 destination.writeInt(mType); 220 mIdentifier.writeToParcel(destination, flags); 221 } 222 } 223