Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c90c974 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Permit system dialer callscreeningservice to access sip invite.

Similar to how the system dialer can use Connection#EXTRA_SIP_INVITE,
adding the ability for the callscreeningservice which is implemented by
the system dialer to also access this extra key value.

Test: Added new unit tests
Bug: 132122961
Change-Id: I402c8c0bfd39322820c65787e24f2f6df842e7c7
parent e8a85b76
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -123,8 +122,10 @@ public class CallScreeningServiceHelper {
                Log.continueSession(mLoggingSession, "CSSH.oSC");
                try {
                    try {
                        // Note: for outgoing calls, never include the restricted extras.
                        screeningService.screenCall(new CallScreeningAdapter(),
                                mParcelableCallUtilsConverter.toParcelableCallForScreening(mCall));
                                mParcelableCallUtilsConverter.toParcelableCallForScreening(mCall,
                                        false /* areRestrictedExtrasIncluded */));
                    } catch (RemoteException e) {
                        Log.w(CallScreeningServiceHelper.this,
                                "Cancelling call id due to remote exception");
+54 −5
Original line number Diff line number Diff line
@@ -52,6 +52,17 @@ public class ParcelableCallUtils {
        EXTRA_KEYS_TO_SANITIZE.add(android.telecom.Connection.EXTRA_SIP_INVITE);
    }

    /**
     * A list of extra keys which should be added to {@link ParcelableCall} when it is being
     * generated for the purpose of sending to a CallScreeningService which has access to these
     * restricted keys.
     */
    private static List<String> RESTRICTED_CALL_SCREENING_EXTRA_KEYS;
    static {
        RESTRICTED_CALL_SCREENING_EXTRA_KEYS = new ArrayList<>();
        RESTRICTED_CALL_SCREENING_EXTRA_KEYS.add(android.telecom.Connection.EXTRA_SIP_INVITE);
    }

    public static class Converter {
        public ParcelableCall toParcelableCall(Call call, boolean includeVideoProvider,
                PhoneAccountRegistrar phoneAccountRegistrar) {
@@ -59,8 +70,10 @@ public class ParcelableCallUtils {
                    call, includeVideoProvider, phoneAccountRegistrar, false, false, false);
        }

        public ParcelableCall toParcelableCallForScreening(Call call) {
            return ParcelableCallUtils.toParcelableCallForScreening(call);
        public ParcelableCall toParcelableCallForScreening(Call call,
                boolean areRestrictedExtrasIncluded) {
            return ParcelableCallUtils.toParcelableCallForScreening(call,
                    areRestrictedExtrasIncluded);
        }
    }

@@ -256,10 +269,17 @@ public class ParcelableCallUtils {
     *     <li>Handle (phone number) presentation</li>
     * </ul>
     * All other fields are nulled or set to 0 values.
     * Where the call screening service is part of the system dialer, the
     * {@link Connection#EXTRA_SIP_INVITE} header information is also sent to the call screening
     * service (since the system dialer has access to this anyways).
     * @param call The telecom call to send to a call screening service.
     * @param areRestrictedExtrasIncluded {@code true} if the set of restricted extras defined in
     *                                    {@link #RESTRICTED_CALL_SCREENING_EXTRA_KEYS} are to
     *                                    be included in the parceled call, {@code false} otherwise.
     * @return Minimal {@link ParcelableCall} to send to the call screening service.
     */
    public static ParcelableCall toParcelableCallForScreening(Call call) {
    public static ParcelableCall toParcelableCallForScreening(Call call,
            boolean areRestrictedExtrasIncluded) {
        Uri handle = call.getHandlePresentation() == TelecomManager.PRESENTATION_ALLOWED ?
                call.getHandle() : null;
        int callDirection;
@@ -270,6 +290,13 @@ public class ParcelableCallUtils {
        } else {
            callDirection = DIRECTION_OUTGOING;
        }
        Bundle callExtras;
        if (areRestrictedExtrasIncluded) {
            callExtras = sanitizeRestrictedCallExtras(call.getExtras());
        } else {
            callExtras = new Bundle();
        }

        return new ParcelableCall(
                call.getId(),
                getParcelableState(call, false /* supportsExternalCalls */),
@@ -295,7 +322,7 @@ public class ParcelableCallUtils {
                0, /* videoState */
                Collections.emptyList(), /* conferenceableCallIds */
                null, /* intentExtras */
                null, /* callExtras */
                callExtras, /* callExtras */
                call.getCreationTimeMillis(),
                callDirection);
    }
@@ -303,7 +330,7 @@ public class ParcelableCallUtils {
    /**
     * Sanitize the extras bundle passed in, removing keys which should not be sent to non-system
     * dialer apps.
     * @param extras Extras bundle to sanitize.
     * @param oldExtras Extras bundle to sanitize.
     * @return The sanitized extras bundle.
     */
    private static Bundle sanitizeExtras(Bundle oldExtras) {
@@ -326,6 +353,28 @@ public class ParcelableCallUtils {
        return extras;
    }

    /**
     * Sanitize the extras bundle passed in, removing keys which should not be sent to call
     * screening services which have access to the restricted extras.
     * @param oldExtras Extras bundle to sanitize.
     * @return The sanitized extras bundle.
     */
    private static Bundle sanitizeRestrictedCallExtras(Bundle oldExtras) {
        if (oldExtras == null) {
            return new Bundle();
        }
        Bundle extras = new Bundle(oldExtras);
        Iterator<String> toCheck = extras.keySet().iterator();
        while (toCheck.hasNext()) {
            String extraKey = toCheck.next();
            if (TextUtils.isEmpty(extraKey)
                    || !RESTRICTED_CALL_SCREENING_EXTRA_KEYS.contains(extraKey)) {
                toCheck.remove();
            }
        }
        return extras;
    }

    private static int getParcelableState(Call call, boolean supportsExternalCalls) {
        int state = CallState.NEW;
        switch (call.getState()) {
+13 −3
Original line number Diff line number Diff line
@@ -160,7 +160,8 @@ public class CallScreeningServiceController implements IncomingCallFilter.CallFi
            bindDefaultDialerAndUserChosenService();
        } else {
            createCallScreeningServiceFilter().startCallScreeningFilter(mCall, this,
                    carrierPackageName, mAppLabelProxy.getAppLabel(carrierPackageName));
                    carrierPackageName, mAppLabelProxy.getAppLabel(carrierPackageName),
                    CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_CARRIER);
        }

        // Carrier filtering timed out
@@ -178,12 +179,16 @@ public class CallScreeningServiceController implements IncomingCallFilter.CallFi
    private void bindDefaultDialerAndUserChosenService() {
        if (mIsCarrierFinished) {
            String dialerPackageName = getDefaultDialerPackageName();
            String systemDialerPackageName = getSystemDialerPackageName();
            if (TextUtils.isEmpty(dialerPackageName)) {
                mIsDefaultDialerFinished = true;
            } else {
                int dialerType = dialerPackageName.equals(systemDialerPackageName) ?
                        CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_SYSTEM_DIALER :
                        CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_DEFAULT_DIALER;
                createCallScreeningServiceFilter().startCallScreeningFilter(mCall,
                        CallScreeningServiceController.this, dialerPackageName,
                        mAppLabelProxy.getAppLabel(dialerPackageName));
                        mAppLabelProxy.getAppLabel(dialerPackageName), dialerType);
            }

            String userChosenPackageName = getUserChosenPackageName();
@@ -192,7 +197,8 @@ public class CallScreeningServiceController implements IncomingCallFilter.CallFi
            } else {
                createCallScreeningServiceFilter().startCallScreeningFilter(mCall,
                        CallScreeningServiceController.this, userChosenPackageName,
                        mAppLabelProxy.getAppLabel(userChosenPackageName));
                        mAppLabelProxy.getAppLabel(userChosenPackageName),
                        CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
            }

            if (mIsDefaultDialerFinished && mIsUserChosenFinished) {
@@ -257,6 +263,10 @@ public class CallScreeningServiceController implements IncomingCallFilter.CallFi
        return TelecomManager.from(mContext).getDefaultDialerPackage();
    }

    private String getSystemDialerPackageName() {
        return TelecomManager.from(mContext).getSystemDialerPackage();
    }

    private String getUserChosenPackageName() {
        return mCallsManager.getRoleManagerAdapter().getDefaultCallScreeningApp();
    }
+18 −11
Original line number Diff line number Diff line
@@ -16,12 +16,9 @@

package com.android.server.telecom.callfiltering;

import android.Manifest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.IBinder;
import android.os.PersistableBundle;
@@ -29,9 +26,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.CallLog;
import android.provider.Settings;
import android.telecom.CallScreeningService;
import android.telecom.Log;
import android.telecom.ParcelableCall;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.text.TextUtils;
@@ -47,14 +42,17 @@ import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.TelecomServiceImpl.SettingsSecureAdapter;
import com.android.server.telecom.TelecomSystem;

import java.util.List;

/**
 * Binds to {@link ICallScreeningService} to allow call blocking. A single instance of this class
 * handles a single call.
 */
public class CallScreeningServiceFilter {

    public static final int CALL_SCREENING_FILTER_TYPE_USER_SELECTED = 1;
    public static final int CALL_SCREENING_FILTER_TYPE_DEFAULT_DIALER = 2;
    public static final int CALL_SCREENING_FILTER_TYPE_SYSTEM_DIALER = 3;
    public static final int CALL_SCREENING_FILTER_TYPE_CARRIER = 4;

    public interface CallScreeningFilterResultCallback {
        void onCallScreeningFilterComplete(Call call, CallFilteringResult result, String
                packageName);
@@ -194,6 +192,7 @@ public class CallScreeningServiceFilter {
    private String mPackageName;
    private CharSequence mAppName;
    private boolean mHasFinished = false;
    private int mCallScreeningServiceType;

    private CallFilteringResult mResult = new CallFilteringResult(
            true, // shouldAllowCall
@@ -219,7 +218,8 @@ public class CallScreeningServiceFilter {
    public void startCallScreeningFilter(Call call,
            CallScreeningFilterResultCallback callback,
            String packageName,
                                         CharSequence appName) {
            CharSequence appName,
            int callScreeningServiceType) {
        if (mHasFinished) {
            Log.w(this, "Attempting to reuse CallScreeningServiceFilter. Ignoring.");
            return;
@@ -229,6 +229,7 @@ public class CallScreeningServiceFilter {
        mCallback = callback;
        mPackageName = packageName;
        mAppName = appName;
        mCallScreeningServiceType = callScreeningServiceType;

        mConnection = new CallScreeningServiceConnection();
        if (!CallScreeningServiceHelper.bindCallScreeningService(mContext,
@@ -262,9 +263,15 @@ public class CallScreeningServiceFilter {
    private void onServiceBound(ICallScreeningService service) {
        mService = service;
        try {
            boolean isSystemDialer =
                    mCallScreeningServiceType
                            == CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_SYSTEM_DIALER;
            // Important: Only send a minimal subset of the call to the screening service.
            // We will send some of the call extras to the call screening service which the system
            // dialer implements.
            mService.screenCall(new CallScreeningAdapter(),
                    mParcelableCallUtilsConverter.toParcelableCallForScreening(mCall));
                    mParcelableCallUtilsConverter.toParcelableCallForScreening(mCall,
                            isSystemDialer));
        } catch (RemoteException e) {
            Log.e(this, e, "Failed to set the call screening adapter.");
            finishCallScreening();
+22 −12
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Icon;
import android.os.IBinder;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -166,7 +165,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
    @SmallTest
    @Test
    public void testNoPackageName() {
        mFilter.startCallScreeningFilter(mCall, mCallback, null, null);
        mFilter.startCallScreeningFilter(mCall, mCallback, null, null,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(null));
    }

@@ -175,7 +175,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
    public void testNoResolveEntries() {
        when(mPackageManager.queryIntentServicesAsUser(nullable(Intent.class), anyInt(), anyInt()))
                .thenReturn(Collections.emptyList());
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
    }

@@ -183,7 +184,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
    @Test
    public void testBadResolveEntry() {
        mResolveInfo.serviceInfo = null;
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
    }

@@ -191,7 +193,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
    @Test
    public void testPermissionlessFilterService() {
        mResolveInfo.serviceInfo.permission = null;
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
    }

@@ -200,7 +203,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
    public void testContextFailToBind() {
        when(mContext.bindServiceAsUser(nullable(Intent.class), nullable(ServiceConnection.class),
                anyInt(), eq(UserHandle.CURRENT))).thenReturn(false);
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
    }

@@ -209,7 +213,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
    public void testExceptionInScreeningService() throws Exception {
        doThrow(new RemoteException()).when(mCallScreeningService).screenCall(
                nullable(ICallScreeningAdapter.class), nullable(ParcelableCall.class));
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        ServiceConnection serviceConnection = verifyBindingIntent();
        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
@@ -218,7 +223,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
    @SmallTest
    @Test
    public void testAllowCall() throws Exception {
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        ServiceConnection serviceConnection = verifyBindingIntent();
        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
@@ -229,7 +235,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
    @SmallTest
    @Test
    public void testSilenceCall() throws Exception {
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        ServiceConnection serviceConnection = verifyBindingIntent();
        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
@@ -249,7 +256,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {

        mFilter.startCallScreeningFilter(mCall, mCallback,
                CARRIER_DEFINED_CALL_SCREENING.getPackageName(),
                CARRIER_DEFINED_CALL_SCREENING_APP_NAME);
                CARRIER_DEFINED_CALL_SCREENING_APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_CARRIER);
        ServiceConnection serviceConnection = verifyBindingIntent();
        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
@@ -281,7 +289,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {

        mFilter.startCallScreeningFilter(mCall, mCallback,
                DEFAULT_DIALER_CALL_SCREENING.getPackageName(),
                DEFAULT_DIALER_APP_NAME);
                DEFAULT_DIALER_APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_DEFAULT_DIALER);
        ServiceConnection serviceConnection = verifyBindingIntent();
        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
@@ -313,7 +322,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {

        mFilter.startCallScreeningFilter(mCall, mCallback,
                USER_CHOSEN_CALL_SCREENING.getPackageName(),
                USER_CHOSEN_CALL_SCREENING_APP_NAME);
                USER_CHOSEN_CALL_SCREENING_APP_NAME,
                CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
        ServiceConnection serviceConnection = verifyBindingIntent();
        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
Loading