Handle carrier config changes in TelecomAccountRegistry.

TelecomAccountRegistry makes use of the carrier configuration to set a
number of properties on the Telephony phone account(s).  This is done when
there is a subscription change.
It is, however, possible for a carrier config change to occur outside of
a subscription change.  If this happens, the change will not be reflected
in the accounts registered by the TelecomAccountRegistry.
Added a receiver for ACTION_CARRIER_CONFIG_CHANGED which triggers a
rebuild of the telephony phone account.  To ensure that unnecessary updates
are not made to the phone account in Telecom, compare the new to the old
phone account definition in this case.  If there is no change, we do not
update the phone account.

Test: Manual testing -- verify that carrier config change causes update to
the phone account for Telephony.
Bug: 112884689

Change-Id: Ia45023251583ea15bfacd85253c88bd79fe1dc27
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 6c8dcaa..642af85 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -107,9 +107,31 @@
         }
 
         /**
+         * Trigger re-registration of this account.
+         */
+        public void reRegisterPstnPhoneAccount() {
+            PhoneAccount newAccount = buildPstnPhoneAccount(mIsEmergency, mIsDummy);
+            if (!newAccount.equals(mAccount)) {
+                Log.i(this, "reRegisterPstnPhoneAccount: subId: " + getSubId()
+                        + " - re-register due to account change.");
+                mTelecomManager.registerPhoneAccount(newAccount);
+                mAccount = newAccount;
+            } else {
+                Log.i(this, "reRegisterPstnPhoneAccount: subId: " + getSubId() + " - no change");
+            }
+        }
+
+        private PhoneAccount registerPstnPhoneAccount(boolean isEmergency, boolean isDummyAccount) {
+            PhoneAccount account = buildPstnPhoneAccount(mIsEmergency, mIsDummy);
+            // Register with Telecom and put into the account entry.
+            mTelecomManager.registerPhoneAccount(account);
+            return account;
+        }
+
+        /**
          * Registers the specified account with Telecom as a PhoneAccountHandle.
          */
-        private PhoneAccount registerPstnPhoneAccount(boolean isEmergency, boolean isDummyAccount) {
+        private PhoneAccount buildPstnPhoneAccount(boolean isEmergency, boolean isDummyAccount) {
             String dummyPrefix = isDummyAccount ? "Dummy " : "";
 
             // Build the Phone account handle.
@@ -312,9 +334,6 @@
                     .setGroupId(groupId)
                     .build();
 
-            // Register with Telecom and put into the account entry.
-            mTelecomManager.registerPhoneAccount(account);
-
             return account;
         }
 
@@ -322,6 +341,10 @@
             return mAccount != null ? mAccount.getAccountHandle() : null;
         }
 
+        public int getSubId() {
+            return mPhone.getSubId();
+        }
+
         /**
          * Determines from carrier configuration whether pausing of IMS video calls is supported.
          *
@@ -579,19 +602,27 @@
         }
     };
 
-    private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            Log.i(this, "User changed, re-registering phone accounts.");
+            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
+                Log.i(this, "User changed, re-registering phone accounts.");
 
-            int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
-            UserHandle currentUserHandle = new UserHandle(userHandleId);
-            mIsPrimaryUser = UserManager.get(mContext).getPrimaryUser().getUserHandle()
-                    .equals(currentUserHandle);
+                int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                UserHandle currentUserHandle = new UserHandle(userHandleId);
+                mIsPrimaryUser = UserManager.get(mContext).getPrimaryUser().getUserHandle()
+                        .equals(currentUserHandle);
 
-            // Any time the user changes, re-register the accounts.
-            tearDownAccounts();
-            setupAccounts();
+                // Any time the user changes, re-register the accounts.
+                tearDownAccounts();
+                setupAccounts();
+            } else if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(
+                    intent.getAction())) {
+                Log.i(this, "Carrier-config changed, checking for phone account updates.");
+                int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
+                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+                handleCarrierConfigChange(subId);
+            }
         }
     };
 
@@ -814,8 +845,10 @@
 
         // Listen for user switches.  When the user switches, we need to ensure that if the current
         // use is not the primary user we disable video calling.
-        mContext.registerReceiver(mUserSwitchedReceiver,
-                new IntentFilter(Intent.ACTION_USER_SWITCHED));
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+        mContext.registerReceiver(mReceiver, filter);
 
         // Listen to the RTT system setting so that we update it when the user flips it.
         ContentObserver rttUiSettingObserver = new ContentObserver(
@@ -951,4 +984,27 @@
             mAccounts.clear();
         }
     }
+
+    /**
+     * Handles changes to the carrier configuration which may impact a phone account.  There are
+     * some extras defined in the {@link PhoneAccount} which are based on carrier config options.
+     * Only checking for carrier config changes when the subscription is configured runs the risk of
+     * missing carrier config changes which happen later.
+     * @param subId The subid the carrier config changed for, if applicable.  Will be
+     *              {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if not specified.
+     */
+    private void handleCarrierConfigChange(int subId) {
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return;
+        }
+        synchronized (mAccountsLock) {
+            for (AccountEntry entry : mAccounts) {
+                if (entry.getSubId() == subId) {
+                    Log.d(this, "handleCarrierConfigChange: subId=%d, accountSubId=%d", subId,
+                            entry.getSubId());
+                    entry.reRegisterPstnPhoneAccount();
+                }
+            }
+        }
+    }
 }