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