Loading src/java/com/android/internal/telephony/ims/ImsServiceController.java +23 −23 Original line number Diff line number Diff line Loading @@ -52,7 +52,6 @@ import com.android.internal.telephony.ExponentialBackoff; import com.android.internal.telephony.util.TelephonyUtils; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; Loading Loading @@ -452,19 +451,24 @@ public class ImsServiceController { SparseIntArray slotIdToSubIdMap) throws RemoteException { sanitizeFeatureConfig(newImsFeatures); synchronized (mLock) { HashSet<Integer> slotIDs = new HashSet<>(); slotIDs.addAll(newImsFeatures.stream().map(e -> e.slotId).collect(Collectors.toSet())); ArrayList<Integer> changedSubIds = new ArrayList<Integer>(); HashSet<Integer> slotIDs = newImsFeatures.stream().map(e -> e.slotId).collect( Collectors.toCollection(HashSet::new)); // detect which subIds have changed on a per-slot basis SparseIntArray changedSubIds = new SparseIntArray(slotIDs.size()); for (Integer slotID : slotIDs) { if (mSlotIdToSubIdMap.get(slotID, PLACEHOLDER_SUBSCRIPTION_ID_BASE) != slotIdToSubIdMap.get(slotID)) { changedSubIds.add(slotIdToSubIdMap.get(slotID)); mLocalLog.log("changed sub IDs: " + changedSubIds); Log.i(LOG_TAG, "changed sub IDs: " + changedSubIds); int oldSubId = mSlotIdToSubIdMap.get(slotID, PLACEHOLDER_SUBSCRIPTION_ID_BASE); int newSubId = slotIdToSubIdMap.get(slotID); if (oldSubId != newSubId) { changedSubIds.put(slotID, newSubId); mLocalLog.log("subId changed for slot: " + slotID + ", " + oldSubId + " -> " + newSubId); Log.i(LOG_TAG, "subId changed for slot: " + slotID + ", " + oldSubId + " -> " + newSubId); } } mSlotIdToSubIdMap = slotIdToSubIdMap; if (mImsFeatures.equals(newImsFeatures) && !isSubIdChanged(changedSubIds)) { // no change, return early. if (mImsFeatures.equals(newImsFeatures) && changedSubIds.size() == 0) { return; } mLocalLog.log("Features (" + mImsFeatures + "->" + newImsFeatures + ")"); Loading Loading @@ -496,22 +500,22 @@ public class ImsServiceController { new HashSet<>(mImsFeatures); unchangedFeatures.removeAll(oldFeatures); unchangedFeatures.removeAll(newFeatures); // ensure remove and add unchanged features that have a slot ID associated with // the new subscription ID. if (isSubIdChanged(changedSubIds)) { for (Integer changedSubId : changedSubIds) { int slotId = mSlotIdToSubIdMap.indexOfValue(changedSubId); // Go through ImsFeatures whose associated subId have changed and recreate them. if (changedSubIds.size() > 0) { for (int slotId : changedSubIds.copyKeys()) { int subId = changedSubIds.get(slotId, SubscriptionManager.INVALID_SUBSCRIPTION_ID); HashSet<ImsFeatureConfiguration.FeatureSlotPair> removeAddFeatures = new HashSet<>(); removeAddFeatures.addAll(unchangedFeatures.stream() .filter(e -> e.slotId == slotId).collect(Collectors.toSet())); removeAddFeatures = unchangedFeatures.stream() .filter(e -> e.slotId == slotId).collect( Collectors.toCollection(HashSet::new)); for (ImsFeatureConfiguration.FeatureSlotPair i : removeAddFeatures) { removeImsServiceFeature(i, true); } for (ImsFeatureConfiguration.FeatureSlotPair i : removeAddFeatures) { long caps = modifyCapabiltiesForSlot(mImsFeatures, i.slotId, mServiceCapabilities); addImsServiceFeature(i, caps, changedSubId); addImsServiceFeature(i, caps, subId); } unchangedFeatures.removeAll(removeAddFeatures); } Loading Loading @@ -919,10 +923,6 @@ public class ImsServiceController { AnomalyReporter.reportAnomaly(mAnomalyUUID, message); } private boolean isSubIdChanged(ArrayList<Integer> changedSubIds) { return !changedSubIds.isEmpty(); } @Override public String toString() { synchronized (mLock) { Loading src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java +15 −4 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import android.telephony.TelephonyLocalConnection; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsCallProfile; import android.telephony.ims.ImsCallSession; import android.telephony.ims.ImsConferenceState; import android.telephony.ims.ImsMmTelManager; import android.telephony.ims.ImsReasonInfo; Loading Loading @@ -2798,7 +2799,9 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { private void maybeSetVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall) { android.telecom.Connection.VideoProvider connVideoProvider = conn.getVideoProvider(); if (connVideoProvider != null || imsCall.getCallSession().getVideoCallProvider() == null) { ImsCallSession callSession = imsCall.getCallSession(); if (connVideoProvider != null || callSession == null || callSession.getVideoCallProvider() == null) { return; } Loading Loading @@ -3292,12 +3295,20 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } else if (conn.isIncoming() && conn.getConnectTime() == 0 && cause != DisconnectCause.ANSWERED_ELSEWHERE) { if (conn.getDisconnectCause() == DisconnectCause.LOCAL) { // Two cases where the call is declared as rejected. // 1. The disconnect was initiated by the user. I.e. the connection's // disconnect cause is LOCAL at this point. // 2. The network provided disconnect cause is INCOMING_REJECTED. This will be // the case for ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE and // ImsReasonInfo.CODE_REJECTED_ELSEWHERE. if (conn.getDisconnectCause() == DisconnectCause.LOCAL || cause == DisconnectCause.INCOMING_REJECTED) { // If the user initiated a disconnect of this connection, then we will treat // this is a rejected call. // Note; the record the fact that this is a local disconnect in // Note; we record the fact that this is a local disconnect in // ImsPhoneConnection#onHangupLocal // Alternatively, the network can specify INCOMING_REJECTED as a result of // remote reject on another device; we'll still treat as rejected. cause = DisconnectCause.INCOMING_REJECTED; } else { // Otherwise in all other cases consider it missed. Loading tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -381,6 +381,68 @@ public class ImsServiceControllerTest extends ImsTestBase { validateMmTelFeatureContainerExists(SLOT_1); } /** * Ensures ImsServiceController correctly removes the existing MmTelFeature and creates an * emergency only MmTelFeature when slot 0 has no subscription and the sim card is removed for * slot 1. */ @SmallTest @Test public void testCallChangeWithNoNewFeaturesWithSlot1SubIdChanged() throws RemoteException { HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>(); testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0, ImsFeature.FEATURE_EMERGENCY_MMTEL)); testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0, ImsFeature.FEATURE_MMTEL)); testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1, ImsFeature.FEATURE_EMERGENCY_MMTEL)); testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1, ImsFeature.FEATURE_MMTEL)); SparseIntArray slotIdToSubIdMap = new SparseIntArray(); // invalid subid in slot 0 slotIdToSubIdMap.put(SLOT_0, SubscriptionManager.INVALID_SUBSCRIPTION_ID); // valid subId in slot 1 slotIdToSubIdMap.put(SLOT_1, SUB_3); bindAndConnectService(testFeatures, slotIdToSubIdMap.clone()); verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_0); verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL), any()); verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController)); verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3); verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), any()); verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController)); validateMmTelFeatureContainerExistsWithEmergency(SLOT_0); validateMmTelFeatureContainerExistsWithEmergency(SLOT_1); slotIdToSubIdMap.put(SLOT_0, SubscriptionManager.INVALID_SUBSCRIPTION_ID); slotIdToSubIdMap.put(SLOT_1, SubscriptionManager.INVALID_SUBSCRIPTION_ID); // ensure only slot 1 gets replaced with emergency only MmTelFeature. mTestImsServiceController.changeImsServiceFeatures(testFeatures, slotIdToSubIdMap.clone()); verify(mMockServiceControllerBinder).removeImsFeature(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), eq(true)); verify(mMockServiceControllerBinder).removeFeatureStatusCallback(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), any()); verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController)); verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_1); verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), any()); verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController)); validateMmTelFeatureContainerExistsWithEmergency(SLOT_0); validateMmTelFeatureContainerExistsWithEmergency(SLOT_1); // this should not have been called again since it did not change (times = 1) verify(mMockServiceControllerBinder, times(1)).createEmergencyOnlyMmTelFeature(SLOT_0); } /** * Tests ImsServiceController keeps SIP delegate creation flags if MMTEL and RCS are supported. */ Loading tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; Loading Loading @@ -144,6 +145,39 @@ public class ImsCallTest extends TelephonyTest { assertTrue(imsCall.wasVideoCall()); } @Test @SmallTest public void testCloseImsCallRtt() throws Exception { ImsCallSession mockSession = mock(ImsCallSession.class); ImsStreamMediaProfile streamProfile = new ImsStreamMediaProfile( ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB, ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE, ImsStreamMediaProfile.VIDEO_QUALITY_NONE, ImsStreamMediaProfile.DIRECTION_INACTIVE, // Full RTT mode ImsStreamMediaProfile.RTT_MODE_FULL); ImsCallProfile profile = new ImsCallProfile(ImsCallProfile.SERVICE_TYPE_NORMAL, ImsCallProfile.CALL_TYPE_VOICE, null /*extras*/, streamProfile); profile.mCallType = ImsCallProfile.CALL_TYPE_VOICE; ImsCall imsCall = new ImsCall(mContext, profile); imsCall.attachSession(mockSession); imsCall.sendRttMessage("test"); verify(mockSession).sendRttMessage("test"); //called by ImsPhoneCallTracker when the call is terminated imsCall.close(); try { // Ensure RTT cases are handled gracefully. imsCall.sendRttMessage("test"); imsCall.sendRttModifyRequest(true); imsCall.sendRttModifyResponse(true); } catch (Exception e) { fail("Unexpected exception: " + e); } } @Test @SmallTest public void testSetWifi() { Loading tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -508,6 +508,24 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest { assertEquals(DisconnectCause.INCOMING_REJECTED, connection.getDisconnectCause()); } @Test @SmallTest public void testRejectedElsewhereIsRejected() { ImsPhoneConnection connection = setupRingingConnection(); mImsCallListener.onCallTerminated(connection.getImsCall(), new ImsReasonInfo(ImsReasonInfo.CODE_REJECTED_ELSEWHERE, 0)); assertEquals(DisconnectCause.INCOMING_REJECTED, connection.getDisconnectCause()); } @Test @SmallTest public void testRemoteCallDeclineIsRejected() { ImsPhoneConnection connection = setupRingingConnection(); mImsCallListener.onCallTerminated(connection.getImsCall(), new ImsReasonInfo(ImsReasonInfo.CODE_REMOTE_CALL_DECLINE, 0)); assertEquals(DisconnectCause.INCOMING_REJECTED, connection.getDisconnectCause()); } private ImsPhoneConnection setupRingingConnection() { mImsCallProfile.setCallerNumberVerificationStatus( ImsCallProfile.VERIFICATION_STATUS_PASSED); Loading Loading @@ -1860,6 +1878,22 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest { assertEquals(Call.State.IDLE, mCTUT.mForegroundCall.getState()); } @Test @SmallTest public void testCallSessionUpdatedAfterSrvccCompleted() throws RemoteException { startOutgoingCall(); // Move the connection to the handover state. mCTUT.notifySrvccState(Call.SrvccState.COMPLETED); try { // When trigger CallSessionUpdated after Srvcc completes, checking no exception. mImsCallListener.onCallUpdated(mSecondImsCall); } catch (Exception ex) { Assert.fail("unexpected exception thrown" + ex.getMessage()); } } private void sendCarrierConfigChanged() { Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, mPhone.getSubId()); Loading Loading
src/java/com/android/internal/telephony/ims/ImsServiceController.java +23 −23 Original line number Diff line number Diff line Loading @@ -52,7 +52,6 @@ import com.android.internal.telephony.ExponentialBackoff; import com.android.internal.telephony.util.TelephonyUtils; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; Loading Loading @@ -452,19 +451,24 @@ public class ImsServiceController { SparseIntArray slotIdToSubIdMap) throws RemoteException { sanitizeFeatureConfig(newImsFeatures); synchronized (mLock) { HashSet<Integer> slotIDs = new HashSet<>(); slotIDs.addAll(newImsFeatures.stream().map(e -> e.slotId).collect(Collectors.toSet())); ArrayList<Integer> changedSubIds = new ArrayList<Integer>(); HashSet<Integer> slotIDs = newImsFeatures.stream().map(e -> e.slotId).collect( Collectors.toCollection(HashSet::new)); // detect which subIds have changed on a per-slot basis SparseIntArray changedSubIds = new SparseIntArray(slotIDs.size()); for (Integer slotID : slotIDs) { if (mSlotIdToSubIdMap.get(slotID, PLACEHOLDER_SUBSCRIPTION_ID_BASE) != slotIdToSubIdMap.get(slotID)) { changedSubIds.add(slotIdToSubIdMap.get(slotID)); mLocalLog.log("changed sub IDs: " + changedSubIds); Log.i(LOG_TAG, "changed sub IDs: " + changedSubIds); int oldSubId = mSlotIdToSubIdMap.get(slotID, PLACEHOLDER_SUBSCRIPTION_ID_BASE); int newSubId = slotIdToSubIdMap.get(slotID); if (oldSubId != newSubId) { changedSubIds.put(slotID, newSubId); mLocalLog.log("subId changed for slot: " + slotID + ", " + oldSubId + " -> " + newSubId); Log.i(LOG_TAG, "subId changed for slot: " + slotID + ", " + oldSubId + " -> " + newSubId); } } mSlotIdToSubIdMap = slotIdToSubIdMap; if (mImsFeatures.equals(newImsFeatures) && !isSubIdChanged(changedSubIds)) { // no change, return early. if (mImsFeatures.equals(newImsFeatures) && changedSubIds.size() == 0) { return; } mLocalLog.log("Features (" + mImsFeatures + "->" + newImsFeatures + ")"); Loading Loading @@ -496,22 +500,22 @@ public class ImsServiceController { new HashSet<>(mImsFeatures); unchangedFeatures.removeAll(oldFeatures); unchangedFeatures.removeAll(newFeatures); // ensure remove and add unchanged features that have a slot ID associated with // the new subscription ID. if (isSubIdChanged(changedSubIds)) { for (Integer changedSubId : changedSubIds) { int slotId = mSlotIdToSubIdMap.indexOfValue(changedSubId); // Go through ImsFeatures whose associated subId have changed and recreate them. if (changedSubIds.size() > 0) { for (int slotId : changedSubIds.copyKeys()) { int subId = changedSubIds.get(slotId, SubscriptionManager.INVALID_SUBSCRIPTION_ID); HashSet<ImsFeatureConfiguration.FeatureSlotPair> removeAddFeatures = new HashSet<>(); removeAddFeatures.addAll(unchangedFeatures.stream() .filter(e -> e.slotId == slotId).collect(Collectors.toSet())); removeAddFeatures = unchangedFeatures.stream() .filter(e -> e.slotId == slotId).collect( Collectors.toCollection(HashSet::new)); for (ImsFeatureConfiguration.FeatureSlotPair i : removeAddFeatures) { removeImsServiceFeature(i, true); } for (ImsFeatureConfiguration.FeatureSlotPair i : removeAddFeatures) { long caps = modifyCapabiltiesForSlot(mImsFeatures, i.slotId, mServiceCapabilities); addImsServiceFeature(i, caps, changedSubId); addImsServiceFeature(i, caps, subId); } unchangedFeatures.removeAll(removeAddFeatures); } Loading Loading @@ -919,10 +923,6 @@ public class ImsServiceController { AnomalyReporter.reportAnomaly(mAnomalyUUID, message); } private boolean isSubIdChanged(ArrayList<Integer> changedSubIds) { return !changedSubIds.isEmpty(); } @Override public String toString() { synchronized (mLock) { Loading
src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java +15 −4 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import android.telephony.TelephonyLocalConnection; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsCallProfile; import android.telephony.ims.ImsCallSession; import android.telephony.ims.ImsConferenceState; import android.telephony.ims.ImsMmTelManager; import android.telephony.ims.ImsReasonInfo; Loading Loading @@ -2798,7 +2799,9 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { private void maybeSetVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall) { android.telecom.Connection.VideoProvider connVideoProvider = conn.getVideoProvider(); if (connVideoProvider != null || imsCall.getCallSession().getVideoCallProvider() == null) { ImsCallSession callSession = imsCall.getCallSession(); if (connVideoProvider != null || callSession == null || callSession.getVideoCallProvider() == null) { return; } Loading Loading @@ -3292,12 +3295,20 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } else if (conn.isIncoming() && conn.getConnectTime() == 0 && cause != DisconnectCause.ANSWERED_ELSEWHERE) { if (conn.getDisconnectCause() == DisconnectCause.LOCAL) { // Two cases where the call is declared as rejected. // 1. The disconnect was initiated by the user. I.e. the connection's // disconnect cause is LOCAL at this point. // 2. The network provided disconnect cause is INCOMING_REJECTED. This will be // the case for ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE and // ImsReasonInfo.CODE_REJECTED_ELSEWHERE. if (conn.getDisconnectCause() == DisconnectCause.LOCAL || cause == DisconnectCause.INCOMING_REJECTED) { // If the user initiated a disconnect of this connection, then we will treat // this is a rejected call. // Note; the record the fact that this is a local disconnect in // Note; we record the fact that this is a local disconnect in // ImsPhoneConnection#onHangupLocal // Alternatively, the network can specify INCOMING_REJECTED as a result of // remote reject on another device; we'll still treat as rejected. cause = DisconnectCause.INCOMING_REJECTED; } else { // Otherwise in all other cases consider it missed. Loading
tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -381,6 +381,68 @@ public class ImsServiceControllerTest extends ImsTestBase { validateMmTelFeatureContainerExists(SLOT_1); } /** * Ensures ImsServiceController correctly removes the existing MmTelFeature and creates an * emergency only MmTelFeature when slot 0 has no subscription and the sim card is removed for * slot 1. */ @SmallTest @Test public void testCallChangeWithNoNewFeaturesWithSlot1SubIdChanged() throws RemoteException { HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>(); testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0, ImsFeature.FEATURE_EMERGENCY_MMTEL)); testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0, ImsFeature.FEATURE_MMTEL)); testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1, ImsFeature.FEATURE_EMERGENCY_MMTEL)); testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_1, ImsFeature.FEATURE_MMTEL)); SparseIntArray slotIdToSubIdMap = new SparseIntArray(); // invalid subid in slot 0 slotIdToSubIdMap.put(SLOT_0, SubscriptionManager.INVALID_SUBSCRIPTION_ID); // valid subId in slot 1 slotIdToSubIdMap.put(SLOT_1, SUB_3); bindAndConnectService(testFeatures, slotIdToSubIdMap.clone()); verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_0); verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL), any()); verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController)); verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3); verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), any()); verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController)); validateMmTelFeatureContainerExistsWithEmergency(SLOT_0); validateMmTelFeatureContainerExistsWithEmergency(SLOT_1); slotIdToSubIdMap.put(SLOT_0, SubscriptionManager.INVALID_SUBSCRIPTION_ID); slotIdToSubIdMap.put(SLOT_1, SubscriptionManager.INVALID_SUBSCRIPTION_ID); // ensure only slot 1 gets replaced with emergency only MmTelFeature. mTestImsServiceController.changeImsServiceFeatures(testFeatures, slotIdToSubIdMap.clone()); verify(mMockServiceControllerBinder).removeImsFeature(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), eq(true)); verify(mMockServiceControllerBinder).removeFeatureStatusCallback(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), any()); verify(mMockCallbacks).imsServiceFeatureRemoved(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController)); verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_1); verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), any()); verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController)); validateMmTelFeatureContainerExistsWithEmergency(SLOT_0); validateMmTelFeatureContainerExistsWithEmergency(SLOT_1); // this should not have been called again since it did not change (times = 1) verify(mMockServiceControllerBinder, times(1)).createEmergencyOnlyMmTelFeature(SLOT_0); } /** * Tests ImsServiceController keeps SIP delegate creation flags if MMTEL and RCS are supported. */ Loading
tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; Loading Loading @@ -144,6 +145,39 @@ public class ImsCallTest extends TelephonyTest { assertTrue(imsCall.wasVideoCall()); } @Test @SmallTest public void testCloseImsCallRtt() throws Exception { ImsCallSession mockSession = mock(ImsCallSession.class); ImsStreamMediaProfile streamProfile = new ImsStreamMediaProfile( ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB, ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE, ImsStreamMediaProfile.VIDEO_QUALITY_NONE, ImsStreamMediaProfile.DIRECTION_INACTIVE, // Full RTT mode ImsStreamMediaProfile.RTT_MODE_FULL); ImsCallProfile profile = new ImsCallProfile(ImsCallProfile.SERVICE_TYPE_NORMAL, ImsCallProfile.CALL_TYPE_VOICE, null /*extras*/, streamProfile); profile.mCallType = ImsCallProfile.CALL_TYPE_VOICE; ImsCall imsCall = new ImsCall(mContext, profile); imsCall.attachSession(mockSession); imsCall.sendRttMessage("test"); verify(mockSession).sendRttMessage("test"); //called by ImsPhoneCallTracker when the call is terminated imsCall.close(); try { // Ensure RTT cases are handled gracefully. imsCall.sendRttMessage("test"); imsCall.sendRttModifyRequest(true); imsCall.sendRttModifyResponse(true); } catch (Exception e) { fail("Unexpected exception: " + e); } } @Test @SmallTest public void testSetWifi() { Loading
tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -508,6 +508,24 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest { assertEquals(DisconnectCause.INCOMING_REJECTED, connection.getDisconnectCause()); } @Test @SmallTest public void testRejectedElsewhereIsRejected() { ImsPhoneConnection connection = setupRingingConnection(); mImsCallListener.onCallTerminated(connection.getImsCall(), new ImsReasonInfo(ImsReasonInfo.CODE_REJECTED_ELSEWHERE, 0)); assertEquals(DisconnectCause.INCOMING_REJECTED, connection.getDisconnectCause()); } @Test @SmallTest public void testRemoteCallDeclineIsRejected() { ImsPhoneConnection connection = setupRingingConnection(); mImsCallListener.onCallTerminated(connection.getImsCall(), new ImsReasonInfo(ImsReasonInfo.CODE_REMOTE_CALL_DECLINE, 0)); assertEquals(DisconnectCause.INCOMING_REJECTED, connection.getDisconnectCause()); } private ImsPhoneConnection setupRingingConnection() { mImsCallProfile.setCallerNumberVerificationStatus( ImsCallProfile.VERIFICATION_STATUS_PASSED); Loading Loading @@ -1860,6 +1878,22 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest { assertEquals(Call.State.IDLE, mCTUT.mForegroundCall.getState()); } @Test @SmallTest public void testCallSessionUpdatedAfterSrvccCompleted() throws RemoteException { startOutgoingCall(); // Move the connection to the handover state. mCTUT.notifySrvccState(Call.SrvccState.COMPLETED); try { // When trigger CallSessionUpdated after Srvcc completes, checking no exception. mImsCallListener.onCallUpdated(mSecondImsCall); } catch (Exception ex) { Assert.fail("unexpected exception thrown" + ex.getMessage()); } } private void sendCarrierConfigChanged() { Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, mPhone.getSubId()); Loading