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