1a4745bddb3a012c826225df313820ccd8a68455dtwyen/*
2a4745bddb3a012c826225df313820ccd8a68455dtwyen * Copyright (C) 2015 The Android Open Source Project
3a4745bddb3a012c826225df313820ccd8a68455dtwyen *
4a4745bddb3a012c826225df313820ccd8a68455dtwyen * Licensed under the Apache License, Version 2.0 (the "License");
5a4745bddb3a012c826225df313820ccd8a68455dtwyen * you may not use this file except in compliance with the License.
6a4745bddb3a012c826225df313820ccd8a68455dtwyen * You may obtain a copy of the License at
7a4745bddb3a012c826225df313820ccd8a68455dtwyen *
8a4745bddb3a012c826225df313820ccd8a68455dtwyen *      http://www.apache.org/licenses/LICENSE-2.0
9a4745bddb3a012c826225df313820ccd8a68455dtwyen *
10a4745bddb3a012c826225df313820ccd8a68455dtwyen * Unless required by applicable law or agreed to in writing, software
11a4745bddb3a012c826225df313820ccd8a68455dtwyen * distributed under the License is distributed on an "AS IS" BASIS,
12a4745bddb3a012c826225df313820ccd8a68455dtwyen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a4745bddb3a012c826225df313820ccd8a68455dtwyen * See the License for the specific language governing permissions and
14a4745bddb3a012c826225df313820ccd8a68455dtwyen * limitations under the License.
15a4745bddb3a012c826225df313820ccd8a68455dtwyen */
16a4745bddb3a012c826225df313820ccd8a68455dtwyen
17a4745bddb3a012c826225df313820ccd8a68455dtwyenpackage com.android.dialer.telecom;
18a4745bddb3a012c826225df313820ccd8a68455dtwyen
19a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.content.Context;
20a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.net.Uri;
21a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.support.annotation.NonNull;
22a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.support.annotation.Nullable;
23a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.support.annotation.WorkerThread;
24a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.telecom.Call;
25a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.telecom.PhoneAccountHandle;
26a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.telephony.PhoneNumberUtils;
27a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.telephony.SubscriptionInfo;
28a4745bddb3a012c826225df313820ccd8a68455dtwyenimport android.text.TextUtils;
29a4745bddb3a012c826225df313820ccd8a68455dtwyenimport com.android.dialer.common.Assert;
30a4745bddb3a012c826225df313820ccd8a68455dtwyenimport com.android.dialer.common.LogUtil;
31a4745bddb3a012c826225df313820ccd8a68455dtwyenimport com.google.common.base.Optional;
32a4745bddb3a012c826225df313820ccd8a68455dtwyenimport java.util.Locale;
33a4745bddb3a012c826225df313820ccd8a68455dtwyen
34a4745bddb3a012c826225df313820ccd8a68455dtwyen/**
35a4745bddb3a012c826225df313820ccd8a68455dtwyen * Class to provide a standard interface for obtaining information from the underlying
36a4745bddb3a012c826225df313820ccd8a68455dtwyen * android.telecom.Call. Much of this should be obtained through the incall.Call, but on occasion we
37a4745bddb3a012c826225df313820ccd8a68455dtwyen * need to interact with the telecom.Call directly (eg. call blocking, before the incall.Call has
38a4745bddb3a012c826225df313820ccd8a68455dtwyen * been created).
39a4745bddb3a012c826225df313820ccd8a68455dtwyen */
40a4745bddb3a012c826225df313820ccd8a68455dtwyenpublic class TelecomCallUtil {
41a4745bddb3a012c826225df313820ccd8a68455dtwyen
42a4745bddb3a012c826225df313820ccd8a68455dtwyen  /** Returns Whether the call handle is an emergency number. */
43a4745bddb3a012c826225df313820ccd8a68455dtwyen  public static boolean isEmergencyCall(@NonNull Call call) {
44a4745bddb3a012c826225df313820ccd8a68455dtwyen    Assert.isNotNull(call);
45a4745bddb3a012c826225df313820ccd8a68455dtwyen    Uri handle = call.getDetails().getHandle();
46a4745bddb3a012c826225df313820ccd8a68455dtwyen    return PhoneNumberUtils.isEmergencyNumber(handle == null ? "" : handle.getSchemeSpecificPart());
47a4745bddb3a012c826225df313820ccd8a68455dtwyen  }
48a4745bddb3a012c826225df313820ccd8a68455dtwyen
49a4745bddb3a012c826225df313820ccd8a68455dtwyen  /**
50a4745bddb3a012c826225df313820ccd8a68455dtwyen   * Returns The phone number which the {@code Call} is currently connected, or {@code null} if the
51a4745bddb3a012c826225df313820ccd8a68455dtwyen   * number is not available.
52a4745bddb3a012c826225df313820ccd8a68455dtwyen   */
53a4745bddb3a012c826225df313820ccd8a68455dtwyen  @Nullable
54a4745bddb3a012c826225df313820ccd8a68455dtwyen  public static String getNumber(@Nullable Call call) {
55a4745bddb3a012c826225df313820ccd8a68455dtwyen    if (call == null) {
56a4745bddb3a012c826225df313820ccd8a68455dtwyen      return null;
57a4745bddb3a012c826225df313820ccd8a68455dtwyen    }
58a4745bddb3a012c826225df313820ccd8a68455dtwyen    if (call.getDetails().getGatewayInfo() != null) {
59a4745bddb3a012c826225df313820ccd8a68455dtwyen      return call.getDetails().getGatewayInfo().getOriginalAddress().getSchemeSpecificPart();
60a4745bddb3a012c826225df313820ccd8a68455dtwyen    }
61a4745bddb3a012c826225df313820ccd8a68455dtwyen    Uri handle = getHandle(call);
62a4745bddb3a012c826225df313820ccd8a68455dtwyen    return handle == null ? null : handle.getSchemeSpecificPart();
63a4745bddb3a012c826225df313820ccd8a68455dtwyen  }
64a4745bddb3a012c826225df313820ccd8a68455dtwyen
65a4745bddb3a012c826225df313820ccd8a68455dtwyen  /**
66a4745bddb3a012c826225df313820ccd8a68455dtwyen   * Returns The handle (e.g., phone number) to which the {@code Call} is currently connected, or
67a4745bddb3a012c826225df313820ccd8a68455dtwyen   * {@code null} if the number is not available.
68a4745bddb3a012c826225df313820ccd8a68455dtwyen   */
69a4745bddb3a012c826225df313820ccd8a68455dtwyen  @Nullable
70a4745bddb3a012c826225df313820ccd8a68455dtwyen  public static Uri getHandle(@Nullable Call call) {
71a4745bddb3a012c826225df313820ccd8a68455dtwyen    return call == null ? null : call.getDetails().getHandle();
72a4745bddb3a012c826225df313820ccd8a68455dtwyen  }
73a4745bddb3a012c826225df313820ccd8a68455dtwyen
74a4745bddb3a012c826225df313820ccd8a68455dtwyen  /**
75e3b74d22b4e92009433e07f29973f53fb90613e1zachh   * Normalizes the number of the {@code call} to E.164. The country of the SIM associated with the
76e3b74d22b4e92009433e07f29973f53fb90613e1zachh   * call is used to determine the country.
77e3b74d22b4e92009433e07f29973f53fb90613e1zachh   *
78e3b74d22b4e92009433e07f29973f53fb90613e1zachh   * <p>If the number cannot be formatted (because for example the country cannot be determined),
79e3b74d22b4e92009433e07f29973f53fb90613e1zachh   * returns the number with non-dialable digits removed.
80a4745bddb3a012c826225df313820ccd8a68455dtwyen   */
81a4745bddb3a012c826225df313820ccd8a68455dtwyen  @WorkerThread
82a4745bddb3a012c826225df313820ccd8a68455dtwyen  public static Optional<String> getNormalizedNumber(Context appContext, Call call) {
83a4745bddb3a012c826225df313820ccd8a68455dtwyen    Assert.isWorkerThread();
84e3b74d22b4e92009433e07f29973f53fb90613e1zachh
85a240266106bf99780a48d86883499dbebd20fbdazachh    Optional<String> validE164 = getValidE164Number(appContext, call);
86a240266106bf99780a48d86883499dbebd20fbdazachh    if (validE164.isPresent()) {
87a240266106bf99780a48d86883499dbebd20fbdazachh      return validE164;
88e3b74d22b4e92009433e07f29973f53fb90613e1zachh    }
89e3b74d22b4e92009433e07f29973f53fb90613e1zachh    String rawNumber = getNumber(call);
90e3b74d22b4e92009433e07f29973f53fb90613e1zachh    if (TextUtils.isEmpty(rawNumber)) {
91e3b74d22b4e92009433e07f29973f53fb90613e1zachh      return Optional.absent();
92e3b74d22b4e92009433e07f29973f53fb90613e1zachh    }
93e3b74d22b4e92009433e07f29973f53fb90613e1zachh    return Optional.of(PhoneNumberUtils.normalizeNumber(rawNumber));
94e3b74d22b4e92009433e07f29973f53fb90613e1zachh  }
95e3b74d22b4e92009433e07f29973f53fb90613e1zachh
96e3b74d22b4e92009433e07f29973f53fb90613e1zachh  /**
97a240266106bf99780a48d86883499dbebd20fbdazachh   * Formats the number of the {@code call} to E.164 if it is valid. The country of the SIM
98a240266106bf99780a48d86883499dbebd20fbdazachh   * associated with the call is used to determine the country.
99e3b74d22b4e92009433e07f29973f53fb90613e1zachh   *
100a240266106bf99780a48d86883499dbebd20fbdazachh   * <p>If the number cannot be formatted (because for example it is invalid or the country cannot
101a240266106bf99780a48d86883499dbebd20fbdazachh   * be determined), returns {@link Optional#absent()}.
102e3b74d22b4e92009433e07f29973f53fb90613e1zachh   */
103e3b74d22b4e92009433e07f29973f53fb90613e1zachh  @WorkerThread
104a240266106bf99780a48d86883499dbebd20fbdazachh  public static Optional<String> getValidE164Number(Context appContext, Call call) {
105e3b74d22b4e92009433e07f29973f53fb90613e1zachh    Assert.isWorkerThread();
106a4745bddb3a012c826225df313820ccd8a68455dtwyen    String rawNumber = getNumber(call);
107a4745bddb3a012c826225df313820ccd8a68455dtwyen    if (TextUtils.isEmpty(rawNumber)) {
108a4745bddb3a012c826225df313820ccd8a68455dtwyen      return Optional.absent();
109a4745bddb3a012c826225df313820ccd8a68455dtwyen    }
110fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    Optional<String> countryCode = getCountryCode(appContext, call);
111fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    if (!countryCode.isPresent()) {
112a240266106bf99780a48d86883499dbebd20fbdazachh      LogUtil.w("TelecomCallUtil.getValidE164Number", "couldn't find a country code for call");
113e3b74d22b4e92009433e07f29973f53fb90613e1zachh      return Optional.absent();
114a4745bddb3a012c826225df313820ccd8a68455dtwyen    }
115fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    return Optional.fromNullable(PhoneNumberUtils.formatNumberToE164(rawNumber, countryCode.get()));
116fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen  }
117fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen
118fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen  @WorkerThread
119fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen  public static Optional<String> getCountryCode(Context appContext, Call call) {
120fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    Assert.isWorkerThread();
121fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    PhoneAccountHandle phoneAccountHandle = call.getDetails().getAccountHandle();
122fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    Optional<SubscriptionInfo> subscriptionInfo =
123fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen        TelecomUtil.getSubscriptionInfo(appContext, phoneAccountHandle);
124fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    if (subscriptionInfo.isPresent() && subscriptionInfo.get().getCountryIso() != null) {
125fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen      return Optional.of(subscriptionInfo.get().getCountryIso().toUpperCase(Locale.US));
126fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    }
127fb112d870c3a564d2dcb0e72dcdcabb6e0375520twyen    return Optional.absent();
128a4745bddb3a012c826225df313820ccd8a68455dtwyen  }
129a4745bddb3a012c826225df313820ccd8a68455dtwyen}
130