PhoneAccount.java revision 9016ecab3be175dace3e1ad3e1c8558fef1a4720
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.content.Context; 20import android.content.pm.PackageManager; 21import android.content.res.Resources.NotFoundException; 22import android.graphics.drawable.Drawable; 23import android.net.Uri; 24import android.os.Parcel; 25import android.os.Parcelable; 26import android.text.TextUtils; 27 28import java.lang.String; 29import java.util.ArrayList; 30import java.util.Collections; 31import java.util.List; 32import java.util.MissingResourceException; 33 34/** 35 * Describes a distinct account, line of service or call placement method that the system 36 * can use to place phone calls. 37 */ 38public class PhoneAccount implements Parcelable { 39 40 /** 41 * Flag indicating that this {@code PhoneAccount} can act as a connection manager for 42 * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount} 43 * will be allowed to manage phone calls including using its own proprietary phone-call 44 * implementation (like VoIP calling) to make calls instead of the telephony stack. 45 * <p> 46 * When a user opts to place a call using the SIM-based telephony stack, the 47 * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first 48 * if the user has explicitly selected it to be used as the default connection manager. 49 * <p> 50 * See {@link #getCapabilities} 51 */ 52 public static final int CAPABILITY_CONNECTION_MANAGER = 0x1; 53 54 /** 55 * Flag indicating that this {@code PhoneAccount} can make phone calls in place of 56 * traditional SIM-based telephony calls. This account will be treated as a distinct method 57 * for placing calls alongside the traditional SIM-based telephony stack. This flag is 58 * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage 59 * calls from or use the built-in telephony stack to place its calls. 60 * <p> 61 * See {@link #getCapabilities} 62 * <p> 63 * {@hide} 64 */ 65 public static final int CAPABILITY_CALL_PROVIDER = 0x2; 66 67 /** 68 * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM 69 * subscription. 70 * <p> 71 * Only the Android framework can register a {@code PhoneAccount} having this capability. 72 * <p> 73 * See {@link #getCapabilities} 74 */ 75 public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4; 76 77 /** 78 * Flag indicating that this {@code PhoneAccount} is capable of placing video calls. 79 * <p> 80 * See {@link #getCapabilities} 81 * @hide 82 */ 83 public static final int CAPABILITY_VIDEO_CALLING = 0x8; 84 85 /** 86 * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls. 87 * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls. 88 * <p> 89 * See {@link #getCapabilities} 90 */ 91 public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10; 92 93 /** 94 * URI scheme for telephone number URIs. 95 */ 96 public static final String SCHEME_TEL = "tel"; 97 98 /** 99 * URI scheme for voicemail URIs. 100 */ 101 public static final String SCHEME_VOICEMAIL = "voicemail"; 102 103 /** 104 * URI scheme for SIP URIs. 105 */ 106 public static final String SCHEME_SIP = "sip"; 107 108 /** 109 * Indicating no color is set. 110 */ 111 public static final int NO_COLOR = -1; 112 113 private final PhoneAccountHandle mAccountHandle; 114 private final Uri mAddress; 115 private final Uri mSubscriptionAddress; 116 private final int mCapabilities; 117 private final int mIconResId; 118 private final int mColor; 119 private final CharSequence mLabel; 120 private final CharSequence mShortDescription; 121 private final List<String> mSupportedUriSchemes; 122 123 public static class Builder { 124 private PhoneAccountHandle mAccountHandle; 125 private Uri mAddress; 126 private Uri mSubscriptionAddress; 127 private int mCapabilities; 128 private int mIconResId; 129 private int mColor = NO_COLOR; 130 private CharSequence mLabel; 131 private CharSequence mShortDescription; 132 private List<String> mSupportedUriSchemes = new ArrayList<String>(); 133 134 public Builder(PhoneAccountHandle accountHandle, CharSequence label) { 135 this.mAccountHandle = accountHandle; 136 this.mLabel = label; 137 } 138 139 /** 140 * Creates an instance of the {@link PhoneAccount.Builder} from an existing 141 * {@link PhoneAccount}. 142 * 143 * @param phoneAccount The {@link PhoneAccount} used to initialize the builder. 144 */ 145 public Builder(PhoneAccount phoneAccount) { 146 mAccountHandle = phoneAccount.getAccountHandle(); 147 mAddress = phoneAccount.getAddress(); 148 mSubscriptionAddress = phoneAccount.getSubscriptionAddress(); 149 mCapabilities = phoneAccount.getCapabilities(); 150 mIconResId = phoneAccount.getIconResId(); 151 mColor = phoneAccount.getColor(); 152 mLabel = phoneAccount.getLabel(); 153 mShortDescription = phoneAccount.getShortDescription(); 154 mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes()); 155 } 156 157 public Builder setAddress(Uri value) { 158 this.mAddress = value; 159 return this; 160 } 161 162 public Builder setSubscriptionAddress(Uri value) { 163 this.mSubscriptionAddress = value; 164 return this; 165 } 166 167 public Builder setCapabilities(int value) { 168 this.mCapabilities = value; 169 return this; 170 } 171 172 public Builder setIconResId(int value) { 173 this.mIconResId = value; 174 return this; 175 } 176 177 public Builder setColor(int value) { 178 this.mColor = value; 179 return this; 180 } 181 182 public Builder setShortDescription(CharSequence value) { 183 this.mShortDescription = value; 184 return this; 185 } 186 187 /** 188 * Specifies an additional URI scheme supported by the {@link PhoneAccount}. 189 * 190 * @param uriScheme The URI scheme. 191 * @return The Builder. 192 * @hide 193 */ 194 public Builder addSupportedUriScheme(String uriScheme) { 195 if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) { 196 this.mSupportedUriSchemes.add(uriScheme); 197 } 198 return this; 199 } 200 201 /** 202 * Specifies the URI schemes supported by the {@link PhoneAccount}. 203 * 204 * @param uriSchemes The URI schemes. 205 * @return The Builder. 206 */ 207 public Builder setSupportedUriSchemes(List<String> uriSchemes) { 208 mSupportedUriSchemes.clear(); 209 210 if (uriSchemes != null && !uriSchemes.isEmpty()) { 211 for (String uriScheme : uriSchemes) { 212 addSupportedUriScheme(uriScheme); 213 } 214 } 215 return this; 216 } 217 218 /** 219 * Creates an instance of a {@link PhoneAccount} based on the current builder settings. 220 * 221 * @return The {@link PhoneAccount}. 222 */ 223 public PhoneAccount build() { 224 // If no supported URI schemes were defined, assume "tel" is supported. 225 if (mSupportedUriSchemes.isEmpty()) { 226 addSupportedUriScheme(SCHEME_TEL); 227 } 228 229 return new PhoneAccount( 230 mAccountHandle, 231 mAddress, 232 mSubscriptionAddress, 233 mCapabilities, 234 mIconResId, 235 mColor, 236 mLabel, 237 mShortDescription, 238 mSupportedUriSchemes); 239 } 240 } 241 242 private PhoneAccount( 243 PhoneAccountHandle account, 244 Uri address, 245 Uri subscriptionAddress, 246 int capabilities, 247 int iconResId, 248 int color, 249 CharSequence label, 250 CharSequence shortDescription, 251 List<String> supportedUriSchemes) { 252 mAccountHandle = account; 253 mAddress = address; 254 mSubscriptionAddress = subscriptionAddress; 255 mCapabilities = capabilities; 256 mIconResId = iconResId; 257 mColor = color; 258 mLabel = label; 259 mShortDescription = shortDescription; 260 mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); 261 } 262 263 public static Builder builder( 264 PhoneAccountHandle accountHandle, 265 CharSequence label) { 266 return new Builder(accountHandle, label); 267 } 268 269 /** 270 * Returns a builder initialized with the current {@link PhoneAccount} instance. 271 * 272 * @return The builder. 273 * @hide 274 */ 275 public Builder toBuilder() { return new Builder(this); } 276 277 /** 278 * The unique identifier of this {@code PhoneAccount}. 279 * 280 * @return A {@code PhoneAccountHandle}. 281 */ 282 public PhoneAccountHandle getAccountHandle() { 283 return mAccountHandle; 284 } 285 286 /** 287 * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This 288 * represents the destination from which outgoing calls using this {@code PhoneAccount} 289 * will appear to come, if applicable, and the destination to which incoming calls using this 290 * {@code PhoneAccount} may be addressed. 291 * 292 * @return A address expressed as a {@code Uri}, for example, a phone number. 293 */ 294 public Uri getAddress() { 295 return mAddress; 296 } 297 298 /** 299 * The raw callback number used for this {@code PhoneAccount}, as distinct from 300 * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered 301 * as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration 302 * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)} 303 * has been used to alter the callback number. 304 * <p> 305 * 306 * @return The subscription number, suitable for display to the user. 307 */ 308 public Uri getSubscriptionAddress() { 309 return mSubscriptionAddress; 310 } 311 312 /** 313 * The capabilities of this {@code PhoneAccount}. 314 * 315 * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities. 316 */ 317 public int getCapabilities() { 318 return mCapabilities; 319 } 320 321 /** 322 * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in 323 * bit mask. 324 * 325 * @param capability The capabilities to check. 326 * @return {@code True} if the phone account has the capability. 327 */ 328 public boolean hasCapabilities(int capability) { 329 return (mCapabilities & capability) == capability; 330 } 331 332 /** 333 * A short label describing a {@code PhoneAccount}. 334 * 335 * @return A label for this {@code PhoneAccount}. 336 */ 337 public CharSequence getLabel() { 338 return mLabel; 339 } 340 341 /** 342 * A short paragraph describing this {@code PhoneAccount}. 343 * 344 * @return A description for this {@code PhoneAccount}. 345 */ 346 public CharSequence getShortDescription() { 347 return mShortDescription; 348 } 349 350 /** 351 * The URI schemes supported by this {@code PhoneAccount}. 352 * 353 * @return The URI schemes. 354 */ 355 public List<String> getSupportedUriSchemes() { 356 return mSupportedUriSchemes; 357 } 358 359 /** 360 * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI 361 * scheme. 362 * 363 * @param uriScheme The URI scheme to check. 364 * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the 365 * specified URI scheme. 366 */ 367 public boolean supportsUriScheme(String uriScheme) { 368 if (mSupportedUriSchemes == null || uriScheme == null) { 369 return false; 370 } 371 372 for (String scheme : mSupportedUriSchemes) { 373 if (scheme != null && scheme.equals(uriScheme)) { 374 return true; 375 } 376 } 377 return false; 378 } 379 380 /** 381 * The icon resource ID for the icon of this {@code PhoneAccount}. 382 * 383 * @return A resource ID. 384 */ 385 public int getIconResId() { 386 return mIconResId; 387 } 388 389 /** 390 * A highlight color to use in displaying information about this {@code PhoneAccount}. 391 * 392 * @return A hexadecimal color value. 393 */ 394 public int getColor() { 395 return mColor; 396 } 397 398 /** 399 * An icon to represent this {@code PhoneAccount} in a user interface. 400 * 401 * @return An icon for this {@code PhoneAccount}. 402 */ 403 public Drawable getIcon(Context context) { 404 return getIcon(context, mIconResId); 405 } 406 407 private Drawable getIcon(Context context, int resId) { 408 if (resId == 0) { 409 return null; 410 } 411 412 Context packageContext; 413 try { 414 packageContext = context.createPackageContext( 415 mAccountHandle.getComponentName().getPackageName(), 0); 416 } catch (PackageManager.NameNotFoundException e) { 417 Log.w(this, "Cannot find package %s", 418 mAccountHandle.getComponentName().getPackageName()); 419 return null; 420 } 421 try { 422 return packageContext.getDrawable(resId); 423 } catch (NotFoundException|MissingResourceException e) { 424 Log.e(this, e, "Cannot find icon %d in package %s", 425 resId, mAccountHandle.getComponentName().getPackageName()); 426 return null; 427 } 428 } 429 430 // 431 // Parcelable implementation 432 // 433 434 @Override 435 public int describeContents() { 436 return 0; 437 } 438 439 @Override 440 public void writeToParcel(Parcel out, int flags) { 441 out.writeParcelable(mAccountHandle, 0); 442 out.writeParcelable(mAddress, 0); 443 out.writeParcelable(mSubscriptionAddress, 0); 444 out.writeInt(mCapabilities); 445 out.writeInt(mIconResId); 446 out.writeInt(mColor); 447 out.writeCharSequence(mLabel); 448 out.writeCharSequence(mShortDescription); 449 out.writeList(mSupportedUriSchemes); 450 } 451 452 public static final Creator<PhoneAccount> CREATOR 453 = new Creator<PhoneAccount>() { 454 @Override 455 public PhoneAccount createFromParcel(Parcel in) { 456 return new PhoneAccount(in); 457 } 458 459 @Override 460 public PhoneAccount[] newArray(int size) { 461 return new PhoneAccount[size]; 462 } 463 }; 464 465 private PhoneAccount(Parcel in) { 466 ClassLoader classLoader = PhoneAccount.class.getClassLoader(); 467 468 mAccountHandle = in.readParcelable(getClass().getClassLoader()); 469 mAddress = in.readParcelable(getClass().getClassLoader()); 470 mSubscriptionAddress = in.readParcelable(getClass().getClassLoader()); 471 mCapabilities = in.readInt(); 472 mIconResId = in.readInt(); 473 mColor = in.readInt(); 474 mLabel = in.readCharSequence(); 475 mShortDescription = in.readCharSequence(); 476 477 List<String> supportedUriSchemes = new ArrayList<>(); 478 in.readList(supportedUriSchemes, classLoader); 479 mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); 480 } 481 482 @Override 483 public String toString() { 484 StringBuilder sb = new StringBuilder().append("[PhoneAccount: ") 485 .append(mAccountHandle) 486 .append(" Capabilities: ") 487 .append(mCapabilities) 488 .append(" Schemes: "); 489 for (String scheme : mSupportedUriSchemes) { 490 sb.append(scheme) 491 .append(" "); 492 } 493 sb.append("]"); 494 return sb.toString(); 495 } 496} 497