Home | History | Annotate | Download | only in util
      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 
     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 
     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 
     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 
     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 
     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
    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 
    123     public static PhoneAccount getPhoneAccount(Context context, PhoneAccountHandle handle) {
    124         return TelecomManagerCompat.getPhoneAccount(getTelecomManager(context), handle);
    125     }
    126 
    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 
    134     public static boolean isInCall(Context context) {
    135         if (hasReadPhoneStatePermission(context)) {
    136             return getTelecomManager(context).isInCall();
    137         }
    138         return false;
    139     }
    140 
    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
    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      */
    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 
    176     public static Uri getCallLogUri(Context context) {
    177         return hasReadWriteVoicemailPermissions(context) ? Calls.CONTENT_URI_WITH_VOICEMAIL
    178                 : Calls.CONTENT_URI;
    179     }
    180 
    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 
    187     public static boolean hasModifyPhoneStatePermission(Context context) {
    188         return isDefaultDialer(context)
    189                 || hasPermission(context, Manifest.permission.MODIFY_PHONE_STATE);
    190     }
    191 
    192     public static boolean hasReadPhoneStatePermission(Context context) {
    193         return isDefaultDialer(context)
    194                 || hasPermission(context, Manifest.permission.READ_PHONE_STATE);
    195     }
    196 
    197     public static boolean hasCallPhonePermission(Context context) {
    198         return isDefaultDialer(context)
    199                 || hasPermission(context, Manifest.permission.CALL_PHONE);
    200     }
    201 
    202     private static boolean hasPermission(Context context, String permission) {
    203         return ContextCompat.checkSelfPermission(context, permission)
    204                 == PackageManager.PERMISSION_GRANTED;
    205     }
    206 
    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 
    222     private static TelecomManager getTelecomManager(Context context) {
    223         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
    224     }
    225 
    226     private static TelephonyManager getTelephonyManager(Context context) {
    227         return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    228     }
    229 }
    230