• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 com.android.dialer.telecom;
18 
19 import android.content.Context;
20 import android.net.Uri;
21 import android.support.annotation.NonNull;
22 import android.support.annotation.Nullable;
23 import android.support.annotation.WorkerThread;
24 import android.telecom.Call;
25 import android.telecom.PhoneAccountHandle;
26 import android.telephony.PhoneNumberUtils;
27 import android.telephony.SubscriptionInfo;
28 import android.text.TextUtils;
29 import com.android.dialer.common.Assert;
30 import com.android.dialer.common.LogUtil;
31 import com.google.common.base.Optional;
32 import java.util.Locale;
33 
34 /**
35  * Class to provide a standard interface for obtaining information from the underlying
36  * android.telecom.Call. Much of this should be obtained through the incall.Call, but on occasion we
37  * need to interact with the telecom.Call directly (eg. call blocking, before the incall.Call has
38  * been created).
39  */
40 public class TelecomCallUtil {
41 
42   /** Returns Whether the call handle is an emergency number. */
isEmergencyCall(@onNull Call call)43   public static boolean isEmergencyCall(@NonNull Call call) {
44     Assert.isNotNull(call);
45     Uri handle = call.getDetails().getHandle();
46     return PhoneNumberUtils.isEmergencyNumber(handle == null ? "" : handle.getSchemeSpecificPart());
47   }
48 
49   /**
50    * Returns The phone number which the {@code Call} is currently connected, or {@code null} if the
51    * number is not available.
52    */
53   @Nullable
getNumber(@ullable Call call)54   public static String getNumber(@Nullable Call call) {
55     if (call == null) {
56       return null;
57     }
58     if (call.getDetails().getGatewayInfo() != null) {
59       return call.getDetails().getGatewayInfo().getOriginalAddress().getSchemeSpecificPart();
60     }
61     Uri handle = getHandle(call);
62     return handle == null ? null : handle.getSchemeSpecificPart();
63   }
64 
65   /**
66    * Returns The handle (e.g., phone number) to which the {@code Call} is currently connected, or
67    * {@code null} if the number is not available.
68    */
69   @Nullable
getHandle(@ullable Call call)70   public static Uri getHandle(@Nullable Call call) {
71     return call == null ? null : call.getDetails().getHandle();
72   }
73 
74   /**
75    * Normalizes the number of the {@code call} to E.164. The country of the SIM associated with the
76    * call is used to determine the country.
77    *
78    * <p>If the number cannot be formatted (because for example the country cannot be determined),
79    * returns the number with non-dialable digits removed.
80    */
81   @WorkerThread
getNormalizedNumber(Context appContext, Call call)82   public static Optional<String> getNormalizedNumber(Context appContext, Call call) {
83     Assert.isWorkerThread();
84 
85     Optional<String> validE164 = getValidE164Number(appContext, call);
86     if (validE164.isPresent()) {
87       return validE164;
88     }
89     String rawNumber = getNumber(call);
90     if (TextUtils.isEmpty(rawNumber)) {
91       return Optional.absent();
92     }
93     return Optional.of(PhoneNumberUtils.normalizeNumber(rawNumber));
94   }
95 
96   /**
97    * Formats the number of the {@code call} to E.164 if it is valid. The country of the SIM
98    * associated with the call is used to determine the country.
99    *
100    * <p>If the number cannot be formatted (because for example it is invalid or the country cannot
101    * be determined), returns {@link Optional#absent()}.
102    */
103   @WorkerThread
getValidE164Number(Context appContext, Call call)104   public static Optional<String> getValidE164Number(Context appContext, Call call) {
105     Assert.isWorkerThread();
106     String rawNumber = getNumber(call);
107     if (TextUtils.isEmpty(rawNumber)) {
108       return Optional.absent();
109     }
110     Optional<String> countryCode = getCountryCode(appContext, call);
111     if (!countryCode.isPresent()) {
112       LogUtil.w("TelecomCallUtil.getValidE164Number", "couldn't find a country code for call");
113       return Optional.absent();
114     }
115     return Optional.fromNullable(PhoneNumberUtils.formatNumberToE164(rawNumber, countryCode.get()));
116   }
117 
118   @WorkerThread
getCountryCode(Context appContext, Call call)119   public static Optional<String> getCountryCode(Context appContext, Call call) {
120     Assert.isWorkerThread();
121     PhoneAccountHandle phoneAccountHandle = call.getDetails().getAccountHandle();
122     Optional<SubscriptionInfo> subscriptionInfo =
123         TelecomUtil.getSubscriptionInfo(appContext, phoneAccountHandle);
124     if (subscriptionInfo.isPresent() && subscriptionInfo.get().getCountryIso() != null) {
125       return Optional.of(subscriptionInfo.get().getCountryIso().toUpperCase(Locale.US));
126     }
127     return Optional.absent();
128   }
129 }
130