aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-20 14:03:55 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-20 14:03:55 +0000
commit71b1315593200697c2b36b576fb4937e7e47ed24 (patch)
tree025edca3b973eefb7197c609ca7356395c48c66d
parentd76f8a9ea2fbc4964adc5db5d13d7a5e59066eaf (diff)
parent36e8e033e177eaefc879ee74f6602a6a797e53ad (diff)
downloadtelephony-android13-frc-permission-release.tar.gz
Snap for 8745897 from 36e8e033e177eaefc879ee74f6602a6a797e53ad to tm-frc-permission-releaset_frc_per_330444010android13-frc-permission-release
Change-Id: I78df6733c084bfd9df797a09b4d8cfa23eac8b46
-rw-r--r--src/java/com/android/internal/telephony/ims/ImsServiceController.java46
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java19
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java62
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java34
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java34
5 files changed, 168 insertions, 27 deletions
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceController.java b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
index 9ae40e1c23..92e7d7117c 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceController.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
@@ -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;
@@ -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 + ")");
@@ -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);
}
@@ -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) {
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index cc8af38cdd..891570b751 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -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;
@@ -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;
}
@@ -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.
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
index 083fac98be..113829f88b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
@@ -382,6 +382,68 @@ public class ImsServiceControllerTest extends ImsTestBase {
}
/**
+ * 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.
*/
@SmallTest
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java
index d6652646f7..aa071255d4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java
@@ -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;
@@ -146,6 +147,39 @@ public class ImsCallTest extends TelephonyTest {
@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() {
ImsCall mTestImsCall = new ImsCall(mContext, mTestCallProfile);
assertFalse(mTestImsCall.isWifiCall());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index 95eedc2aed..1428b254ed 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -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);
@@ -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());