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