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