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