diff options
author | Tyler Gunn <tgunn@google.com> | 2019-05-08 13:38:16 -0700 |
---|---|---|
committer | Tyler Gunn <tgunn@google.com> | 2019-05-10 14:46:16 -0700 |
commit | 2c90c974fcd216680f31bdfbeb7ff2bf4a6c9b93 (patch) | |
tree | e81666de77b48bbe13ee91dffd22bd180077209b | |
parent | e8a85b76a057536c02aceae6b6c44f37e3602c00 (diff) | |
download | android_packages_services_Telecomm-2c90c974fcd216680f31bdfbeb7ff2bf4a6c9b93.tar.gz android_packages_services_Telecomm-2c90c974fcd216680f31bdfbeb7ff2bf4a6c9b93.tar.bz2 android_packages_services_Telecomm-2c90c974fcd216680f31bdfbeb7ff2bf4a6c9b93.zip |
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
6 files changed, 136 insertions, 33 deletions
diff --git a/src/com/android/server/telecom/CallScreeningServiceHelper.java b/src/com/android/server/telecom/CallScreeningServiceHelper.java index 82ee3c76..a9341ab8 100644 --- a/src/com/android/server/telecom/CallScreeningServiceHelper.java +++ b/src/com/android/server/telecom/CallScreeningServiceHelper.java @@ -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"); diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java index b936504d..6a66ccf4 100644 --- a/src/com/android/server/telecom/ParcelableCallUtils.java +++ b/src/com/android/server/telecom/ParcelableCallUtils.java @@ -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()) { diff --git a/src/com/android/server/telecom/callfiltering/CallScreeningServiceController.java b/src/com/android/server/telecom/callfiltering/CallScreeningServiceController.java index b72ac0bd..5b1971e5 100644 --- a/src/com/android/server/telecom/callfiltering/CallScreeningServiceController.java +++ b/src/com/android/server/telecom/callfiltering/CallScreeningServiceController.java @@ -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(); } diff --git a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java index 755cd5eb..c8ec18a3 100644 --- a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java +++ b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java @@ -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 @@ -217,9 +216,10 @@ public class CallScreeningServiceFilter { } public void startCallScreeningFilter(Call call, - CallScreeningFilterResultCallback callback, - String packageName, - CharSequence appName) { + CallScreeningFilterResultCallback callback, + String packageName, + 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(); diff --git a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java index bab80203..5b47fe94 100644 --- a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java +++ b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java @@ -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(); diff --git a/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java b/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java index 753b6353..3f4a4cdd 100644 --- a/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java +++ b/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java @@ -112,6 +112,32 @@ public class ParcelableCallUtilsTest extends TelecomTestCase { assertTrue(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT)); } + @SmallTest + @Test + public void testParcelForSystemCallScreening() { + mCall.putExtras(Call.SOURCE_CONNECTION_SERVICE, getSomeExtras()); + ParcelableCall call = ParcelableCallUtils.toParcelableCallForScreening(mCall, + true /* isPartOfSystemDialer */); + + Bundle parceledExtras = call.getExtras(); + assertTrue(parceledExtras.containsKey(Connection.EXTRA_SIP_INVITE)); + assertFalse(parceledExtras.containsKey("SomeExtra")); + assertFalse(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT)); + } + + @SmallTest + @Test + public void testParcelForSystemNonSystemCallScreening() { + mCall.putExtras(Call.SOURCE_CONNECTION_SERVICE, getSomeExtras()); + ParcelableCall call = ParcelableCallUtils.toParcelableCallForScreening(mCall, + false /* isPartOfSystemDialer */); + + Bundle parceledExtras = call.getExtras(); + assertFalse(parceledExtras.containsKey(Connection.EXTRA_SIP_INVITE)); + assertFalse(parceledExtras.containsKey("SomeExtra")); + assertFalse(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT)); + } + private Bundle getSomeExtras() { Bundle extras = new Bundle(); extras.putString(Connection.EXTRA_SIP_INVITE, "scary data"); |