• 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.util;
18 
19 import android.Manifest;
20 import android.app.Activity;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.PackageManager;
24 import android.net.Uri;
25 import android.provider.CallLog.Calls;
26 import android.support.annotation.Nullable;
27 import android.support.v4.content.ContextCompat;
28 import android.telecom.PhoneAccount;
29 import android.telecom.PhoneAccountHandle;
30 import android.telecom.TelecomManager;
31 import android.telephony.PhoneNumberUtils;
32 import android.telephony.TelephonyManager;
33 import android.text.TextUtils;
34 import android.util.Log;
35 
36 import com.android.contacts.common.compat.CompatUtils;
37 import com.android.contacts.common.compat.telecom.TelecomManagerCompat;
38 import com.android.dialer.compat.DialerCompatUtils;
39 
40 import java.util.ArrayList;
41 import java.util.List;
42 
43 /**
44  * Performs permission checks before calling into TelecomManager. Each method is self-explanatory -
45  * perform the required check and return the fallback default if the permission is missing,
46  * otherwise return the value from TelecomManager.
47  *
48  */
49 public class TelecomUtil {
50     private static final String TAG = "TelecomUtil";
51     private static boolean sWarningLogged = false;
52 
showInCallScreen(Context context, boolean showDialpad)53     public static void showInCallScreen(Context context, boolean showDialpad) {
54         if (hasReadPhoneStatePermission(context)) {
55             try {
56                 getTelecomManager(context).showInCallScreen(showDialpad);
57             } catch (SecurityException e) {
58                 // Just in case
59                 Log.w(TAG, "TelecomManager.showInCallScreen called without permission.");
60             }
61         }
62     }
63 
silenceRinger(Context context)64     public static void silenceRinger(Context context) {
65         if (hasModifyPhoneStatePermission(context)) {
66             try {
67                 TelecomManagerCompat.silenceRinger(getTelecomManager(context));
68             } catch (SecurityException e) {
69                 // Just in case
70                 Log.w(TAG, "TelecomManager.silenceRinger called without permission.");
71             }
72         }
73     }
74 
cancelMissedCallsNotification(Context context)75     public static void cancelMissedCallsNotification(Context context) {
76         if (hasModifyPhoneStatePermission(context)) {
77             try {
78                 getTelecomManager(context).cancelMissedCallsNotification();
79             } catch (SecurityException e) {
80                 Log.w(TAG, "TelecomManager.cancelMissedCalls called without permission.");
81             }
82         }
83     }
84 
getAdnUriForPhoneAccount(Context context, PhoneAccountHandle handle)85     public static Uri getAdnUriForPhoneAccount(Context context, PhoneAccountHandle handle) {
86         if (hasModifyPhoneStatePermission(context)) {
87             try {
88                 return TelecomManagerCompat.getAdnUriForPhoneAccount(
89                         getTelecomManager(context), handle);
90             } catch (SecurityException e) {
91                 Log.w(TAG, "TelecomManager.getAdnUriForPhoneAccount called without permission.");
92             }
93         }
94         return null;
95     }
96 
handleMmi(Context context, String dialString, @Nullable PhoneAccountHandle handle)97     public static boolean handleMmi(Context context, String dialString,
98             @Nullable PhoneAccountHandle handle) {
99         if (hasModifyPhoneStatePermission(context)) {
100             try {
101                 if (handle == null) {
102                     return getTelecomManager(context).handleMmi(dialString);
103                 } else {
104                     return getTelecomManager(context).handleMmi(dialString, handle);
105                 }
106             } catch (SecurityException e) {
107                 Log.w(TAG, "TelecomManager.handleMmi called without permission.");
108             }
109         }
110         return false;
111     }
112 
113     @Nullable
getDefaultOutgoingPhoneAccount(Context context, String uriScheme)114     public static PhoneAccountHandle getDefaultOutgoingPhoneAccount(Context context,
115             String uriScheme) {
116         if (hasReadPhoneStatePermission(context)) {
117             return TelecomManagerCompat.getDefaultOutgoingPhoneAccount(
118                     getTelecomManager(context), uriScheme);
119         }
120         return null;
121     }
122 
getPhoneAccount(Context context, PhoneAccountHandle handle)123     public static PhoneAccount getPhoneAccount(Context context, PhoneAccountHandle handle) {
124         return TelecomManagerCompat.getPhoneAccount(getTelecomManager(context), handle);
125     }
126 
getCallCapablePhoneAccounts(Context context)127     public static List<PhoneAccountHandle> getCallCapablePhoneAccounts(Context context) {
128         if (hasReadPhoneStatePermission(context)) {
129             return TelecomManagerCompat.getCallCapablePhoneAccounts(getTelecomManager(context));
130         }
131         return new ArrayList<>();
132     }
133 
isInCall(Context context)134     public static boolean isInCall(Context context) {
135         if (hasReadPhoneStatePermission(context)) {
136             return getTelecomManager(context).isInCall();
137         }
138         return false;
139     }
140 
isVoicemailNumber(Context context, PhoneAccountHandle accountHandle, String number)141     public static boolean isVoicemailNumber(Context context, PhoneAccountHandle accountHandle,
142             String number) {
143         if (hasReadPhoneStatePermission(context)) {
144             return TelecomManagerCompat.isVoiceMailNumber(getTelecomManager(context),
145                     accountHandle, number);
146         }
147         return false;
148     }
149 
150     @Nullable
getVoicemailNumber(Context context, PhoneAccountHandle accountHandle)151     public static String getVoicemailNumber(Context context, PhoneAccountHandle accountHandle) {
152         if (hasReadPhoneStatePermission(context)) {
153             return TelecomManagerCompat.getVoiceMailNumber(getTelecomManager(context),
154                     getTelephonyManager(context), accountHandle);
155         }
156         return null;
157     }
158 
159     /**
160      * Tries to place a call using the {@link TelecomManager}.
161      *
162      * @param activity a valid activity.
163      * @param intent the call intent.
164      *
165      * @return {@code true} if we successfully attempted to place the call, {@code false} if it
166      *         failed due to a permission check.
167      */
placeCall(Activity activity, Intent intent)168     public static boolean placeCall(Activity activity, Intent intent) {
169         if (hasCallPhonePermission(activity)) {
170             TelecomManagerCompat.placeCall(activity, getTelecomManager(activity), intent);
171             return true;
172         }
173         return false;
174     }
175 
getCallLogUri(Context context)176     public static Uri getCallLogUri(Context context) {
177         return hasReadWriteVoicemailPermissions(context) ? Calls.CONTENT_URI_WITH_VOICEMAIL
178                 : Calls.CONTENT_URI;
179     }
180 
hasReadWriteVoicemailPermissions(Context context)181     public static boolean hasReadWriteVoicemailPermissions(Context context) {
182         return isDefaultDialer(context)
183                 || (hasPermission(context, Manifest.permission.READ_VOICEMAIL)
184                         && hasPermission(context, Manifest.permission.WRITE_VOICEMAIL));
185     }
186 
hasModifyPhoneStatePermission(Context context)187     public static boolean hasModifyPhoneStatePermission(Context context) {
188         return isDefaultDialer(context)
189                 || hasPermission(context, Manifest.permission.MODIFY_PHONE_STATE);
190     }
191 
hasReadPhoneStatePermission(Context context)192     public static boolean hasReadPhoneStatePermission(Context context) {
193         return isDefaultDialer(context)
194                 || hasPermission(context, Manifest.permission.READ_PHONE_STATE);
195     }
196 
hasCallPhonePermission(Context context)197     public static boolean hasCallPhonePermission(Context context) {
198         return isDefaultDialer(context)
199                 || hasPermission(context, Manifest.permission.CALL_PHONE);
200     }
201 
hasPermission(Context context, String permission)202     private static boolean hasPermission(Context context, String permission) {
203         return ContextCompat.checkSelfPermission(context, permission)
204                 == PackageManager.PERMISSION_GRANTED;
205     }
206 
isDefaultDialer(Context context)207     public static boolean isDefaultDialer(Context context) {
208         final boolean result = TextUtils.equals(context.getPackageName(),
209                 TelecomManagerCompat.getDefaultDialerPackage(getTelecomManager(context)));
210         if (result) {
211             sWarningLogged = false;
212         } else {
213             if (!sWarningLogged) {
214                 // Log only once to prevent spam.
215                 Log.w(TAG, "Dialer is not currently set to be default dialer");
216                 sWarningLogged = true;
217             }
218         }
219         return result;
220     }
221 
getTelecomManager(Context context)222     private static TelecomManager getTelecomManager(Context context) {
223         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
224     }
225 
getTelephonyManager(Context context)226     private static TelephonyManager getTelephonyManager(Context context) {
227         return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
228     }
229 }
230