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.telecom; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 import android.media.ToneGenerator; 22 import android.text.TextUtils; 23 24 import java.util.Objects; 25 26 /** 27 * Describes the cause of a disconnected call. This always includes a code describing the generic 28 * cause of the disconnect. Optionally, it may include a label and/or description to display to the 29 * user. It is the responsibility of the {@link ConnectionService} to provide localized versions of 30 * the label and description. It also may contain a reason for the disconnect, which is intended for 31 * logging and not for display to the user. 32 */ 33 public final class DisconnectCause implements Parcelable { 34 35 /** Disconnected because of an unknown or unspecified reason. */ 36 public static final int UNKNOWN = TelecomProtoEnums.UNKNOWN; // = 0 37 /** Disconnected because there was an error, such as a problem with the network. */ 38 public static final int ERROR = TelecomProtoEnums.ERROR; // = 1 39 /** Disconnected because of a local user-initiated action, such as hanging up. */ 40 public static final int LOCAL = TelecomProtoEnums.LOCAL; // = 2 41 /** 42 * Disconnected because of a remote user-initiated action, such as the other party hanging up 43 * up. 44 */ 45 public static final int REMOTE = TelecomProtoEnums.REMOTE; // = 3 46 /** Disconnected because it has been canceled. */ 47 public static final int CANCELED = TelecomProtoEnums.CANCELED; // = 4 48 /** Disconnected because there was no response to an incoming call. */ 49 public static final int MISSED = TelecomProtoEnums.MISSED; // = 5 50 /** Disconnected because the user rejected an incoming call. */ 51 public static final int REJECTED = TelecomProtoEnums.REJECTED; // = 6 52 /** Disconnected because the other party was busy. */ 53 public static final int BUSY = TelecomProtoEnums.BUSY; // = 7 54 /** 55 * Disconnected because of a restriction on placing the call, such as dialing in airplane 56 * mode. 57 */ 58 public static final int RESTRICTED = TelecomProtoEnums.RESTRICTED; // = 8 59 /** Disconnected for reason not described by other disconnect codes. */ 60 public static final int OTHER = TelecomProtoEnums.OTHER; // = 9 61 /** 62 * Disconnected because the connection manager did not support the call. The call will be tried 63 * again without a connection manager. See {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. 64 */ 65 public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 66 TelecomProtoEnums.CONNECTION_MANAGER_NOT_SUPPORTED; // = 10 67 68 /** 69 * Disconnected because the user did not locally answer the incoming call, but it was answered 70 * on another device where the call was ringing. 71 */ 72 public static final int ANSWERED_ELSEWHERE = TelecomProtoEnums.ANSWERED_ELSEWHERE; // = 11 73 74 /** 75 * Disconnected because the call was pulled from the current device to another device. 76 */ 77 public static final int CALL_PULLED = TelecomProtoEnums.CALL_PULLED; // = 12 78 79 /** 80 * Reason code (returned via {@link #getReason()}) which indicates that a call could not be 81 * completed because the cellular radio is off or out of service, the device is connected to 82 * a wifi network, but the user has not enabled wifi calling. 83 * @hide 84 */ 85 public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF"; 86 87 /** 88 * Reason code (returned via {@link #getReason()}), which indicates that the video telephony 89 * call was disconnected because IMS access is blocked. 90 * @hide 91 */ 92 public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED"; 93 94 private int mDisconnectCode; 95 private CharSequence mDisconnectLabel; 96 private CharSequence mDisconnectDescription; 97 private String mDisconnectReason; 98 private int mToneToPlay; 99 100 /** 101 * Creates a new DisconnectCause. 102 * 103 * @param code The code for the disconnect cause. 104 */ 105 public DisconnectCause(int code) { 106 this(code, null, null, null, ToneGenerator.TONE_UNKNOWN); 107 } 108 109 /** 110 * Creates a new DisconnectCause. 111 * 112 * @param code The code for the disconnect cause. 113 * @param reason The reason for the disconnect. 114 */ 115 public DisconnectCause(int code, String reason) { 116 this(code, null, null, reason, ToneGenerator.TONE_UNKNOWN); 117 } 118 119 /** 120 * Creates a new DisconnectCause. 121 * 122 * @param code The code for the disconnect cause. 123 * @param label The localized label to show to the user to explain the disconnect. 124 * @param description The localized description to show to the user to explain the disconnect. 125 * @param reason The reason for the disconnect. 126 */ 127 public DisconnectCause(int code, CharSequence label, CharSequence description, String reason) { 128 this(code, label, description, reason, ToneGenerator.TONE_UNKNOWN); 129 } 130 131 /** 132 * Creates a new DisconnectCause. 133 * 134 * @param code The code for the disconnect cause. 135 * @param label The localized label to show to the user to explain the disconnect. 136 * @param description The localized description to show to the user to explain the disconnect. 137 * @param reason The reason for the disconnect. 138 * @param toneToPlay The tone to play on disconnect, as defined in {@link ToneGenerator}. 139 */ 140 public DisconnectCause(int code, CharSequence label, CharSequence description, String reason, 141 int toneToPlay) { 142 mDisconnectCode = code; 143 mDisconnectLabel = label; 144 mDisconnectDescription = description; 145 mDisconnectReason = reason; 146 mToneToPlay = toneToPlay; 147 } 148 149 /** 150 * Returns the code for the reason for this disconnect. 151 * 152 * @return The disconnect code. 153 */ 154 public int getCode() { 155 return mDisconnectCode; 156 } 157 158 /** 159 * Returns a short label which explains the reason for the disconnect cause and is for display 160 * in the user interface. If not null, it is expected that the In-Call UI should display this 161 * text where it would normally display the call state ("Dialing", "Disconnected") and is 162 * therefore expected to be relatively small. The {@link ConnectionService } is responsible for 163 * providing and localizing this label. If there is no string provided, returns null. 164 * 165 * @return The disconnect label. 166 */ 167 public CharSequence getLabel() { 168 return mDisconnectLabel; 169 } 170 171 /** 172 * Returns a description which explains the reason for the disconnect cause and is for display 173 * in the user interface. This optional text is generally a longer and more descriptive version 174 * of {@link #getLabel}, however it can exist even if {@link #getLabel} is empty. The In-Call UI 175 * should display this relatively prominently; the traditional implementation displays this as 176 * an alert dialog. The {@link ConnectionService} is responsible for providing and localizing 177 * this message. If there is no string provided, returns null. 178 * 179 * @return The disconnect description. 180 */ 181 public CharSequence getDescription() { 182 return mDisconnectDescription; 183 } 184 185 /** 186 * Returns an explanation of the reason for the disconnect. This is not intended for display to 187 * the user and is used mainly for logging. 188 * 189 * @return The disconnect reason. 190 */ 191 public String getReason() { 192 return mDisconnectReason; 193 } 194 195 /** 196 * Returns the tone to play when disconnected. 197 * 198 * @return the tone as defined in {@link ToneGenerator} to play when disconnected. 199 */ 200 public int getTone() { 201 return mToneToPlay; 202 } 203 204 public static final Creator<DisconnectCause> CREATOR = new Creator<DisconnectCause>() { 205 @Override 206 public DisconnectCause createFromParcel(Parcel source) { 207 int code = source.readInt(); 208 CharSequence label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 209 CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 210 String reason = source.readString(); 211 int tone = source.readInt(); 212 return new DisconnectCause(code, label, description, reason, tone); 213 } 214 215 @Override 216 public DisconnectCause[] newArray(int size) { 217 return new DisconnectCause[size]; 218 } 219 }; 220 221 @Override 222 public void writeToParcel(Parcel destination, int flags) { 223 destination.writeInt(mDisconnectCode); 224 TextUtils.writeToParcel(mDisconnectLabel, destination, flags); 225 TextUtils.writeToParcel(mDisconnectDescription, destination, flags); 226 destination.writeString(mDisconnectReason); 227 destination.writeInt(mToneToPlay); 228 } 229 230 @Override 231 public int describeContents() { 232 return 0; 233 } 234 235 @Override 236 public int hashCode() { 237 return Objects.hashCode(mDisconnectCode) 238 + Objects.hashCode(mDisconnectLabel) 239 + Objects.hashCode(mDisconnectDescription) 240 + Objects.hashCode(mDisconnectReason) 241 + Objects.hashCode(mToneToPlay); 242 } 243 244 @Override 245 public boolean equals(Object o) { 246 if (o instanceof DisconnectCause) { 247 DisconnectCause d = (DisconnectCause) o; 248 return Objects.equals(mDisconnectCode, d.getCode()) 249 && Objects.equals(mDisconnectLabel, d.getLabel()) 250 && Objects.equals(mDisconnectDescription, d.getDescription()) 251 && Objects.equals(mDisconnectReason, d.getReason()) 252 && Objects.equals(mToneToPlay, d.getTone()); 253 } 254 return false; 255 } 256 257 @Override 258 public String toString() { 259 String code = ""; 260 switch (mDisconnectCode) { 261 case UNKNOWN: 262 code = "UNKNOWN"; 263 break; 264 case ERROR: 265 code = "ERROR"; 266 break; 267 case LOCAL: 268 code = "LOCAL"; 269 break; 270 case REMOTE: 271 code = "REMOTE"; 272 break; 273 case CANCELED: 274 code = "CANCELED"; 275 break; 276 case MISSED: 277 code = "MISSED"; 278 break; 279 case REJECTED: 280 code = "REJECTED"; 281 break; 282 case BUSY: 283 code = "BUSY"; 284 break; 285 case RESTRICTED: 286 code = "RESTRICTED"; 287 break; 288 case OTHER: 289 code = "OTHER"; 290 break; 291 case CONNECTION_MANAGER_NOT_SUPPORTED: 292 code = "CONNECTION_MANAGER_NOT_SUPPORTED"; 293 break; 294 case CALL_PULLED: 295 code = "CALL_PULLED"; 296 break; 297 case ANSWERED_ELSEWHERE: 298 code = "ANSWERED_ELSEWHERE"; 299 break; 300 default: 301 code = "invalid code: " + mDisconnectCode; 302 break; 303 } 304 String label = mDisconnectLabel == null ? "" : mDisconnectLabel.toString(); 305 String description = mDisconnectDescription == null 306 ? "" : mDisconnectDescription.toString(); 307 String reason = mDisconnectReason == null ? "" : mDisconnectReason; 308 return "DisconnectCause [ Code: (" + code + ")" 309 + " Label: (" + label + ")" 310 + " Description: (" + description + ")" 311 + " Reason: (" + reason + ")" 312 + " Tone: (" + mToneToPlay + ") ]"; 313 } 314 } 315