Loading src/com/android/server/telecom/CallsManager.java +4 −1 Original line number Diff line number Diff line Loading @@ -2178,7 +2178,10 @@ public class CallsManager extends Call.ListenerBase // is a video call, of if using speaker when docked PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount( call.getTargetPhoneAccount(), call.getInitiatingUser()); boolean allowVideo = account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING); boolean allowVideo = false; if (account != null) { allowVideo = account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING); } call.setStartWithSpeakerphoneOn(speakerphoneOn || (useSpeakerForVideoCall && allowVideo) || (useSpeakerWhenDocked && useSpeakerForDock)); call.setVideoState(videoState); Loading src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java +8 −1 Original line number Diff line number Diff line Loading @@ -196,7 +196,7 @@ public class CallRedirectionProcessor implements CallRedirectionCallback { synchronized (mTelecomLock) { mRedirectionGatewayInfo = mCallRedirectionProcessorHelper .getGatewayInfoFromGatewayUri(mComponentName.getPackageName(), gatewayUri, mDestinationUri); gatewayUri, mDestinationUri, mPostDialDigits); mPhoneAccountHandle = targetPhoneAccount; // If carrier redirects call, we should skip to notify users about // the user-defined call redirection service. Loading Loading @@ -246,6 +246,12 @@ public class CallRedirectionProcessor implements CallRedirectionCallback { */ private Uri mProcessedDestinationUri; /** * The post dial digits which were removed from {@link #mDestinationUri} when determining * {@link #mProcessedDestinationUri}. */ private String mPostDialDigits; /** * Indicates if Telecom should cancel the call when the whole call redirection finishes. */ Loading Loading @@ -293,6 +299,7 @@ public class CallRedirectionProcessor implements CallRedirectionCallback { context, callsManager, phoneAccountRegistrar); mProcessedDestinationUri = mCallRedirectionProcessorHelper.formatNumberForRedirection( mDestinationUri); mPostDialDigits = mCallRedirectionProcessorHelper.getPostDialDigits(mDestinationUri); } @Override Loading src/com/android/server/telecom/callredirection/CallRedirectionProcessorHelper.java +22 −3 Original line number Diff line number Diff line Loading @@ -129,6 +129,18 @@ public class CallRedirectionProcessorHelper { return removePostDialDigits(formatNumberToE164(handle)); } /** * Extras the post dial digits from a given handle. * @param handle The handle * @return The post dial digits. */ public String getPostDialDigits(Uri handle) { if (handle == null) { return ""; } return PhoneNumberUtils.extractPostDialPortion(handle.getSchemeSpecificPart()); } protected Uri formatNumberToE164(Uri handle) { String number = handle.getSchemeSpecificPart(); Loading Loading @@ -163,10 +175,17 @@ public class CallRedirectionProcessorHelper { } } protected GatewayInfo getGatewayInfoFromGatewayUri( String gatewayPackageName, Uri gatewayUri, Uri destinationUri) { public static GatewayInfo getGatewayInfoFromGatewayUri( String gatewayPackageName, Uri gatewayUri, Uri destinationUri, String postdialDigits) { if (!TextUtils.isEmpty(gatewayPackageName) && gatewayUri != null) { return new GatewayInfo(gatewayPackageName, gatewayUri, destinationUri); Uri gatewayWithPostdial = gatewayUri; if (gatewayUri != null && !TextUtils.isEmpty(postdialDigits)) { gatewayWithPostdial = new Uri.Builder() .scheme(gatewayUri.getScheme()) .encodedOpaquePart(gatewayUri.getSchemeSpecificPart() + postdialDigits) .build(); } return new GatewayInfo(gatewayPackageName, gatewayWithPostdial, destinationUri); } return null; } Loading tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java +68 −1 Original line number Diff line number Diff line Loading @@ -23,11 +23,15 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.UserHandle; import android.telecom.GatewayInfo; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; import com.android.internal.telecom.ICallRedirectionAdapter; import com.android.internal.telecom.ICallRedirectionService; import com.android.server.telecom.Call; import com.android.server.telecom.CallsManager; Loading @@ -39,24 +43,30 @@ import com.android.server.telecom.Timeouts; import com.android.server.telecom.callredirection.CallRedirectionProcessor; import com.android.server.telecom.callredirection.CallRedirectionProcessorHelper; import static org.junit.Assert.assertEquals; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.junit.Before; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; @RunWith(JUnit4.class) public class CallRedirectionProcessorTest extends TelecomTestCase { @Mock private Context mContext; Loading @@ -82,6 +92,11 @@ public class CallRedirectionProcessorTest extends TelecomTestCase { @Mock private Timeouts.Adapter mTimeoutsAdapter; private static final Uri ORIGINAL_NUMBER_WITH_POST_DIAL = Uri.parse("tel:6505551212,,,1234"); private static final Uri ORIGINAL_NUMBER_NO_POST_DIAL = Uri.parse("tel:6505551212"); private static final Uri REDIRECTED_GATEWAY_NUMBER = Uri.parse("tel:6505551213"); private static final Uri REDIRECTED_GATEWAY_NUMBER_WITH_POST_DIAL = Uri.parse("tel:6505551213,,,1234"); private static final String USER_DEFINED_PKG_NAME = "user_defined_pkg"; private static final String USER_DEFINED_CLS_NAME = "user_defined_cls"; private static final String CARRIER_PKG_NAME = "carrier_pkg"; Loading Loading @@ -130,6 +145,8 @@ public class CallRedirectionProcessorTest extends TelecomTestCase { @Override @After public void tearDown() throws Exception { mProcessor.getHandler().removeCallbacksAndMessages(null); waitForHandlerAction(new Handler(Looper.getMainLooper()), TelecomSystemTest.TEST_TIMEOUT); super.tearDown(); } Loading Loading @@ -158,7 +175,11 @@ public class CallRedirectionProcessorTest extends TelecomTestCase { } private void startProcessWithNoGateWayInfo() { mProcessor = new CallRedirectionProcessor(mContext, mCallsManager, mCall, mHandle, startProcessWithNoGateWayInfo(mHandle); } private void startProcessWithNoGateWayInfo(Uri handle) { mProcessor = new CallRedirectionProcessor(mContext, mCallsManager, mCall, handle, mPhoneAccountRegistrar, null, SPEAKER_PHONE_ON, VIDEO_STATE); mProcessor.setCallRedirectionServiceHelper(mCallRedirectionProcessorHelper); } Loading Loading @@ -287,4 +308,50 @@ public class CallRedirectionProcessorTest extends TelecomTestCase { eq(mPhoneAccountHandle), eq(mGatewayInfo), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE), eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION)); } @Test public void testStripPostDialDigits() throws Exception { startProcessWithNoGateWayInfo(ORIGINAL_NUMBER_WITH_POST_DIAL); enableUserDefinedCallRedirectionService(); disableCarrierCallRedirectionService(); mProcessor.performCallRedirection(); // Capture binding and mock it out. ArgumentCaptor<ServiceConnection> serviceConnectionCaptor = ArgumentCaptor.forClass( ServiceConnection.class); verify(mContext, times(1)).bindServiceAsUser(any(Intent.class), serviceConnectionCaptor.capture(), anyInt(), any(UserHandle.class)); // Mock out a service which performed a redirection IBinder mockBinder = mock(IBinder.class); ICallRedirectionService mockCallRedirectionService = mock(ICallRedirectionService.class); when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockCallRedirectionService); serviceConnectionCaptor.getValue().onServiceConnected( USER_DEFINED_SERVICE_TEST_COMPONENT_NAME, mockBinder); ArgumentCaptor<ICallRedirectionAdapter> redirectionAdapterCaptor = ArgumentCaptor.forClass( ICallRedirectionAdapter.class); ArgumentCaptor<Uri> uriArgumentCaptor = ArgumentCaptor.forClass(Uri.class); verify(mockCallRedirectionService, times(1)).placeCall(redirectionAdapterCaptor.capture(), uriArgumentCaptor.capture(), any(), anyBoolean()); // Verify the service did not get passed post-dial digits. assertEquals(ORIGINAL_NUMBER_NO_POST_DIAL, uriArgumentCaptor.getValue()); // Pretend it was verified. redirectionAdapterCaptor.getValue().redirectCall(REDIRECTED_GATEWAY_NUMBER, mPhoneAccountHandle, false); waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY); ArgumentCaptor<GatewayInfo> gatewayInfoArgumentCaptor = ArgumentCaptor.forClass( GatewayInfo.class); verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), eq(ORIGINAL_NUMBER_WITH_POST_DIAL), eq(mPhoneAccountHandle), gatewayInfoArgumentCaptor.capture(), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE), eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION)); assertEquals(REDIRECTED_GATEWAY_NUMBER_WITH_POST_DIAL, gatewayInfoArgumentCaptor.getValue().getGatewayAddress()); } } Loading
src/com/android/server/telecom/CallsManager.java +4 −1 Original line number Diff line number Diff line Loading @@ -2178,7 +2178,10 @@ public class CallsManager extends Call.ListenerBase // is a video call, of if using speaker when docked PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount( call.getTargetPhoneAccount(), call.getInitiatingUser()); boolean allowVideo = account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING); boolean allowVideo = false; if (account != null) { allowVideo = account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING); } call.setStartWithSpeakerphoneOn(speakerphoneOn || (useSpeakerForVideoCall && allowVideo) || (useSpeakerWhenDocked && useSpeakerForDock)); call.setVideoState(videoState); Loading
src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java +8 −1 Original line number Diff line number Diff line Loading @@ -196,7 +196,7 @@ public class CallRedirectionProcessor implements CallRedirectionCallback { synchronized (mTelecomLock) { mRedirectionGatewayInfo = mCallRedirectionProcessorHelper .getGatewayInfoFromGatewayUri(mComponentName.getPackageName(), gatewayUri, mDestinationUri); gatewayUri, mDestinationUri, mPostDialDigits); mPhoneAccountHandle = targetPhoneAccount; // If carrier redirects call, we should skip to notify users about // the user-defined call redirection service. Loading Loading @@ -246,6 +246,12 @@ public class CallRedirectionProcessor implements CallRedirectionCallback { */ private Uri mProcessedDestinationUri; /** * The post dial digits which were removed from {@link #mDestinationUri} when determining * {@link #mProcessedDestinationUri}. */ private String mPostDialDigits; /** * Indicates if Telecom should cancel the call when the whole call redirection finishes. */ Loading Loading @@ -293,6 +299,7 @@ public class CallRedirectionProcessor implements CallRedirectionCallback { context, callsManager, phoneAccountRegistrar); mProcessedDestinationUri = mCallRedirectionProcessorHelper.formatNumberForRedirection( mDestinationUri); mPostDialDigits = mCallRedirectionProcessorHelper.getPostDialDigits(mDestinationUri); } @Override Loading
src/com/android/server/telecom/callredirection/CallRedirectionProcessorHelper.java +22 −3 Original line number Diff line number Diff line Loading @@ -129,6 +129,18 @@ public class CallRedirectionProcessorHelper { return removePostDialDigits(formatNumberToE164(handle)); } /** * Extras the post dial digits from a given handle. * @param handle The handle * @return The post dial digits. */ public String getPostDialDigits(Uri handle) { if (handle == null) { return ""; } return PhoneNumberUtils.extractPostDialPortion(handle.getSchemeSpecificPart()); } protected Uri formatNumberToE164(Uri handle) { String number = handle.getSchemeSpecificPart(); Loading Loading @@ -163,10 +175,17 @@ public class CallRedirectionProcessorHelper { } } protected GatewayInfo getGatewayInfoFromGatewayUri( String gatewayPackageName, Uri gatewayUri, Uri destinationUri) { public static GatewayInfo getGatewayInfoFromGatewayUri( String gatewayPackageName, Uri gatewayUri, Uri destinationUri, String postdialDigits) { if (!TextUtils.isEmpty(gatewayPackageName) && gatewayUri != null) { return new GatewayInfo(gatewayPackageName, gatewayUri, destinationUri); Uri gatewayWithPostdial = gatewayUri; if (gatewayUri != null && !TextUtils.isEmpty(postdialDigits)) { gatewayWithPostdial = new Uri.Builder() .scheme(gatewayUri.getScheme()) .encodedOpaquePart(gatewayUri.getSchemeSpecificPart() + postdialDigits) .build(); } return new GatewayInfo(gatewayPackageName, gatewayWithPostdial, destinationUri); } return null; } Loading
tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java +68 −1 Original line number Diff line number Diff line Loading @@ -23,11 +23,15 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.UserHandle; import android.telecom.GatewayInfo; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; import com.android.internal.telecom.ICallRedirectionAdapter; import com.android.internal.telecom.ICallRedirectionService; import com.android.server.telecom.Call; import com.android.server.telecom.CallsManager; Loading @@ -39,24 +43,30 @@ import com.android.server.telecom.Timeouts; import com.android.server.telecom.callredirection.CallRedirectionProcessor; import com.android.server.telecom.callredirection.CallRedirectionProcessorHelper; import static org.junit.Assert.assertEquals; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.junit.Before; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; @RunWith(JUnit4.class) public class CallRedirectionProcessorTest extends TelecomTestCase { @Mock private Context mContext; Loading @@ -82,6 +92,11 @@ public class CallRedirectionProcessorTest extends TelecomTestCase { @Mock private Timeouts.Adapter mTimeoutsAdapter; private static final Uri ORIGINAL_NUMBER_WITH_POST_DIAL = Uri.parse("tel:6505551212,,,1234"); private static final Uri ORIGINAL_NUMBER_NO_POST_DIAL = Uri.parse("tel:6505551212"); private static final Uri REDIRECTED_GATEWAY_NUMBER = Uri.parse("tel:6505551213"); private static final Uri REDIRECTED_GATEWAY_NUMBER_WITH_POST_DIAL = Uri.parse("tel:6505551213,,,1234"); private static final String USER_DEFINED_PKG_NAME = "user_defined_pkg"; private static final String USER_DEFINED_CLS_NAME = "user_defined_cls"; private static final String CARRIER_PKG_NAME = "carrier_pkg"; Loading Loading @@ -130,6 +145,8 @@ public class CallRedirectionProcessorTest extends TelecomTestCase { @Override @After public void tearDown() throws Exception { mProcessor.getHandler().removeCallbacksAndMessages(null); waitForHandlerAction(new Handler(Looper.getMainLooper()), TelecomSystemTest.TEST_TIMEOUT); super.tearDown(); } Loading Loading @@ -158,7 +175,11 @@ public class CallRedirectionProcessorTest extends TelecomTestCase { } private void startProcessWithNoGateWayInfo() { mProcessor = new CallRedirectionProcessor(mContext, mCallsManager, mCall, mHandle, startProcessWithNoGateWayInfo(mHandle); } private void startProcessWithNoGateWayInfo(Uri handle) { mProcessor = new CallRedirectionProcessor(mContext, mCallsManager, mCall, handle, mPhoneAccountRegistrar, null, SPEAKER_PHONE_ON, VIDEO_STATE); mProcessor.setCallRedirectionServiceHelper(mCallRedirectionProcessorHelper); } Loading Loading @@ -287,4 +308,50 @@ public class CallRedirectionProcessorTest extends TelecomTestCase { eq(mPhoneAccountHandle), eq(mGatewayInfo), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE), eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION)); } @Test public void testStripPostDialDigits() throws Exception { startProcessWithNoGateWayInfo(ORIGINAL_NUMBER_WITH_POST_DIAL); enableUserDefinedCallRedirectionService(); disableCarrierCallRedirectionService(); mProcessor.performCallRedirection(); // Capture binding and mock it out. ArgumentCaptor<ServiceConnection> serviceConnectionCaptor = ArgumentCaptor.forClass( ServiceConnection.class); verify(mContext, times(1)).bindServiceAsUser(any(Intent.class), serviceConnectionCaptor.capture(), anyInt(), any(UserHandle.class)); // Mock out a service which performed a redirection IBinder mockBinder = mock(IBinder.class); ICallRedirectionService mockCallRedirectionService = mock(ICallRedirectionService.class); when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockCallRedirectionService); serviceConnectionCaptor.getValue().onServiceConnected( USER_DEFINED_SERVICE_TEST_COMPONENT_NAME, mockBinder); ArgumentCaptor<ICallRedirectionAdapter> redirectionAdapterCaptor = ArgumentCaptor.forClass( ICallRedirectionAdapter.class); ArgumentCaptor<Uri> uriArgumentCaptor = ArgumentCaptor.forClass(Uri.class); verify(mockCallRedirectionService, times(1)).placeCall(redirectionAdapterCaptor.capture(), uriArgumentCaptor.capture(), any(), anyBoolean()); // Verify the service did not get passed post-dial digits. assertEquals(ORIGINAL_NUMBER_NO_POST_DIAL, uriArgumentCaptor.getValue()); // Pretend it was verified. redirectionAdapterCaptor.getValue().redirectCall(REDIRECTED_GATEWAY_NUMBER, mPhoneAccountHandle, false); waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY); ArgumentCaptor<GatewayInfo> gatewayInfoArgumentCaptor = ArgumentCaptor.forClass( GatewayInfo.class); verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), eq(ORIGINAL_NUMBER_WITH_POST_DIAL), eq(mPhoneAccountHandle), gatewayInfoArgumentCaptor.capture(), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE), eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION)); assertEquals(REDIRECTED_GATEWAY_NUMBER_WITH_POST_DIAL, gatewayInfoArgumentCaptor.getValue().getGatewayAddress()); } }