110e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon/* 210e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * Copyright (C) 2013 The Android Open Source Project 310e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * 410e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License"); 510e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * you may not use this file except in compliance with the License. 610e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * You may obtain a copy of the License at 710e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * 810e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * http://www.apache.org/licenses/LICENSE-2.0 910e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * 1010e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * Unless required by applicable law or agreed to in writing, software 1110e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS, 1210e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1310e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * See the License for the specific language governing permissions and 1410e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * limitations under the License. 1510e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon */ 1610e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon 178d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadpackage com.android.server.telecom.components; 1810e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon 198d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadimport com.android.server.telecom.CallIntentProcessor; 208d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadimport com.android.server.telecom.R; 218d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadimport com.android.server.telecom.TelephonyUtil; 2224b10bebff4939daeabef78e906ee447212b0c5aTony Makimport com.android.server.telecom.UserUtil; 23d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shankaimport com.android.settingslib.RestrictedLockUtils; 24d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shankaimport com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 2578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad 265dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Leeimport android.app.AppOpsManager; 27cce5deb2bc998d6385152292153a9423f5206c28Yorke Leeimport android.content.Context; 2810e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordonimport android.content.Intent; 295dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Leeimport android.content.pm.PackageManager; 300d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chenimport android.net.Uri; 315070b0da14bd2da6f68a1ba011f9125fb9d193c5Santos Cordonimport android.os.UserHandle; 3235bcc89cddc7bbcf891454059bf78cd5f35da0a7Yorke Leeimport android.os.UserManager; 334e4ed74f1c29ede44450f78354755bfabfb1fc4fYorke Leeimport android.telecom.DefaultDialerManager; 34a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Log; 357cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccount; 367cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.TelecomManager; 37d240fe8e16205623eb6cb73c3d42448554690033Rekha Kumarimport android.telecom.VideoProfile; 380d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chenimport android.telephony.PhoneNumberUtils; 39cce5deb2bc998d6385152292153a9423f5206c28Yorke Leeimport android.text.TextUtils; 4035bcc89cddc7bbcf891454059bf78cd5f35da0a7Yorke Leeimport android.widget.Toast; 4110e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon 4291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R; 4391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn 4410e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon/** 4578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * Handles system CALL actions and forwards them to {@link CallIntentProcessor}. 4610e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon * Handles all three CALL action types: CALL, CALL_PRIVILEGED, and CALL_EMERGENCY. 47cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee * 48cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee * Pre-L, the only way apps were were allowed to make outgoing emergency calls was the 49cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee * ACTION_CALL_PRIVILEGED action (which requires the system only CALL_PRIVILEGED permission). 50cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee * 51cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee * In L, any app that has the CALL_PRIVILEGED permission can continue to make outgoing emergency 52cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee * calls via ACTION_CALL_PRIVILEGED. 53cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee * 545070b0da14bd2da6f68a1ba011f9125fb9d193c5Santos Cordon * In addition, the default dialer (identified via 5581050722a5236234e5a127f30a139f0238d316edYorke Lee * {@link android.telecom.TelecomManager#getDefaultDialerPackage()} will also be granted the 5681050722a5236234e5a127f30a139f0238d316edYorke Lee * ability to make emergency outgoing calls using the CALL action. In order to do this, it must 5781050722a5236234e5a127f30a139f0238d316edYorke Lee * use the {@link TelecomManager#placeCall(Uri, android.os.Bundle)} method to allow its package 5881050722a5236234e5a127f30a139f0238d316edYorke Lee * name to be passed to {@link UserCallIntentProcessor}. Calling startActivity will continue to 5981050722a5236234e5a127f30a139f0238d316edYorke Lee * work on all non-emergency numbers just like it did pre-L. 6010e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon */ 6178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadpublic class UserCallIntentProcessor { 6210e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon 6378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad private final Context mContext; 64b3feab5a6ad30161726cf2decf4c0b06a78f5d41Yorke Lee private final UserHandle mUserHandle; 6510e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon 66b3feab5a6ad30161726cf2decf4c0b06a78f5d41Yorke Lee public UserCallIntentProcessor(Context context, UserHandle userHandle) { 6778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad mContext = context; 68b3feab5a6ad30161726cf2decf4c0b06a78f5d41Yorke Lee mUserHandle = userHandle; 6910e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon } 7010e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon 7110e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon /** 72523f6058d49238c46b740cb65535710831215a45Santos Cordon * Processes intents sent to the activity. 73523f6058d49238c46b740cb65535710831215a45Santos Cordon * 74523f6058d49238c46b740cb65535710831215a45Santos Cordon * @param intent The intent. 75523f6058d49238c46b740cb65535710831215a45Santos Cordon */ 76cf497c9f72d3f7bac609ca6d5a64ddf2e28f6dbeYorke Lee public void processIntent(Intent intent, String callingPackageName, 77cf497c9f72d3f7bac609ca6d5a64ddf2e28f6dbeYorke Lee boolean canCallNonEmergency) { 788ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn // Ensure call intents are not processed on devices that are not capable of calling. 795070b0da14bd2da6f68a1ba011f9125fb9d193c5Santos Cordon if (!isVoiceCapable()) { 808ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn return; 818ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn } 828ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn 83523f6058d49238c46b740cb65535710831215a45Santos Cordon String action = intent.getAction(); 84523f6058d49238c46b740cb65535710831215a45Santos Cordon 85523f6058d49238c46b740cb65535710831215a45Santos Cordon if (Intent.ACTION_CALL.equals(action) || 86523f6058d49238c46b740cb65535710831215a45Santos Cordon Intent.ACTION_CALL_PRIVILEGED.equals(action) || 87523f6058d49238c46b740cb65535710831215a45Santos Cordon Intent.ACTION_CALL_EMERGENCY.equals(action)) { 88cf497c9f72d3f7bac609ca6d5a64ddf2e28f6dbeYorke Lee processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency); 8939d94c1b821e7da3a551f487b052ee347e3377a7Yorke Lee } 9039d94c1b821e7da3a551f487b052ee347e3377a7Yorke Lee } 9139d94c1b821e7da3a551f487b052ee347e3377a7Yorke Lee 925dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee private void processOutgoingCallIntent(Intent intent, String callingPackageName, 93cf497c9f72d3f7bac609ca6d5a64ddf2e28f6dbeYorke Lee boolean canCallNonEmergency) { 94d75fabf9b3787b851a29e1396d9525706c11864dNancy Chen Uri handle = intent.getData(); 95d75fabf9b3787b851a29e1396d9525706c11864dNancy Chen String scheme = handle.getScheme(); 96d75fabf9b3787b851a29e1396d9525706c11864dNancy Chen String uriString = handle.getSchemeSpecificPart(); 97d75fabf9b3787b851a29e1396d9525706c11864dNancy Chen 9856a76b79e2a03eb0fe070d3ef17e474ae27bb6f3Jay Shrauner if (!PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) { 99d75fabf9b3787b851a29e1396d9525706c11864dNancy Chen handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(uriString) ? 10056a76b79e2a03eb0fe070d3ef17e474ae27bb6f3Jay Shrauner PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, uriString, null); 101d75fabf9b3787b851a29e1396d9525706c11864dNancy Chen } 10235bcc89cddc7bbcf891454059bf78cd5f35da0a7Yorke Lee 10324b10bebff4939daeabef78e906ee447212b0c5aTony Mak // Check DISALLOW_OUTGOING_CALLS restriction. Note: We are skipping this check in a managed 10424b10bebff4939daeabef78e906ee447212b0c5aTony Mak // profile user because this check can always be bypassed by copying and pasting the phone 10524b10bebff4939daeabef78e906ee447212b0c5aTony Mak // number into the personal dialer. 10624b10bebff4939daeabef78e906ee447212b0c5aTony Mak if (!UserUtil.isManagedProfile(mContext, mUserHandle)) { 107d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka // Only emergency calls are allowed for users with the DISALLOW_OUTGOING_CALLS 108d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka // restriction. 109d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka if (!TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) { 110d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka final UserManager userManager = (UserManager) mContext.getSystemService( 111d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka Context.USER_SERVICE); 112d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka if (userManager.hasBaseUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, 113d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka mUserHandle)) { 114d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka showErrorDialogForRestrictedOutgoingCall(mContext, 115d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka R.string.outgoing_call_not_allowed_user_restriction); 116d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka Log.w(this, "Rejecting non-emergency phone call due to DISALLOW_OUTGOING_CALLS " 117d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka + "restriction"); 118d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka return; 119d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka } else if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, 120d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka mUserHandle)) { 121d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, 122d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN); 123d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka return; 124d3b06b720a761677ab3412a40d0f1fc6e328f249Sudheer Shanka } 12524b10bebff4939daeabef78e906ee447212b0c5aTony Mak } 12635bcc89cddc7bbcf891454059bf78cd5f35da0a7Yorke Lee } 12735bcc89cddc7bbcf891454059bf78cd5f35da0a7Yorke Lee 128cf497c9f72d3f7bac609ca6d5a64ddf2e28f6dbeYorke Lee if (!canCallNonEmergency && !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) { 1295dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee showErrorDialogForRestrictedOutgoingCall(mContext, 1305dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee R.string.outgoing_call_not_allowed_no_permission); 1315dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee Log.w(this, "Rejecting non-emergency phone call because " 1325dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee + android.Manifest.permission.CALL_PHONE + " permission is not granted."); 1335dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee return; 1345dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee } 1355dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee 136d240fe8e16205623eb6cb73c3d42448554690033Rekha Kumar int videoState = intent.getIntExtra( 137d240fe8e16205623eb6cb73c3d42448554690033Rekha Kumar TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, 1385b8824979e929250a46791c785b8459512236585Tyler Gunn VideoProfile.STATE_AUDIO_ONLY); 139d240fe8e16205623eb6cb73c3d42448554690033Rekha Kumar Log.d(this, "processOutgoingCallIntent videoState = " + videoState); 140d240fe8e16205623eb6cb73c3d42448554690033Rekha Kumar 14181050722a5236234e5a127f30a139f0238d316edYorke Lee intent.putExtra(CallIntentProcessor.KEY_IS_PRIVILEGED_DIALER, 14281050722a5236234e5a127f30a139f0238d316edYorke Lee isDefaultOrSystemDialer(callingPackageName)); 143578a4e6661fc1be20d164458acb335356d742f72Tony Mak 144578a4e6661fc1be20d164458acb335356d742f72Tony Mak // Save the user handle of current user before forwarding the intent to primary user. 145578a4e6661fc1be20d164458acb335356d742f72Tony Mak intent.putExtra(CallIntentProcessor.KEY_INITIATING_USER, mUserHandle); 146578a4e6661fc1be20d164458acb335356d742f72Tony Mak 1479b71ea8289cb3c6e14beb11f7707ae3ef4dfe83fYorke Lee sendBroadcastToReceiver(intent); 14810e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon } 149523f6058d49238c46b740cb65535710831215a45Santos Cordon 15081050722a5236234e5a127f30a139f0238d316edYorke Lee private boolean isDefaultOrSystemDialer(String callingPackageName) { 15178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad if (TextUtils.isEmpty(callingPackageName)) { 152cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee return false; 153cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee } 154cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee 1554e4ed74f1c29ede44450f78354755bfabfb1fc4fYorke Lee final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext, 1564e4ed74f1c29ede44450f78354755bfabfb1fc4fYorke Lee mUserHandle.getIdentifier()); 1574e4ed74f1c29ede44450f78354755bfabfb1fc4fYorke Lee if (TextUtils.equals(defaultDialer, callingPackageName)) { 15881050722a5236234e5a127f30a139f0238d316edYorke Lee return true; 15981050722a5236234e5a127f30a139f0238d316edYorke Lee } 16081050722a5236234e5a127f30a139f0238d316edYorke Lee 1614e4ed74f1c29ede44450f78354755bfabfb1fc4fYorke Lee final TelecomManager telecomManager = 1624e4ed74f1c29ede44450f78354755bfabfb1fc4fYorke Lee (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 16381050722a5236234e5a127f30a139f0238d316edYorke Lee return TextUtils.equals(telecomManager.getSystemDialerPackage(), callingPackageName); 164cce5deb2bc998d6385152292153a9423f5206c28Yorke Lee } 1658ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn 1668ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn /** 1678ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn * Returns whether the device is voice-capable (e.g. a phone vs a tablet). 1688ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn * 1698ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn * @return {@code True} if the device is voice-capable. 1708ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn */ 1718ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn private boolean isVoiceCapable() { 17278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad return mContext.getApplicationContext().getResources().getBoolean( 1738ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn com.android.internal.R.bool.config_voice_capable); 1748ad2d8d82922bcb14c1a12a6055342b2fd414bcbTyler Gunn } 175d7255872e2204a074bc5dfb5dceb4da13574864cYorke Lee 1765070b0da14bd2da6f68a1ba011f9125fb9d193c5Santos Cordon /** 1776dc1c75ff9fbabce11540c2bbe3972159899b414Yorke Lee * Trampolines the intent to the broadcast receiver that runs only as the primary user. 1785070b0da14bd2da6f68a1ba011f9125fb9d193c5Santos Cordon */ 1799b71ea8289cb3c6e14beb11f7707ae3ef4dfe83fYorke Lee private boolean sendBroadcastToReceiver(Intent intent) { 18078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false); 181c0670ffdc003c43f78f5fc7034f02a3e7fef5753Andrew Lee intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 18278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad intent.setClass(mContext, PrimaryCallReceiver.class); 1839b71ea8289cb3c6e14beb11f7707ae3ef4dfe83fYorke Lee Log.d(this, "Sending broadcast as user to CallReceiver"); 18464196864859c3b46502002edacc235fc83f4aa32Xiaohui Chen mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM); 1856dc1c75ff9fbabce11540c2bbe3972159899b414Yorke Lee return true; 1865070b0da14bd2da6f68a1ba011f9125fb9d193c5Santos Cordon } 187b3feab5a6ad30161726cf2decf4c0b06a78f5d41Yorke Lee 1885dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee private static void showErrorDialogForRestrictedOutgoingCall(Context context, int stringId) { 189b3feab5a6ad30161726cf2decf4c0b06a78f5d41Yorke Lee final Intent intent = new Intent(context, ErrorDialogActivity.class); 190b3feab5a6ad30161726cf2decf4c0b06a78f5d41Yorke Lee intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1915dc42ee62c21ee81d51a411a0cfb61653fdf2858Yorke Lee intent.putExtra(ErrorDialogActivity.ERROR_MESSAGE_ID_EXTRA, stringId); 192b3feab5a6ad30161726cf2decf4c0b06a78f5d41Yorke Lee context.startActivityAsUser(intent, UserHandle.CURRENT); 193b3feab5a6ad30161726cf2decf4c0b06a78f5d41Yorke Lee } 19410e68320fe1dc8270601c442cf47fdb94edc151dSantos Cordon} 195