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