Home | History | Annotate | Download | only in components
      1 /*
      2  * Copyright (C) 2013 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.server.telecom.components;
     18 
     19 import com.android.server.telecom.CallIntentProcessor;
     20 import com.android.server.telecom.R;
     21 import com.android.server.telecom.TelephonyUtil;
     22 import com.android.server.telecom.UserUtil;
     23 import com.android.settingslib.RestrictedLockUtils;
     24 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
     25 
     26 import android.app.AppOpsManager;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.content.pm.PackageManager;
     30 import android.net.Uri;
     31 import android.os.UserHandle;
     32 import android.os.UserManager;
     33 import android.telecom.DefaultDialerManager;
     34 import android.telecom.Log;
     35 import android.telecom.PhoneAccount;
     36 import android.telecom.TelecomManager;
     37 import android.telecom.VideoProfile;
     38 import android.telephony.PhoneNumberUtils;
     39 import android.text.TextUtils;
     40 import android.widget.Toast;
     41 
     42 // TODO: Needed for move to system service: import com.android.internal.R;
     43 
     44 /**
     45  * Handles system CALL actions and forwards them to {@link CallIntentProcessor}.
     46  * Handles all three CALL action types: CALL, CALL_PRIVILEGED, and CALL_EMERGENCY.
     47  *
     48  * Pre-L, the only way apps were were allowed to make outgoing emergency calls was the
     49  * ACTION_CALL_PRIVILEGED action (which requires the system only CALL_PRIVILEGED permission).
     50  *
     51  * In L, any app that has the CALL_PRIVILEGED permission can continue to make outgoing emergency
     52  * calls via ACTION_CALL_PRIVILEGED.
     53  *
     54  * In addition, the default dialer (identified via
     55  * {@link android.telecom.TelecomManager#getDefaultDialerPackage()} will also be granted the
     56  * ability to make emergency outgoing calls using the CALL action. In order to do this, it must
     57  * use the {@link TelecomManager#placeCall(Uri, android.os.Bundle)} method to allow its package
     58  * name to be passed to {@link UserCallIntentProcessor}. Calling startActivity will continue to
     59  * work on all non-emergency numbers just like it did pre-L.
     60  */
     61 public class UserCallIntentProcessor {
     62 
     63     private final Context mContext;
     64     private final UserHandle mUserHandle;
     65 
     66     public UserCallIntentProcessor(Context context, UserHandle userHandle) {
     67         mContext = context;
     68         mUserHandle = userHandle;
     69     }
     70 
     71     /**
     72      * Processes intents sent to the activity.
     73      *
     74      * @param intent The intent.
     75      */
     76     public void processIntent(Intent intent, String callingPackageName,
     77             boolean canCallNonEmergency) {
     78         // Ensure call intents are not processed on devices that are not capable of calling.
     79         if (!isVoiceCapable()) {
     80             return;
     81         }
     82 
     83         String action = intent.getAction();
     84 
     85         if (Intent.ACTION_CALL.equals(action) ||
     86                 Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
     87                 Intent.ACTION_CALL_EMERGENCY.equals(action)) {
     88             processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency);
     89         }
     90     }
     91 
     92     private void processOutgoingCallIntent(Intent intent, String callingPackageName,
     93             boolean canCallNonEmergency) {
     94         Uri handle = intent.getData();
     95         String scheme = handle.getScheme();
     96         String uriString = handle.getSchemeSpecificPart();
     97 
     98         if (!PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) {
     99             handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(uriString) ?
    100                     PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, uriString, null);
    101         }
    102 
    103         // Check DISALLOW_OUTGOING_CALLS restriction. Note: We are skipping this check in a managed
    104         // profile user because this check can always be bypassed by copying and pasting the phone
    105         // number into the personal dialer.
    106         if (!UserUtil.isManagedProfile(mContext, mUserHandle)) {
    107             // Only emergency calls are allowed for users with the DISALLOW_OUTGOING_CALLS
    108             // restriction.
    109             if (!TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
    110                 final UserManager userManager = (UserManager) mContext.getSystemService(
    111                         Context.USER_SERVICE);
    112                 if (userManager.hasBaseUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
    113                         mUserHandle)) {
    114                     showErrorDialogForRestrictedOutgoingCall(mContext,
    115                             R.string.outgoing_call_not_allowed_user_restriction);
    116                     Log.w(this, "Rejecting non-emergency phone call due to DISALLOW_OUTGOING_CALLS "
    117                             + "restriction");
    118                     return;
    119                 } else if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
    120                         mUserHandle)) {
    121                     RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext,
    122                             EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN);
    123                     return;
    124                 }
    125             }
    126         }
    127 
    128         if (!canCallNonEmergency && !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
    129             showErrorDialogForRestrictedOutgoingCall(mContext,
    130                     R.string.outgoing_call_not_allowed_no_permission);
    131             Log.w(this, "Rejecting non-emergency phone call because "
    132                     + android.Manifest.permission.CALL_PHONE + " permission is not granted.");
    133             return;
    134         }
    135 
    136         int videoState = intent.getIntExtra(
    137                 TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
    138                 VideoProfile.STATE_AUDIO_ONLY);
    139         Log.d(this, "processOutgoingCallIntent videoState = " + videoState);
    140 
    141         intent.putExtra(CallIntentProcessor.KEY_IS_PRIVILEGED_DIALER,
    142                 isDefaultOrSystemDialer(callingPackageName));
    143 
    144         // Save the user handle of current user before forwarding the intent to primary user.
    145         intent.putExtra(CallIntentProcessor.KEY_INITIATING_USER, mUserHandle);
    146 
    147         sendBroadcastToReceiver(intent);
    148     }
    149 
    150     private boolean isDefaultOrSystemDialer(String callingPackageName) {
    151         if (TextUtils.isEmpty(callingPackageName)) {
    152             return false;
    153         }
    154 
    155         final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext,
    156                 mUserHandle.getIdentifier());
    157         if (TextUtils.equals(defaultDialer, callingPackageName)) {
    158             return true;
    159         }
    160 
    161         final TelecomManager telecomManager =
    162                 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
    163         return TextUtils.equals(telecomManager.getSystemDialerPackage(), callingPackageName);
    164     }
    165 
    166     /**
    167      * Returns whether the device is voice-capable (e.g. a phone vs a tablet).
    168      *
    169      * @return {@code True} if the device is voice-capable.
    170      */
    171     private boolean isVoiceCapable() {
    172         return mContext.getApplicationContext().getResources().getBoolean(
    173                 com.android.internal.R.bool.config_voice_capable);
    174     }
    175 
    176     /**
    177      * Trampolines the intent to the broadcast receiver that runs only as the primary user.
    178      */
    179     private boolean sendBroadcastToReceiver(Intent intent) {
    180         intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false);
    181         intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
    182         intent.setClass(mContext, PrimaryCallReceiver.class);
    183         Log.d(this, "Sending broadcast as user to CallReceiver");
    184         mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
    185         return true;
    186     }
    187 
    188     private static void showErrorDialogForRestrictedOutgoingCall(Context context, int stringId) {
    189         final Intent intent = new Intent(context, ErrorDialogActivity.class);
    190         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    191         intent.putExtra(ErrorDialogActivity.ERROR_MESSAGE_ID_EXTRA, stringId);
    192         context.startActivityAsUser(intent, UserHandle.CURRENT);
    193     }
    194 }
    195