Listen for SimultaneousCallingTracker updates in TelecomAccountRegistry.

This CL registers a listener with SimultaneousCallingTracker in order to be notified when the list of subscription IDs that support simultaneous calling has been update dfor a specific account.

Bug: 320569342
Test: atest SimultaneousCallingTrackerTest
Change-Id: I6a263e70f290ef0ac7b1b31b064c898c2068de7a
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index efa5278..09194a0 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -64,6 +64,7 @@
 import com.android.internal.telephony.ExponentialBackoff;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.SimultaneousCallingTracker;
 import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.phone.PhoneGlobals;
@@ -72,11 +73,15 @@
 import com.android.telephony.Rlog;
 
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 /**
  * Owns all data we have registered with Telecom including handling dynamic addition and
@@ -123,6 +128,7 @@
     final class AccountEntry implements PstnPhoneCapabilitiesNotifier.Listener {
         private final Phone mPhone;
         private PhoneAccount mAccount;
+        private SimultaneousCallingTracker mSCT;
         private final PstnIncomingCallNotifier mIncomingCallNotifier;
         private final PstnPhoneCapabilitiesNotifier mPhoneCapabilitiesNotifier;
         private boolean mIsEmergency;
@@ -133,6 +139,7 @@
         private MmTelFeature.MmTelCapabilities mMmTelCapabilities;
         private ImsMmTelManager.CapabilityCallback mMmtelCapabilityCallback;
         private RegistrationManager.RegistrationCallback mImsRegistrationCallback;
+        private SimultaneousCallingTracker.Listener mSimultaneousCallingTrackerListener;
         private ImsMmTelManager mMmTelManager;
         private final boolean mIsTestAccount;
         private boolean mIsVideoCapable;
@@ -145,12 +152,18 @@
         private boolean mIsManageImsConferenceCallSupported;
         private boolean mIsUsingSimCallManager;
         private boolean mIsShowPreciseFailedCause;
+        private Set<Integer> mSimultaneousCallSupportedSubIds;
 
         AccountEntry(Phone phone, boolean isEmergency, boolean isTest) {
             mPhone = phone;
             mIsEmergency = isEmergency;
             mIsTestAccount = isTest;
             mIsAdhocConfCapable = mPhone.isImsRegistered();
+            if (Flags.simultaneousCallingIndications()) {
+                mSCT = SimultaneousCallingTracker.getInstance();
+                mSimultaneousCallSupportedSubIds =
+                        mSCT.getSubIdsSupportingSimultaneousCalling(mPhone.getSubId());
+            }
             mAccount = registerPstnPhoneAccount(isEmergency, isTest);
             Log.i(this, "Registered phoneAccount: %s with handle: %s",
                     mAccount, mAccount.getAccountHandle());
@@ -203,6 +216,21 @@
                 }
             };
             registerImsRegistrationCallback();
+
+            if (Flags.simultaneousCallingIndications()) {
+                //Register SimultaneousCallingTracker listener:
+                mSimultaneousCallingTrackerListener = new SimultaneousCallingTracker.Listener() {
+                    @Override
+                    public void onSimultaneousCallingSupportChanged(Map<Integer,
+                            Set<Integer>> simultaneousCallSubSupportMap) {
+                        updateSimultaneousCallSubSupportMap(simultaneousCallSubSupportMap);
+                    }
+                };
+                SimultaneousCallingTracker.getInstance()
+                        .addListener(mSimultaneousCallingTrackerListener);
+                Log.d(LOG_TAG, "Finished registering mSimultaneousCallingTrackerListener for "
+                        + "phoneId = " + mPhone.getPhoneId() + "; subId = " + mPhone.getSubId());
+            }
         }
 
         void teardown() {
@@ -217,6 +245,10 @@
                     mMmTelManager.unregisterImsRegistrationCallback(mImsRegistrationCallback);
                 }
             }
+            if (Flags.simultaneousCallingIndications()) {
+                SimultaneousCallingTracker.getInstance()
+                        .removeListener(mSimultaneousCallingTrackerListener);
+            }
         }
 
         private void registerMmTelCapabilityCallback() {
@@ -514,7 +546,7 @@
                 Log.i(this, "Adding Merged Account with group: " + Rlog.pii(LOG_TAG, groupId));
             }
 
-            PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, label)
+            PhoneAccount.Builder accountBuilder = PhoneAccount.builder(phoneAccountHandle, label)
                     .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, line1Number, null))
                     .setSubscriptionAddress(
                             Uri.fromParts(PhoneAccount.SCHEME_TEL, subNumber, null))
@@ -525,10 +557,19 @@
                     .setSupportedUriSchemes(Arrays.asList(
                             PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL))
                     .setExtras(extras)
-                    .setGroupId(groupId)
-                    .build();
+                    .setGroupId(groupId);
 
-            return account;
+            if (Flags.simultaneousCallingIndications()) {
+                Set <PhoneAccountHandle> simultaneousCallingHandles =
+                        mSimultaneousCallSupportedSubIds.stream()
+                                .map(subscriptionId -> PhoneUtils.makePstnPhoneAccountHandleWithId(
+                                        String.valueOf(subscriptionId), userToRegister))
+                                .collect(Collectors.toSet());
+                accountBuilder.setSimultaneousCallingRestriction(simultaneousCallingHandles);
+            }
+
+
+            return accountBuilder.build();
         }
 
         public PhoneAccountHandle getPhoneAccountHandle() {
@@ -849,6 +890,30 @@
             }
         }
 
+        public void updateSimultaneousCallSubSupportMap(Map<Integer,
+                Set<Integer>> simultaneousCallSubSupportMap) {
+            if (!Flags.simultaneousCallingIndications()) { return; }
+            //Check if the simultaneous call support subIds for this account have changed:
+            Set<Integer> updatedSimultaneousCallSupportSubIds = new HashSet<>(3);
+            updatedSimultaneousCallSupportSubIds.addAll(
+                    simultaneousCallSubSupportMap.get(mPhone.getSubId()));
+            if (!updatedSimultaneousCallSupportSubIds.equals(mSimultaneousCallSupportedSubIds)) {
+                //If necessary, update cache and re-register mAccount:
+                mSimultaneousCallSupportedSubIds = updatedSimultaneousCallSupportSubIds;
+                synchronized (mAccountsLock) {
+                    if (!mAccounts.contains(this)) {
+                        // Account has already been torn down, don't try to register it again.
+                        // This handles the case where teardown has already happened, and we got a
+                        // simultaneous calling support update that lost the race for the
+                        // mAccountsLock. In such a scenario by the time we get here, the original
+                        // phone account could have been torn down.
+                        return;
+                    }
+                    mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount);
+                }
+            }
+        }
+
         public void updateAdhocConfCapability(boolean isAdhocConfCapable) {
             synchronized (mAccountsLock) {
                 if (!mAccounts.contains(this)) {