Home | History | Annotate | Download | only in telecom
      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.NonNull;
     20 import android.content.ComponentName;
     21 import android.os.Parcel;
     22 import android.os.Parcelable;
     23 import android.os.Process;
     24 import android.os.UserHandle;
     25 
     26 import java.util.Objects;
     27 
     28 /**
     29  * The unique identifier for a {@link PhoneAccount}. A {@code PhoneAccountHandle} is made of two
     30  * parts:
     31  * <ul>
     32  *  <li>The component name of the associated connection service.</li>
     33  *  <li>A string identifier that is unique across {@code PhoneAccountHandle}s with the same
     34  *      component name.</li>
     35  * </ul>
     36  *
     37  * Note: This Class requires a non-null {@link ComponentName} and {@link UserHandle} to operate
     38  * properly. Passing in invalid parameters will generate a log warning.
     39  *
     40  * See {@link PhoneAccount}, {@link TelecomManager}.
     41  */
     42 public final class PhoneAccountHandle implements Parcelable {
     43     private final ComponentName mComponentName;
     44     private final String mId;
     45     private final UserHandle mUserHandle;
     46 
     47     public PhoneAccountHandle(
     48             @NonNull ComponentName componentName,
     49             @NonNull String id) {
     50         this(componentName, id, Process.myUserHandle());
     51     }
     52 
     53     public PhoneAccountHandle(
     54             @NonNull ComponentName componentName,
     55             @NonNull String id,
     56             @NonNull UserHandle userHandle) {
     57         checkParameters(componentName, userHandle);
     58         mComponentName = componentName;
     59         mId = id;
     60         mUserHandle = userHandle;
     61     }
     62 
     63     /**
     64      * The {@code ComponentName} of the connection service which is responsible for making phone
     65      * calls using this {@code PhoneAccountHandle}.
     66      *
     67      * @return A suitable {@code ComponentName}.
     68      */
     69     public ComponentName getComponentName() {
     70         return mComponentName;
     71     }
     72 
     73     /**
     74      * A string that uniquely distinguishes this particular {@code PhoneAccountHandle} from all the
     75      * others supported by the connection service that created it.
     76      * <p>
     77      * A connection service must select identifiers that are stable for the lifetime of
     78      * their users' relationship with their service, across many Android devices. For example, a
     79      * good set of identifiers might be the email addresses with which with users registered for
     80      * their accounts with a particular service. Depending on how a service chooses to operate,
     81      * a bad set of identifiers might be an increasing series of integers
     82      * ({@code 0}, {@code 1}, {@code 2}, ...) that are generated locally on each phone and could
     83      * collide with values generated on other phones or after a data wipe of a given phone.
     84      *
     85      * Important: A non-unique identifier could cause non-deterministic call-log backup/restore
     86      * behavior.
     87      *
     88      * @return A service-specific unique identifier for this {@code PhoneAccountHandle}.
     89      */
     90     public String getId() {
     91         return mId;
     92     }
     93 
     94     /**
     95      * @return the {@link UserHandle} to use when connecting to this PhoneAccount.
     96      */
     97     public UserHandle getUserHandle() {
     98         return mUserHandle;
     99     }
    100 
    101     @Override
    102     public int hashCode() {
    103         return Objects.hash(mComponentName, mId, mUserHandle);
    104     }
    105 
    106     @Override
    107     public String toString() {
    108         // Note: Log.pii called for mId as it can contain personally identifying phone account
    109         // information such as SIP account IDs.
    110         return new StringBuilder().append(mComponentName)
    111                     .append(", ")
    112                     .append(Log.pii(mId))
    113                     .append(", ")
    114                     .append(mUserHandle)
    115                     .toString();
    116     }
    117 
    118     @Override
    119     public boolean equals(Object other) {
    120         return other != null &&
    121                 other instanceof PhoneAccountHandle &&
    122                 Objects.equals(((PhoneAccountHandle) other).getComponentName(),
    123                         getComponentName()) &&
    124                 Objects.equals(((PhoneAccountHandle) other).getId(), getId()) &&
    125                 Objects.equals(((PhoneAccountHandle) other).getUserHandle(), getUserHandle());
    126     }
    127 
    128     //
    129     // Parcelable implementation.
    130     //
    131 
    132     @Override
    133     public int describeContents() {
    134         return 0;
    135     }
    136 
    137     @Override
    138     public void writeToParcel(Parcel out, int flags) {
    139         mComponentName.writeToParcel(out, flags);
    140         out.writeString(mId);
    141         mUserHandle.writeToParcel(out, flags);
    142     }
    143 
    144     private void checkParameters(ComponentName componentName, UserHandle userHandle) {
    145         if(componentName == null) {
    146             android.util.Log.w("PhoneAccountHandle", new Exception("PhoneAccountHandle has " +
    147                     "been created with null ComponentName!"));
    148         }
    149         if(userHandle == null) {
    150             android.util.Log.w("PhoneAccountHandle", new Exception("PhoneAccountHandle has " +
    151                     "been created with null UserHandle!"));
    152         }
    153     }
    154 
    155     public static final Creator<PhoneAccountHandle> CREATOR = new Creator<PhoneAccountHandle>() {
    156         @Override
    157         public PhoneAccountHandle createFromParcel(Parcel in) {
    158             return new PhoneAccountHandle(in);
    159         }
    160 
    161         @Override
    162         public PhoneAccountHandle[] newArray(int size) {
    163             return new PhoneAccountHandle[size];
    164         }
    165     };
    166 
    167     private PhoneAccountHandle(Parcel in) {
    168         this(ComponentName.CREATOR.createFromParcel(in),
    169                 in.readString(),
    170                 UserHandle.CREATOR.createFromParcel(in));
    171     }
    172 }
    173