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.telephony.PhoneNumberUtils;
26 import android.text.TextUtils;
27 import com.android.dialer.common.Assert;
28 import com.android.dialer.location.GeoUtil;
29 import com.google.common.base.Optional;
30 
31 /**
32  * Class to provide a standard interface for obtaining information from the underlying
33  * android.telecom.Call. Much of this should be obtained through the incall.Call, but on occasion we
34  * need to interact with the telecom.Call directly (eg. call blocking, before the incall.Call has
35  * been created).
36  */
37 public class TelecomCallUtil {
38 
39   /** Returns Whether the call handle is an emergency number. */
isEmergencyCall(@onNull Call call)40   public static boolean isEmergencyCall(@NonNull Call call) {
41     Assert.isNotNull(call);
42     Uri handle = call.getDetails().getHandle();
43     return PhoneNumberUtils.isEmergencyNumber(handle == null ? "" : handle.getSchemeSpecificPart());
44   }
45 
46   /**
47    * Returns The phone number which the {@code Call} is currently connected, or {@code null} if the
48    * number is not available.
49    */
50   @Nullable
getNumber(@ullable Call call)51   public static String getNumber(@Nullable Call call) {
52     if (call == null) {
53       return null;
54     }
55     if (call.getDetails().getGatewayInfo() != null) {
56       return call.getDetails().getGatewayInfo().getOriginalAddress().getSchemeSpecificPart();
57     }
58     Uri handle = getHandle(call);
59     return handle == null ? null : handle.getSchemeSpecificPart();
60   }
61 
62   /**
63    * Returns The handle (e.g., phone number) to which the {@code Call} is currently connected, or
64    * {@code null} if the number is not available.
65    */
66   @Nullable
getHandle(@ullable Call call)67   public static Uri getHandle(@Nullable Call call) {
68     return call == null ? null : call.getDetails().getHandle();
69   }
70 
71   /**
72    * Normalizes the number of the {@code call} to E.164. If the number for the call does not contain
73    * a country code, then the current location as defined by {@link
74    * GeoUtil#getCurrentCountryIso(Context)} is used.
75    *
76    * <p>If the number cannot be formatted (because for example number is invalid), returns the
77    * number with non-dialable digits removed.
78    */
79   @WorkerThread
getNormalizedNumber(Context appContext, Call call)80   public static Optional<String> getNormalizedNumber(Context appContext, Call call) {
81     Assert.isWorkerThread();
82 
83     Optional<String> validE164 = getValidE164Number(appContext, call);
84     if (validE164.isPresent()) {
85       return validE164;
86     }
87     String rawNumber = getNumber(call);
88     if (TextUtils.isEmpty(rawNumber)) {
89       return Optional.absent();
90     }
91     return Optional.of(PhoneNumberUtils.normalizeNumber(rawNumber));
92   }
93 
94   /**
95    * Formats the number of the {@code call} to E.164 if it is valid. If the number for the call does
96    * not contain a country code, then the current location as defined by {@link
97    * GeoUtil#getCurrentCountryIso(Context)} is used.
98    *
99    * <p>If the number cannot be formatted (because for example it is invalid), returns {@link
100    * Optional#absent()}.
101    */
102   @WorkerThread
getValidE164Number(Context appContext, Call call)103   public static Optional<String> getValidE164Number(Context appContext, Call call) {
104     Assert.isWorkerThread();
105     String rawNumber = getNumber(call);
106     if (TextUtils.isEmpty(rawNumber)) {
107       return Optional.absent();
108     }
109     return Optional.fromNullable(
110         PhoneNumberUtils.formatNumberToE164(rawNumber, GeoUtil.getCurrentCountryIso(appContext)));
111   }
112 }
113