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