PhoneAccount.java revision ef9f6f957d897ea0ed82114185b8fa3fefd4917b
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 * Flag indicating that this {@code PhoneAccount} is always enabled and cannot be disabled by 95 * the user. 96 * This capability is reserved for important {@code PhoneAccount}s such as the emergency calling 97 * only {@code PhoneAccount}. 98 * <p> 99 * See {@link #getCapabilities} 100 * @hide 101 */ 102 public static final int CAPABILITY_ALWAYS_ENABLED = 0x20; 103 104 /** 105 * URI scheme for telephone number URIs. 106 */ 107 public static final String SCHEME_TEL = "tel"; 108 109 /** 110 * URI scheme for voicemail URIs. 111 */ 112 public static final String SCHEME_VOICEMAIL = "voicemail"; 113 114 /** 115 * URI scheme for SIP URIs. 116 */ 117 public static final String SCHEME_SIP = "sip"; 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 CharSequence mLabel; 125 private final CharSequence mShortDescription; 126 private final List<String> mSupportedUriSchemes; 127 private final boolean mIsEnabled; 128 129 public static class Builder { 130 private PhoneAccountHandle mAccountHandle; 131 private Uri mAddress; 132 private Uri mSubscriptionAddress; 133 private int mCapabilities; 134 private int mIconResId; 135 private CharSequence mLabel; 136 private CharSequence mShortDescription; 137 private List<String> mSupportedUriSchemes = new ArrayList<String>(); 138 private boolean mIsEnabled = false; 139 140 public Builder(PhoneAccountHandle accountHandle, CharSequence label) { 141 this.mAccountHandle = accountHandle; 142 this.mLabel = label; 143 } 144 145 /** 146 * Creates an instance of the {@link PhoneAccount.Builder} from an existing 147 * {@link PhoneAccount}. 148 * 149 * @param phoneAccount The {@link PhoneAccount} used to initialize the builder. 150 */ 151 public Builder(PhoneAccount phoneAccount) { 152 mAccountHandle = phoneAccount.getAccountHandle(); 153 mAddress = phoneAccount.getAddress(); 154 mSubscriptionAddress = phoneAccount.getSubscriptionAddress(); 155 mCapabilities = phoneAccount.getCapabilities(); 156 mIconResId = phoneAccount.getIconResId(); 157 mLabel = phoneAccount.getLabel(); 158 mShortDescription = phoneAccount.getShortDescription(); 159 mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes()); 160 mIsEnabled = phoneAccount.isEnabled(); 161 } 162 163 public Builder setAddress(Uri value) { 164 this.mAddress = value; 165 return this; 166 } 167 168 public Builder setSubscriptionAddress(Uri value) { 169 this.mSubscriptionAddress = value; 170 return this; 171 } 172 173 public Builder setCapabilities(int value) { 174 this.mCapabilities = value; 175 return this; 176 } 177 178 public Builder setIconResId(int value) { 179 this.mIconResId = value; 180 return this; 181 } 182 183 public Builder setShortDescription(CharSequence value) { 184 this.mShortDescription = value; 185 return this; 186 } 187 188 /** 189 * Specifies an additional URI scheme supported by the {@link PhoneAccount}. 190 * 191 * @param uriScheme The URI scheme. 192 * @return The Builder. 193 * @hide 194 */ 195 public Builder addSupportedUriScheme(String uriScheme) { 196 if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) { 197 this.mSupportedUriSchemes.add(uriScheme); 198 } 199 return this; 200 } 201 202 /** 203 * Specifies the URI schemes supported by the {@link PhoneAccount}. 204 * 205 * @param uriSchemes The URI schemes. 206 * @return The Builder. 207 */ 208 public Builder setSupportedUriSchemes(List<String> uriSchemes) { 209 mSupportedUriSchemes.clear(); 210 211 if (uriSchemes != null && !uriSchemes.isEmpty()) { 212 for (String uriScheme : uriSchemes) { 213 addSupportedUriScheme(uriScheme); 214 } 215 } 216 return this; 217 } 218 219 /** 220 * Specifies whether the {@link PhoneAccount} is enabled or not. {@link PhoneAccount}s are 221 * by default not enabled. 222 * 223 * @param value {@code True} if the {@link PhoneAccount} is enabled. 224 * @return The Builder. 225 * @hide 226 */ 227 public Builder setEnabled(boolean value) { 228 this.mIsEnabled = value; 229 return this; 230 } 231 232 /** 233 * Creates an instance of a {@link PhoneAccount} based on the current builder settings. 234 * 235 * @return The {@link PhoneAccount}. 236 */ 237 public PhoneAccount build() { 238 // If no supported URI schemes were defined, assume "tel" is supported. 239 if (mSupportedUriSchemes.isEmpty()) { 240 addSupportedUriScheme(SCHEME_TEL); 241 } 242 243 return new PhoneAccount( 244 mAccountHandle, 245 mAddress, 246 mSubscriptionAddress, 247 mCapabilities, 248 mIconResId, 249 mLabel, 250 mShortDescription, 251 mSupportedUriSchemes, 252 mIsEnabled); 253 } 254 } 255 256 private PhoneAccount( 257 PhoneAccountHandle account, 258 Uri address, 259 Uri subscriptionAddress, 260 int capabilities, 261 int iconResId, 262 CharSequence label, 263 CharSequence shortDescription, 264 List<String> supportedUriSchemes, 265 boolean enabled) { 266 mAccountHandle = account; 267 mAddress = address; 268 mSubscriptionAddress = subscriptionAddress; 269 mCapabilities = capabilities; 270 mIconResId = iconResId; 271 mLabel = label; 272 mShortDescription = shortDescription; 273 mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); 274 mIsEnabled = enabled; 275 } 276 277 public static Builder builder( 278 PhoneAccountHandle accountHandle, 279 CharSequence label) { 280 return new Builder(accountHandle, label); 281 } 282 283 /** 284 * Returns a builder initialized with the current {@link PhoneAccount} instance. 285 * 286 * @return The builder. 287 * @hide 288 */ 289 public Builder toBuilder() { return new Builder(this); } 290 291 /** 292 * The unique identifier of this {@code PhoneAccount}. 293 * 294 * @return A {@code PhoneAccountHandle}. 295 */ 296 public PhoneAccountHandle getAccountHandle() { 297 return mAccountHandle; 298 } 299 300 /** 301 * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This 302 * represents the destination from which outgoing calls using this {@code PhoneAccount} 303 * will appear to come, if applicable, and the destination to which incoming calls using this 304 * {@code PhoneAccount} may be addressed. 305 * 306 * @return A address expressed as a {@code Uri}, for example, a phone number. 307 */ 308 public Uri getAddress() { 309 return mAddress; 310 } 311 312 /** 313 * The raw callback number used for this {@code PhoneAccount}, as distinct from 314 * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered 315 * as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration 316 * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)} 317 * has been used to alter the callback number. 318 * <p> 319 * 320 * @return The subscription number, suitable for display to the user. 321 */ 322 public Uri getSubscriptionAddress() { 323 return mSubscriptionAddress; 324 } 325 326 /** 327 * The capabilities of this {@code PhoneAccount}. 328 * 329 * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities. 330 */ 331 public int getCapabilities() { 332 return mCapabilities; 333 } 334 335 /** 336 * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in 337 * bit mask. 338 * 339 * @param capability The capabilities to check. 340 * @return {@code True} if the phone account has the capability. 341 */ 342 public boolean hasCapabilities(int capability) { 343 return (mCapabilities & capability) == capability; 344 } 345 346 /** 347 * A short label describing a {@code PhoneAccount}. 348 * 349 * @return A label for this {@code PhoneAccount}. 350 */ 351 public CharSequence getLabel() { 352 return mLabel; 353 } 354 355 /** 356 * A short paragraph describing this {@code PhoneAccount}. 357 * 358 * @return A description for this {@code PhoneAccount}. 359 */ 360 public CharSequence getShortDescription() { 361 return mShortDescription; 362 } 363 364 /** 365 * The URI schemes supported by this {@code PhoneAccount}. 366 * 367 * @return The URI schemes. 368 */ 369 public List<String> getSupportedUriSchemes() { 370 return mSupportedUriSchemes; 371 } 372 373 /** 374 * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI 375 * scheme. 376 * 377 * @param uriScheme The URI scheme to check. 378 * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the 379 * specified URI scheme. 380 */ 381 public boolean supportsUriScheme(String uriScheme) { 382 if (mSupportedUriSchemes == null || uriScheme == null) { 383 return false; 384 } 385 386 for (String scheme : mSupportedUriSchemes) { 387 if (scheme != null && scheme.equals(uriScheme)) { 388 return true; 389 } 390 } 391 return false; 392 } 393 394 /** 395 * Determines whether this {@code PhoneAccount} is enabled. 396 * 397 * @return {@code True} if this {@code PhoneAccount} is enabled.. 398 */ 399 public boolean isEnabled() { 400 return mIsEnabled; 401 } 402 403 /** 404 * The icon resource ID for the icon of this {@code PhoneAccount}. 405 * 406 * @return A resource ID. 407 */ 408 public int getIconResId() { 409 return mIconResId; 410 } 411 412 /** 413 * An icon to represent this {@code PhoneAccount} in a user interface. 414 * 415 * @return An icon for this {@code PhoneAccount}. 416 */ 417 public Drawable getIcon(Context context) { 418 return getIcon(context, mIconResId); 419 } 420 421 private Drawable getIcon(Context context, int resId) { 422 Context packageContext; 423 try { 424 packageContext = context.createPackageContext( 425 mAccountHandle.getComponentName().getPackageName(), 0); 426 } catch (PackageManager.NameNotFoundException e) { 427 Log.w(this, "Cannot find package %s", mAccountHandle.getComponentName().getPackageName()); 428 return null; 429 } 430 try { 431 return packageContext.getDrawable(resId); 432 } catch (NotFoundException|MissingResourceException e) { 433 Log.e(this, e, "Cannot find icon %d in package %s", 434 resId, mAccountHandle.getComponentName().getPackageName()); 435 return null; 436 } 437 } 438 439 // 440 // Parcelable implementation 441 // 442 443 @Override 444 public int describeContents() { 445 return 0; 446 } 447 448 @Override 449 public void writeToParcel(Parcel out, int flags) { 450 out.writeParcelable(mAccountHandle, 0); 451 out.writeParcelable(mAddress, 0); 452 out.writeParcelable(mSubscriptionAddress, 0); 453 out.writeInt(mCapabilities); 454 out.writeInt(mIconResId); 455 out.writeCharSequence(mLabel); 456 out.writeCharSequence(mShortDescription); 457 out.writeList(mSupportedUriSchemes); 458 out.writeInt(mIsEnabled ? 1 : 0); 459 } 460 461 public static final Creator<PhoneAccount> CREATOR 462 = new Creator<PhoneAccount>() { 463 @Override 464 public PhoneAccount createFromParcel(Parcel in) { 465 return new PhoneAccount(in); 466 } 467 468 @Override 469 public PhoneAccount[] newArray(int size) { 470 return new PhoneAccount[size]; 471 } 472 }; 473 474 private PhoneAccount(Parcel in) { 475 ClassLoader classLoader = PhoneAccount.class.getClassLoader(); 476 477 mAccountHandle = in.readParcelable(getClass().getClassLoader()); 478 mAddress = in.readParcelable(getClass().getClassLoader()); 479 mSubscriptionAddress = in.readParcelable(getClass().getClassLoader()); 480 mCapabilities = in.readInt(); 481 mIconResId = in.readInt(); 482 mLabel = in.readCharSequence(); 483 mShortDescription = in.readCharSequence(); 484 485 List<String> supportedUriSchemes = new ArrayList<>(); 486 in.readList(supportedUriSchemes, classLoader); 487 mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); 488 mIsEnabled = in.readInt() == 1; 489 } 490} 491