1 /* 2 * Copyright (C) 2014 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.bluetooth; 18 19 import android.annotation.NonNull; 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.content.Attributable; 22 import android.content.AttributionSource; 23 import android.os.Build; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.os.SystemClock; 27 28 import java.util.UUID; 29 30 /** 31 * This class represents a single call, its state and properties. 32 * It implements {@link Parcelable} for inter-process message passing. 33 * 34 * @hide 35 */ 36 public final class BluetoothHeadsetClientCall implements Parcelable, Attributable { 37 38 /* Call state */ 39 /** 40 * Call is active. 41 */ 42 public static final int CALL_STATE_ACTIVE = 0; 43 /** 44 * Call is in held state. 45 */ 46 public static final int CALL_STATE_HELD = 1; 47 /** 48 * Outgoing call that is being dialed right now. 49 */ 50 public static final int CALL_STATE_DIALING = 2; 51 /** 52 * Outgoing call that remote party has already been alerted about. 53 */ 54 public static final int CALL_STATE_ALERTING = 3; 55 /** 56 * Incoming call that can be accepted or rejected. 57 */ 58 public static final int CALL_STATE_INCOMING = 4; 59 /** 60 * Waiting call state when there is already an active call. 61 */ 62 public static final int CALL_STATE_WAITING = 5; 63 /** 64 * Call that has been held by response and hold 65 * (see Bluetooth specification for further references). 66 */ 67 public static final int CALL_STATE_HELD_BY_RESPONSE_AND_HOLD = 6; 68 /** 69 * Call that has been already terminated and should not be referenced as a valid call. 70 */ 71 public static final int CALL_STATE_TERMINATED = 7; 72 73 private final BluetoothDevice mDevice; 74 private final int mId; 75 private int mState; 76 private String mNumber; 77 private boolean mMultiParty; 78 private final boolean mOutgoing; 79 private final UUID mUUID; 80 private final long mCreationElapsedMilli; 81 private final boolean mInBandRing; 82 83 /** 84 * Creates BluetoothHeadsetClientCall instance. 85 */ BluetoothHeadsetClientCall(BluetoothDevice device, int id, int state, String number, boolean multiParty, boolean outgoing, boolean inBandRing)86 public BluetoothHeadsetClientCall(BluetoothDevice device, int id, int state, String number, 87 boolean multiParty, boolean outgoing, boolean inBandRing) { 88 this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing, inBandRing); 89 } 90 BluetoothHeadsetClientCall(BluetoothDevice device, int id, UUID uuid, int state, String number, boolean multiParty, boolean outgoing, boolean inBandRing)91 public BluetoothHeadsetClientCall(BluetoothDevice device, int id, UUID uuid, int state, 92 String number, boolean multiParty, boolean outgoing, boolean inBandRing) { 93 mDevice = device; 94 mId = id; 95 mUUID = uuid; 96 mState = state; 97 mNumber = number != null ? number : ""; 98 mMultiParty = multiParty; 99 mOutgoing = outgoing; 100 mInBandRing = inBandRing; 101 mCreationElapsedMilli = SystemClock.elapsedRealtime(); 102 } 103 104 /** {@hide} */ setAttributionSource(@onNull AttributionSource attributionSource)105 public void setAttributionSource(@NonNull AttributionSource attributionSource) { 106 Attributable.setAttributionSource(mDevice, attributionSource); 107 } 108 109 /** 110 * Sets call's state. 111 * 112 * <p>Note: This is an internal function and shouldn't be exposed</p> 113 * 114 * @param state new call state. 115 */ setState(int state)116 public void setState(int state) { 117 mState = state; 118 } 119 120 /** 121 * Sets call's number. 122 * 123 * <p>Note: This is an internal function and shouldn't be exposed</p> 124 * 125 * @param number String representing phone number. 126 */ setNumber(String number)127 public void setNumber(String number) { 128 mNumber = number; 129 } 130 131 /** 132 * Sets this call as multi party call. 133 * 134 * <p>Note: This is an internal function and shouldn't be exposed</p> 135 * 136 * @param multiParty if <code>true</code> sets this call as a part of multi party conference. 137 */ setMultiParty(boolean multiParty)138 public void setMultiParty(boolean multiParty) { 139 mMultiParty = multiParty; 140 } 141 142 /** 143 * Gets call's device. 144 * 145 * @return call device. 146 */ getDevice()147 public BluetoothDevice getDevice() { 148 return mDevice; 149 } 150 151 /** 152 * Gets call's Id. 153 * 154 * @return call id. 155 */ 156 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getId()157 public int getId() { 158 return mId; 159 } 160 161 /** 162 * Gets call's UUID. 163 * 164 * @return call uuid 165 * @hide 166 */ getUUID()167 public UUID getUUID() { 168 return mUUID; 169 } 170 171 /** 172 * Gets call's current state. 173 * 174 * @return state of this particular phone call. 175 */ 176 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getState()177 public int getState() { 178 return mState; 179 } 180 181 /** 182 * Gets call's number. 183 * 184 * @return string representing phone number. 185 */ 186 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getNumber()187 public String getNumber() { 188 return mNumber; 189 } 190 191 /** 192 * Gets call's creation time in millis since epoch. 193 * 194 * @return long representing the creation time. 195 */ getCreationElapsedMilli()196 public long getCreationElapsedMilli() { 197 return mCreationElapsedMilli; 198 } 199 200 /** 201 * Checks if call is an active call in a conference mode (aka multi party). 202 * 203 * @return <code>true</code> if call is a multi party call, <code>false</code> otherwise. 204 */ 205 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isMultiParty()206 public boolean isMultiParty() { 207 return mMultiParty; 208 } 209 210 /** 211 * Checks if this call is an outgoing call. 212 * 213 * @return <code>true</code> if its outgoing call, <code>false</code> otherwise. 214 */ 215 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isOutgoing()216 public boolean isOutgoing() { 217 return mOutgoing; 218 } 219 220 /** 221 * Checks if the ringtone will be generated by the connected phone 222 * 223 * @return <code>true</code> if in band ring is enabled, <code>false</code> otherwise. 224 */ isInBandRing()225 public boolean isInBandRing() { 226 return mInBandRing; 227 } 228 229 230 @Override toString()231 public String toString() { 232 return toString(false); 233 } 234 235 /** 236 * Generate a log string for this call 237 * @param loggable whether device address should be logged 238 * @return log string 239 */ toString(boolean loggable)240 public String toString(boolean loggable) { 241 StringBuilder builder = new StringBuilder("BluetoothHeadsetClientCall{mDevice: "); 242 builder.append(loggable ? mDevice : mDevice.hashCode()); 243 builder.append(", mId: "); 244 builder.append(mId); 245 builder.append(", mUUID: "); 246 builder.append(mUUID); 247 builder.append(", mState: "); 248 switch (mState) { 249 case CALL_STATE_ACTIVE: 250 builder.append("ACTIVE"); 251 break; 252 case CALL_STATE_HELD: 253 builder.append("HELD"); 254 break; 255 case CALL_STATE_DIALING: 256 builder.append("DIALING"); 257 break; 258 case CALL_STATE_ALERTING: 259 builder.append("ALERTING"); 260 break; 261 case CALL_STATE_INCOMING: 262 builder.append("INCOMING"); 263 break; 264 case CALL_STATE_WAITING: 265 builder.append("WAITING"); 266 break; 267 case CALL_STATE_HELD_BY_RESPONSE_AND_HOLD: 268 builder.append("HELD_BY_RESPONSE_AND_HOLD"); 269 break; 270 case CALL_STATE_TERMINATED: 271 builder.append("TERMINATED"); 272 break; 273 default: 274 builder.append(mState); 275 break; 276 } 277 builder.append(", mNumber: "); 278 builder.append(loggable ? mNumber : mNumber.hashCode()); 279 builder.append(", mMultiParty: "); 280 builder.append(mMultiParty); 281 builder.append(", mOutgoing: "); 282 builder.append(mOutgoing); 283 builder.append(", mInBandRing: "); 284 builder.append(mInBandRing); 285 builder.append("}"); 286 return builder.toString(); 287 } 288 289 /** 290 * {@link Parcelable.Creator} interface implementation. 291 */ 292 public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHeadsetClientCall> CREATOR = 293 new Parcelable.Creator<BluetoothHeadsetClientCall>() { 294 @Override 295 public BluetoothHeadsetClientCall createFromParcel(Parcel in) { 296 return new BluetoothHeadsetClientCall((BluetoothDevice) in.readParcelable(null), 297 in.readInt(), UUID.fromString(in.readString()), in.readInt(), 298 in.readString(), in.readInt() == 1, in.readInt() == 1, 299 in.readInt() == 1); 300 } 301 302 @Override 303 public BluetoothHeadsetClientCall[] newArray(int size) { 304 return new BluetoothHeadsetClientCall[size]; 305 } 306 }; 307 308 @Override writeToParcel(Parcel out, int flags)309 public void writeToParcel(Parcel out, int flags) { 310 out.writeParcelable(mDevice, 0); 311 out.writeInt(mId); 312 out.writeString(mUUID.toString()); 313 out.writeInt(mState); 314 out.writeString(mNumber); 315 out.writeInt(mMultiParty ? 1 : 0); 316 out.writeInt(mOutgoing ? 1 : 0); 317 out.writeInt(mInBandRing ? 1 : 0); 318 } 319 320 @Override describeContents()321 public int describeContents() { 322 return 0; 323 } 324 } 325