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 package com.android.contacts.common.compat.telecom;
17 
18 import android.app.Activity;
19 import android.content.Intent;
20 import android.content.Context;
21 import android.net.Uri;
22 import android.support.annotation.Nullable;
23 import android.telecom.PhoneAccount;
24 import android.telecom.PhoneAccountHandle;
25 import android.telecom.TelecomManager;
26 import android.telephony.PhoneNumberUtils;
27 import android.telephony.TelephonyManager;
28 import android.text.TextUtils;
29 
30 import com.android.contacts.common.compat.CompatUtils;
31 
32 import java.lang.reflect.Method;
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 /**
37  * Compatibility class for {@link android.telecom.TelecomManager}.
38  */
39 public class TelecomManagerCompat {
40     public static final String TELECOM_MANAGER_CLASS = "android.telecom.TelecomManager";
41     /**
42      * Places a new outgoing call to the provided address using the system telecom service with
43      * the specified intent.
44      *
45      * @param activity {@link Activity} used to start another activity for the given intent
46      * @param telecomManager the {@link TelecomManager} used to place a call, if possible
47      * @param intent the intent for the call
48      */
placeCall(@ullable Activity activity, @Nullable TelecomManager telecomManager, @Nullable Intent intent)49     public static void placeCall(@Nullable Activity activity,
50             @Nullable TelecomManager telecomManager, @Nullable Intent intent) {
51         if (activity == null || telecomManager == null || intent == null) {
52             return;
53         }
54         if (CompatUtils.isMarshmallowCompatible()) {
55             telecomManager.placeCall(intent.getData(), intent.getExtras());
56             return;
57         }
58         activity.startActivityForResult(intent, 0);
59     }
60 
61     /**
62      * Get the URI for running an adn query.
63      *
64      * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
65      * @param accountHandle The handle for the account to derive an adn query URI for or
66      * {@code null} to return a URI which will use the default account.
67      * @return The URI (with the content:// scheme) specific to the specified {@link PhoneAccount}
68      * for the the content retrieve.
69      */
getAdnUriForPhoneAccount(@ullable TelecomManager telecomManager, PhoneAccountHandle accountHandle)70     public static Uri getAdnUriForPhoneAccount(@Nullable TelecomManager telecomManager,
71             PhoneAccountHandle accountHandle) {
72         if (telecomManager != null && (CompatUtils.isMarshmallowCompatible()
73                 || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "getAdnUriForPhoneAccount",
74                         PhoneAccountHandle.class))) {
75             return telecomManager.getAdnUriForPhoneAccount(accountHandle);
76         }
77         return Uri.parse("content://icc/adn");
78     }
79 
80     /**
81      * Returns a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
82      * calls. The returned list includes only those accounts which have been explicitly enabled
83      * by the user.
84      *
85      * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
86      * @return A list of PhoneAccountHandle objects.
87      */
getCallCapablePhoneAccounts( @ullable TelecomManager telecomManager)88     public static List<PhoneAccountHandle> getCallCapablePhoneAccounts(
89             @Nullable TelecomManager telecomManager) {
90         if (telecomManager != null && (CompatUtils.isMarshmallowCompatible()
91                 || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS,
92                         "getCallCapablePhoneAccounts"))) {
93             return telecomManager.getCallCapablePhoneAccounts();
94         }
95         return new ArrayList<>();
96     }
97 
98     /**
99      * Used to determine the currently selected default dialer package.
100      *
101      * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
102      * @return package name for the default dialer package or null if no package has been
103      *         selected as the default dialer.
104      */
105     @Nullable
getDefaultDialerPackage(@ullable TelecomManager telecomManager)106     public static String getDefaultDialerPackage(@Nullable TelecomManager telecomManager) {
107         if (telecomManager != null && CompatUtils.isDefaultDialerCompatible()) {
108             return telecomManager.getDefaultDialerPackage();
109         }
110         return null;
111     }
112 
113     /**
114      * Return the {@link PhoneAccount} which will be used to place outgoing calls to addresses with
115      * the specified {@code uriScheme}. This PhoneAccount will always be a member of the
116      * list which is returned from invoking {@link TelecomManager#getCallCapablePhoneAccounts()}.
117      * The specific account returned depends on the following priorities:
118      *
119      * 1. If the user-selected default PhoneAccount supports the specified scheme, it will
120      * be returned.
121      * 2. If there exists only one PhoneAccount that supports the specified scheme, it
122      * will be returned.
123      *
124      * If no PhoneAccount fits the criteria above, this method will return {@code null}.
125      *
126      * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
127      * @param uriScheme The URI scheme.
128      * @return The {@link PhoneAccountHandle} corresponding to the account to be used.
129      */
130     @Nullable
getDefaultOutgoingPhoneAccount( @ullable TelecomManager telecomManager, @Nullable String uriScheme)131     public static PhoneAccountHandle getDefaultOutgoingPhoneAccount(
132             @Nullable TelecomManager telecomManager, @Nullable String uriScheme) {
133         if (telecomManager != null && (CompatUtils.isMarshmallowCompatible()
134                 || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS,
135                         "getDefaultOutgoingPhoneAccount", String.class))) {
136             return telecomManager.getDefaultOutgoingPhoneAccount(uriScheme);
137         }
138         return null;
139     }
140 
141     /**
142      * Return the line 1 phone number for given phone account.
143      *
144      * @param telecomManager the {@link TelecomManager} to use in the event that
145      *    {@link TelecomManager#getLine1Number(PhoneAccountHandle)} is available
146      * @param telephonyManager the {@link TelephonyManager} to use if TelecomManager#getLine1Number
147      *    is unavailable
148      * @param phoneAccountHandle the phoneAccountHandle upon which to check the line one number
149      * @return the line one number
150      */
151     @Nullable
getLine1Number(@ullable TelecomManager telecomManager, @Nullable TelephonyManager telephonyManager, @Nullable PhoneAccountHandle phoneAccountHandle)152     public static String getLine1Number(@Nullable TelecomManager telecomManager,
153             @Nullable TelephonyManager telephonyManager,
154             @Nullable PhoneAccountHandle phoneAccountHandle) {
155         if (telecomManager != null && CompatUtils.isMarshmallowCompatible()) {
156             return telecomManager.getLine1Number(phoneAccountHandle);
157         }
158         if (telephonyManager != null) {
159             return telephonyManager.getLine1Number();
160         }
161         return null;
162     }
163 
164     /**
165      * Return whether a given phone number is the configured voicemail number for a
166      * particular phone account.
167      *
168      * @param telecomManager the {@link TelecomManager} to use for checking the number.
169      * @param accountHandle The handle for the account to check the voicemail number against
170      * @param number The number to look up.
171      */
isVoiceMailNumber(@ullable TelecomManager telecomManager, @Nullable PhoneAccountHandle accountHandle, @Nullable String number)172     public static boolean isVoiceMailNumber(@Nullable TelecomManager telecomManager,
173             @Nullable PhoneAccountHandle accountHandle, @Nullable String number) {
174         if (telecomManager != null && (CompatUtils.isMarshmallowCompatible()
175                 || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "isVoiceMailNumber",
176                         PhoneAccountHandle.class, String.class))) {
177             return telecomManager.isVoiceMailNumber(accountHandle, number);
178         }
179         return PhoneNumberUtils.isVoiceMailNumber(number);
180     }
181 
182     /**
183      * Return the {@link PhoneAccount} for a specified {@link PhoneAccountHandle}. Object includes
184      * resources which can be used in a user interface.
185      *
186      * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
187      * @param account The {@link PhoneAccountHandle}.
188      * @return The {@link PhoneAccount} object or null if it doesn't exist.
189      */
190     @Nullable
getPhoneAccount(@ullable TelecomManager telecomManager, @Nullable PhoneAccountHandle accountHandle)191     public static PhoneAccount getPhoneAccount(@Nullable TelecomManager telecomManager,
192             @Nullable PhoneAccountHandle accountHandle) {
193         if (telecomManager != null && (CompatUtils.isMethodAvailable(
194                 TELECOM_MANAGER_CLASS, "getPhoneAccount", PhoneAccountHandle.class))) {
195             return telecomManager.getPhoneAccount(accountHandle);
196         }
197         return null;
198     }
199 
200     /**
201      * Return the voicemail number for a given phone account.
202      *
203      * @param telecomManager The {@link TelecomManager} object to use for retrieving the voicemail
204      * number if accountHandle is specified.
205      * @param telephonyManager The {@link TelephonyManager} object to use for retrieving the
206      * voicemail number if accountHandle is null.
207      * @param accountHandle The handle for the phone account.
208      * @return The voicemail number for the phone account, and {@code null} if one has not been
209      *         configured.
210      */
211     @Nullable
getVoiceMailNumber(@ullable TelecomManager telecomManager, @Nullable TelephonyManager telephonyManager, @Nullable PhoneAccountHandle accountHandle)212     public static String getVoiceMailNumber(@Nullable TelecomManager telecomManager,
213             @Nullable TelephonyManager telephonyManager,
214             @Nullable PhoneAccountHandle accountHandle) {
215         if (telecomManager != null && (CompatUtils.isMethodAvailable(
216                 TELECOM_MANAGER_CLASS, "getVoiceMailNumber", PhoneAccountHandle.class))) {
217             return telecomManager.getVoiceMailNumber(accountHandle);
218         } else if (telephonyManager != null){
219             return telephonyManager.getVoiceMailNumber();
220         }
221         return null;
222     }
223 
224     /**
225      * Processes the specified dial string as an MMI code.
226      * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#".
227      * Some of these sequences launch special behavior through handled by Telephony.
228      *
229      * @param telecomManager The {@link TelecomManager} object to use for handling MMI.
230      * @param dialString The digits to dial.
231      * @return {@code true} if the digits were processed as an MMI code, {@code false} otherwise.
232      */
handleMmi(@ullable TelecomManager telecomManager, @Nullable String dialString, @Nullable PhoneAccountHandle accountHandle)233     public static boolean handleMmi(@Nullable TelecomManager telecomManager,
234             @Nullable String dialString, @Nullable PhoneAccountHandle accountHandle) {
235         if (telecomManager == null || TextUtils.isEmpty(dialString)) {
236             return false;
237         }
238         if (CompatUtils.isMarshmallowCompatible()) {
239             return telecomManager.handleMmi(dialString, accountHandle);
240         }
241 
242         Object handleMmiResult = CompatUtils.invokeMethod(
243                 telecomManager,
244                 "handleMmi",
245                 new Class<?>[] {PhoneAccountHandle.class, String.class},
246                 new Object[] {accountHandle, dialString});
247         if (handleMmiResult != null) {
248             return (boolean) handleMmiResult;
249         }
250 
251         return telecomManager.handleMmi(dialString);
252     }
253 
254     /**
255      * Silences the ringer if a ringing call exists. Noop if {@link TelecomManager#silenceRinger()}
256      * is unavailable.
257      *
258      * @param telecomManager the TelecomManager to use to silence the ringer.
259      */
silenceRinger(@ullable TelecomManager telecomManager)260     public static void silenceRinger(@Nullable TelecomManager telecomManager) {
261         if (telecomManager != null && (CompatUtils.isMarshmallowCompatible() || CompatUtils
262                 .isMethodAvailable(TELECOM_MANAGER_CLASS, "silenceRinger"))) {
263             telecomManager.silenceRinger();
264         }
265     }
266 
267     /**
268      * Returns the current SIM call manager. Apps must be prepared for this method to return null,
269      * indicating that there currently exists no registered SIM call manager.
270      *
271      * @param telecomManager the {@link TelecomManager} to use to fetch the SIM call manager.
272      * @return The phone account handle of the current sim call manager.
273      */
274     @Nullable
getSimCallManager(TelecomManager telecomManager)275     public static PhoneAccountHandle getSimCallManager(TelecomManager telecomManager) {
276         if (telecomManager != null && (CompatUtils.isMarshmallowCompatible() || CompatUtils
277                 .isMethodAvailable(TELECOM_MANAGER_CLASS, "getSimCallManager"))) {
278             return telecomManager.getSimCallManager();
279         }
280         return null;
281     }
282 }
283