Loading src/java/com/android/internal/telephony/PhoneConfigurationManager.java +77 −21 Original line number Diff line number Diff line Loading @@ -47,7 +47,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; /** Loading Loading @@ -76,8 +78,10 @@ public class PhoneConfigurationManager { private static PhoneConfigurationManager sInstance = null; private final Context mContext; private PhoneCapability mStaticCapability; private final Set<Integer> mSlotsSupportingSimultaneousCellularCalls = new HashSet<>(2); private final Set<Integer> mSubIdsSupportingSimultaneousCellularCalls = new HashSet<>(2); private final Set<Integer> mSlotsSupportingSimultaneousCellularCalls = new HashSet<>(3); private final Set<Integer> mSubIdsSupportingSimultaneousCellularCalls = new HashSet<>(3); private final HashSet<Consumer<Set<Integer>>> mSimultaneousCellularCallingListeners = new HashSet<>(1); private final RadioConfig mRadioConfig; private final Handler mHandler; // mPhones is obtained from PhoneFactory and can have phones corresponding to inactive modems as Loading Loading @@ -185,12 +189,16 @@ public class PhoneConfigurationManager { /** * If virtual DSDA is enabled for this UE, then increase maxActiveVoiceSubscriptions to 2. */ private PhoneCapability maybeUpdateMaxActiveVoiceSubscriptions( private PhoneCapability maybeOverrideMaxActiveVoiceSubscriptions( final PhoneCapability staticCapability) { if (staticCapability.getLogicalModemList().size() > 1 && mVirtualDsdaEnabled) { boolean isVDsdaEnabled = staticCapability.getLogicalModemList().size() > 1 && mVirtualDsdaEnabled; boolean isBkwdCompatDsdaEnabled = mFeatureFlags.simultaneousCallingIndications() && mMi.getMultiSimProperty().orElse(SSSS).equals(DSDA); if (isVDsdaEnabled || isBkwdCompatDsdaEnabled) { // Since we already initialized maxActiveVoiceSubscriptions to the count the // modem is capable of, vDSDA is only able to increase that count via this method. We do // not allow vDSDA to decrease maxActiveVoiceSubscriptions: // modem is capable of, we are only able to increase that count via this method. We do // not allow a decrease of maxActiveVoiceSubscriptions: int updatedMaxActiveVoiceSubscriptions = Math.max(staticCapability.getMaxActiveVoiceSubscriptions(), 2); return new PhoneCapability.Builder(staticCapability) Loading @@ -202,14 +210,31 @@ public class PhoneConfigurationManager { } private void maybeEnableCellularDSDASupport() { if (mRadioConfig != null && mRadioConfig.getRadioConfigProxy(null) .getVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_2_2) && getPhoneCount() > 1 && mStaticCapability.getMaxActiveVoiceSubscriptions() > 1) { boolean bkwdsCompatDsda = mFeatureFlags.simultaneousCallingIndications() && getPhoneCount() > 1 && mMi.getMultiSimProperty().orElse(SSSS).equals(DSDA); boolean halSupportSimulCalling = mRadioConfig != null && mRadioConfig.getRadioConfigProxy(null).getVersion().greaterOrEqual( RIL.RADIO_HAL_VERSION_2_2) && getPhoneCount() > 1 && mStaticCapability.getMaxActiveVoiceSubscriptions() > 1; // Register for simultaneous calling support changes in the modem if the HAL supports it if (halSupportSimulCalling) { updateSimultaneousCallingSupport(); mRadioConfig.registerForSimultaneousCallingSupportStatusChanged(mHandler, EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED, null); if (mFeatureFlags.simultaneousCallingIndications()) { } else if (bkwdsCompatDsda) { // For older devices that only declare that they support DSDA via modem config, // set DSDA as capable now statically. log("DSDA modem config detected - setting DSDA enabled"); for (Phone p : mPhones) { mSlotsSupportingSimultaneousCellularCalls.add(p.getPhoneId()); } updateSimultaneousSubIdsFromPhoneIdMappingAndNotify(); notifySimultaneousCellularCallingSlotsChanged(); } // Register for subId updates to notify listeners when simultaneous calling is configured if (mFeatureFlags.simultaneousCallingIndications() && (bkwdsCompatDsda || halSupportSimulCalling)) { mContext.getSystemService(TelephonyRegistryManager.class) .addOnSubscriptionsChangedListener( new SubscriptionManager.OnSubscriptionsChangedListener() { Loading @@ -220,7 +245,6 @@ public class PhoneConfigurationManager { }, mHandler::post); } } } /** * Static method to get instance. Loading Loading @@ -331,6 +355,7 @@ public class PhoneConfigurationManager { } if (mFeatureFlags.simultaneousCallingIndications()) { updateSimultaneousSubIdsFromPhoneIdMappingAndNotify(); notifySimultaneousCellularCallingSlotsChanged(); } break; default: Loading Loading @@ -469,7 +494,7 @@ public class PhoneConfigurationManager { mHandler, EVENT_GET_PHONE_CAPABILITY_DONE); mRadioConfig.getPhoneCapability(callback); } mStaticCapability = maybeUpdateMaxActiveVoiceSubscriptions(mStaticCapability); mStaticCapability = maybeOverrideMaxActiveVoiceSubscriptions(mStaticCapability); log("getStaticPhoneCapability: mStaticCapability " + mStaticCapability); return mStaticCapability; } Loading @@ -485,8 +510,31 @@ public class PhoneConfigurationManager { return mStaticCapability.getMaxActiveDataSubscriptions(); } /** * Register to listen to changes in the Phone slots that support simultaneous calling. * @param consumer A consumer that will be used to consume the new slots supporting simultaneous * cellular calling when it changes. */ public void registerForSimultaneousCellularCallingSlotsChanged( Consumer<Set<Integer>> consumer) { mSimultaneousCellularCallingListeners.add(consumer); } private void notifySimultaneousCellularCallingSlotsChanged() { log("notifying listeners of changes to simultaneous cellular calling - new state:" + mSlotsSupportingSimultaneousCellularCalls); for (Consumer<Set<Integer>> consumer : mSimultaneousCellularCallingListeners) { try { consumer.accept(new HashSet<>(mSlotsSupportingSimultaneousCellularCalls)); } catch (Exception e) { log("Unexpected Exception encountered when notifying listener: " + e); } } } private void notifyCapabilityChanged() { mNotifier.notifyPhoneCapabilityChanged(mStaticCapability); mNotifier.notifyPhoneCapabilityChanged(maybeOverrideMaxActiveVoiceSubscriptions( mStaticCapability)); } /** Loading Loading @@ -572,6 +620,7 @@ public class PhoneConfigurationManager { mSlotsSupportingSimultaneousCellularCalls.clear(); if (mFeatureFlags.simultaneousCallingIndications()) { updateSimultaneousSubIdsFromPhoneIdMappingAndNotify(); notifySimultaneousCellularCallingSlotsChanged(); } } Loading Loading @@ -750,6 +799,13 @@ public class PhoneConfigurationManager { Context context, int numOfActiveModems) { PhoneFactory.onMultiSimConfigChanged(context, numOfActiveModems); } /** * Wrapper function to query the sysprop for multi_sim_config */ public Optional<String> getMultiSimProperty() { return TelephonyProperties.multi_sim_config(); } } private static void log(String s) { Loading tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper Loading Loading @@ -220,6 +222,61 @@ public class PhoneConfigurationManagerTest extends TelephonyTest { assertTrue(mPcm.getSlotsSupportingSimultaneousCellularCalls().isEmpty()); } /** * If the device uses the older "dsda" multi_sim_config setting, ensure that DSDA is set * statically for that device and subId updates work. */ @Test @SmallTest public void testBkwdsCompatSimultaneousCallingDsda() throws Exception { doReturn(true).when(mFeatureFlags).simultaneousCallingIndications(); doReturn(RIL.RADIO_HAL_VERSION_2_1).when(mMockRadioConfigProxy).getVersion(); doReturn(Optional.of("dsda")).when(mMi).getMultiSimProperty(); final int phone0SubId = 2; final int phone1SubId = 3; mPhones = new Phone[]{mPhone, mPhone1}; doReturn(0).when(mPhone).getPhoneId(); doReturn(1).when(mPhone1).getPhoneId(); replaceInstance(PhoneFactory.class, "sPhones", null, mPhones); init(2); doReturn(phone0SubId).when(mPhone).getSubId(); doReturn(phone1SubId).when(mPhone1).getSubId(); Set<Integer>[] cachedSimultaneousCallingSlots = new Set[]{Collections.emptySet()}; mPcm.registerForSimultaneousCellularCallingSlotsChanged(newSlots -> cachedSimultaneousCallingSlots[0] = newSlots); mPcm.getStaticPhoneCapability(); setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY); ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> cBCaptor = ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class); verify(mMockRegistryManager).addOnSubscriptionsChangedListener(cBCaptor.capture(), any()); processAllMessages(); int[] enabledLogicalSlots = {0, 1}; HashSet<Integer> expectedSlots = new HashSet<>(2); for (int i : enabledLogicalSlots) { expectedSlots.add(i); } HashSet<Integer> expectedSubIds = new HashSet<>(2); expectedSubIds.add(phone0SubId); expectedSubIds.add(phone1SubId); assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls()); verify(mMockRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged( eq(expectedSubIds)); assertEquals(expectedSlots, cachedSimultaneousCallingSlots[0]); // Change sub ID mapping final int phone1SubIdV2 = 4; expectedSubIds.clear(); expectedSubIds.add(phone0SubId); expectedSubIds.add(phone1SubIdV2); doReturn(phone1SubIdV2).when(mPhone1).getSubId(); cBCaptor.getValue().onSubscriptionsChanged(); processAllMessages(); verify(mMockRegistryManager, times(2)) .notifySimultaneousCellularCallingSubscriptionsChanged(eq(expectedSubIds)); } @Test @SmallTest public void testUpdateSimultaneousCallingSupportNotifications() throws Exception { Loading @@ -233,6 +290,9 @@ public class PhoneConfigurationManagerTest extends TelephonyTest { init(2); doReturn(phone0SubId).when(mPhone).getSubId(); doReturn(phone1SubId).when(mPhone1).getSubId(); Set<Integer>[] cachedSimultaneousCallingSlots = new Set[]{Collections.emptySet()}; mPcm.registerForSimultaneousCellularCallingSlotsChanged(newSlots -> cachedSimultaneousCallingSlots[0] = newSlots); // Simultaneous calling enabled mPcm.updateSimultaneousCallingSupport(); Loading @@ -254,6 +314,7 @@ public class PhoneConfigurationManagerTest extends TelephonyTest { assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls()); verify(mMockRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged( eq(expectedSubIds)); assertEquals(expectedSlots, cachedSimultaneousCallingSlots[0]); // Simultaneous Calling Disabled mPcm.updateSimultaneousCallingSupport(); Loading @@ -268,6 +329,7 @@ public class PhoneConfigurationManagerTest extends TelephonyTest { assertEquals(Collections.emptySet(), mPcm.getSlotsSupportingSimultaneousCellularCalls()); verify(mMockRegistryManager, times(2)) .notifySimultaneousCellularCallingSubscriptionsChanged(eq(Collections.emptySet())); assertEquals(Collections.emptySet(), cachedSimultaneousCallingSlots[0]); } @Test Loading Loading
src/java/com/android/internal/telephony/PhoneConfigurationManager.java +77 −21 Original line number Diff line number Diff line Loading @@ -47,7 +47,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; /** Loading Loading @@ -76,8 +78,10 @@ public class PhoneConfigurationManager { private static PhoneConfigurationManager sInstance = null; private final Context mContext; private PhoneCapability mStaticCapability; private final Set<Integer> mSlotsSupportingSimultaneousCellularCalls = new HashSet<>(2); private final Set<Integer> mSubIdsSupportingSimultaneousCellularCalls = new HashSet<>(2); private final Set<Integer> mSlotsSupportingSimultaneousCellularCalls = new HashSet<>(3); private final Set<Integer> mSubIdsSupportingSimultaneousCellularCalls = new HashSet<>(3); private final HashSet<Consumer<Set<Integer>>> mSimultaneousCellularCallingListeners = new HashSet<>(1); private final RadioConfig mRadioConfig; private final Handler mHandler; // mPhones is obtained from PhoneFactory and can have phones corresponding to inactive modems as Loading Loading @@ -185,12 +189,16 @@ public class PhoneConfigurationManager { /** * If virtual DSDA is enabled for this UE, then increase maxActiveVoiceSubscriptions to 2. */ private PhoneCapability maybeUpdateMaxActiveVoiceSubscriptions( private PhoneCapability maybeOverrideMaxActiveVoiceSubscriptions( final PhoneCapability staticCapability) { if (staticCapability.getLogicalModemList().size() > 1 && mVirtualDsdaEnabled) { boolean isVDsdaEnabled = staticCapability.getLogicalModemList().size() > 1 && mVirtualDsdaEnabled; boolean isBkwdCompatDsdaEnabled = mFeatureFlags.simultaneousCallingIndications() && mMi.getMultiSimProperty().orElse(SSSS).equals(DSDA); if (isVDsdaEnabled || isBkwdCompatDsdaEnabled) { // Since we already initialized maxActiveVoiceSubscriptions to the count the // modem is capable of, vDSDA is only able to increase that count via this method. We do // not allow vDSDA to decrease maxActiveVoiceSubscriptions: // modem is capable of, we are only able to increase that count via this method. We do // not allow a decrease of maxActiveVoiceSubscriptions: int updatedMaxActiveVoiceSubscriptions = Math.max(staticCapability.getMaxActiveVoiceSubscriptions(), 2); return new PhoneCapability.Builder(staticCapability) Loading @@ -202,14 +210,31 @@ public class PhoneConfigurationManager { } private void maybeEnableCellularDSDASupport() { if (mRadioConfig != null && mRadioConfig.getRadioConfigProxy(null) .getVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_2_2) && getPhoneCount() > 1 && mStaticCapability.getMaxActiveVoiceSubscriptions() > 1) { boolean bkwdsCompatDsda = mFeatureFlags.simultaneousCallingIndications() && getPhoneCount() > 1 && mMi.getMultiSimProperty().orElse(SSSS).equals(DSDA); boolean halSupportSimulCalling = mRadioConfig != null && mRadioConfig.getRadioConfigProxy(null).getVersion().greaterOrEqual( RIL.RADIO_HAL_VERSION_2_2) && getPhoneCount() > 1 && mStaticCapability.getMaxActiveVoiceSubscriptions() > 1; // Register for simultaneous calling support changes in the modem if the HAL supports it if (halSupportSimulCalling) { updateSimultaneousCallingSupport(); mRadioConfig.registerForSimultaneousCallingSupportStatusChanged(mHandler, EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED, null); if (mFeatureFlags.simultaneousCallingIndications()) { } else if (bkwdsCompatDsda) { // For older devices that only declare that they support DSDA via modem config, // set DSDA as capable now statically. log("DSDA modem config detected - setting DSDA enabled"); for (Phone p : mPhones) { mSlotsSupportingSimultaneousCellularCalls.add(p.getPhoneId()); } updateSimultaneousSubIdsFromPhoneIdMappingAndNotify(); notifySimultaneousCellularCallingSlotsChanged(); } // Register for subId updates to notify listeners when simultaneous calling is configured if (mFeatureFlags.simultaneousCallingIndications() && (bkwdsCompatDsda || halSupportSimulCalling)) { mContext.getSystemService(TelephonyRegistryManager.class) .addOnSubscriptionsChangedListener( new SubscriptionManager.OnSubscriptionsChangedListener() { Loading @@ -220,7 +245,6 @@ public class PhoneConfigurationManager { }, mHandler::post); } } } /** * Static method to get instance. Loading Loading @@ -331,6 +355,7 @@ public class PhoneConfigurationManager { } if (mFeatureFlags.simultaneousCallingIndications()) { updateSimultaneousSubIdsFromPhoneIdMappingAndNotify(); notifySimultaneousCellularCallingSlotsChanged(); } break; default: Loading Loading @@ -469,7 +494,7 @@ public class PhoneConfigurationManager { mHandler, EVENT_GET_PHONE_CAPABILITY_DONE); mRadioConfig.getPhoneCapability(callback); } mStaticCapability = maybeUpdateMaxActiveVoiceSubscriptions(mStaticCapability); mStaticCapability = maybeOverrideMaxActiveVoiceSubscriptions(mStaticCapability); log("getStaticPhoneCapability: mStaticCapability " + mStaticCapability); return mStaticCapability; } Loading @@ -485,8 +510,31 @@ public class PhoneConfigurationManager { return mStaticCapability.getMaxActiveDataSubscriptions(); } /** * Register to listen to changes in the Phone slots that support simultaneous calling. * @param consumer A consumer that will be used to consume the new slots supporting simultaneous * cellular calling when it changes. */ public void registerForSimultaneousCellularCallingSlotsChanged( Consumer<Set<Integer>> consumer) { mSimultaneousCellularCallingListeners.add(consumer); } private void notifySimultaneousCellularCallingSlotsChanged() { log("notifying listeners of changes to simultaneous cellular calling - new state:" + mSlotsSupportingSimultaneousCellularCalls); for (Consumer<Set<Integer>> consumer : mSimultaneousCellularCallingListeners) { try { consumer.accept(new HashSet<>(mSlotsSupportingSimultaneousCellularCalls)); } catch (Exception e) { log("Unexpected Exception encountered when notifying listener: " + e); } } } private void notifyCapabilityChanged() { mNotifier.notifyPhoneCapabilityChanged(mStaticCapability); mNotifier.notifyPhoneCapabilityChanged(maybeOverrideMaxActiveVoiceSubscriptions( mStaticCapability)); } /** Loading Loading @@ -572,6 +620,7 @@ public class PhoneConfigurationManager { mSlotsSupportingSimultaneousCellularCalls.clear(); if (mFeatureFlags.simultaneousCallingIndications()) { updateSimultaneousSubIdsFromPhoneIdMappingAndNotify(); notifySimultaneousCellularCallingSlotsChanged(); } } Loading Loading @@ -750,6 +799,13 @@ public class PhoneConfigurationManager { Context context, int numOfActiveModems) { PhoneFactory.onMultiSimConfigChanged(context, numOfActiveModems); } /** * Wrapper function to query the sysprop for multi_sim_config */ public Optional<String> getMultiSimProperty() { return TelephonyProperties.multi_sim_config(); } } private static void log(String s) { Loading
tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper Loading Loading @@ -220,6 +222,61 @@ public class PhoneConfigurationManagerTest extends TelephonyTest { assertTrue(mPcm.getSlotsSupportingSimultaneousCellularCalls().isEmpty()); } /** * If the device uses the older "dsda" multi_sim_config setting, ensure that DSDA is set * statically for that device and subId updates work. */ @Test @SmallTest public void testBkwdsCompatSimultaneousCallingDsda() throws Exception { doReturn(true).when(mFeatureFlags).simultaneousCallingIndications(); doReturn(RIL.RADIO_HAL_VERSION_2_1).when(mMockRadioConfigProxy).getVersion(); doReturn(Optional.of("dsda")).when(mMi).getMultiSimProperty(); final int phone0SubId = 2; final int phone1SubId = 3; mPhones = new Phone[]{mPhone, mPhone1}; doReturn(0).when(mPhone).getPhoneId(); doReturn(1).when(mPhone1).getPhoneId(); replaceInstance(PhoneFactory.class, "sPhones", null, mPhones); init(2); doReturn(phone0SubId).when(mPhone).getSubId(); doReturn(phone1SubId).when(mPhone1).getSubId(); Set<Integer>[] cachedSimultaneousCallingSlots = new Set[]{Collections.emptySet()}; mPcm.registerForSimultaneousCellularCallingSlotsChanged(newSlots -> cachedSimultaneousCallingSlots[0] = newSlots); mPcm.getStaticPhoneCapability(); setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY); ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> cBCaptor = ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class); verify(mMockRegistryManager).addOnSubscriptionsChangedListener(cBCaptor.capture(), any()); processAllMessages(); int[] enabledLogicalSlots = {0, 1}; HashSet<Integer> expectedSlots = new HashSet<>(2); for (int i : enabledLogicalSlots) { expectedSlots.add(i); } HashSet<Integer> expectedSubIds = new HashSet<>(2); expectedSubIds.add(phone0SubId); expectedSubIds.add(phone1SubId); assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls()); verify(mMockRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged( eq(expectedSubIds)); assertEquals(expectedSlots, cachedSimultaneousCallingSlots[0]); // Change sub ID mapping final int phone1SubIdV2 = 4; expectedSubIds.clear(); expectedSubIds.add(phone0SubId); expectedSubIds.add(phone1SubIdV2); doReturn(phone1SubIdV2).when(mPhone1).getSubId(); cBCaptor.getValue().onSubscriptionsChanged(); processAllMessages(); verify(mMockRegistryManager, times(2)) .notifySimultaneousCellularCallingSubscriptionsChanged(eq(expectedSubIds)); } @Test @SmallTest public void testUpdateSimultaneousCallingSupportNotifications() throws Exception { Loading @@ -233,6 +290,9 @@ public class PhoneConfigurationManagerTest extends TelephonyTest { init(2); doReturn(phone0SubId).when(mPhone).getSubId(); doReturn(phone1SubId).when(mPhone1).getSubId(); Set<Integer>[] cachedSimultaneousCallingSlots = new Set[]{Collections.emptySet()}; mPcm.registerForSimultaneousCellularCallingSlotsChanged(newSlots -> cachedSimultaneousCallingSlots[0] = newSlots); // Simultaneous calling enabled mPcm.updateSimultaneousCallingSupport(); Loading @@ -254,6 +314,7 @@ public class PhoneConfigurationManagerTest extends TelephonyTest { assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls()); verify(mMockRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged( eq(expectedSubIds)); assertEquals(expectedSlots, cachedSimultaneousCallingSlots[0]); // Simultaneous Calling Disabled mPcm.updateSimultaneousCallingSupport(); Loading @@ -268,6 +329,7 @@ public class PhoneConfigurationManagerTest extends TelephonyTest { assertEquals(Collections.emptySet(), mPcm.getSlotsSupportingSimultaneousCellularCalls()); verify(mMockRegistryManager, times(2)) .notifySimultaneousCellularCallingSubscriptionsChanged(eq(Collections.emptySet())); assertEquals(Collections.emptySet(), cachedSimultaneousCallingSlots[0]); } @Test Loading