Fix sms app changed broadcast

Fixes: 136257475
Test: switch sms holder in settings, and ensure ceceived broadcasts for both
becoming and leaving the sms app status
Change-Id: I10dda3fd8ebd38ab12bdb8192ed4f3863f4238b8
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 9cd6b0d..c6a1867 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -49,6 +49,7 @@
 import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
+import android.provider.Telephony;
 import android.service.sms.FinancialSmsService;
 import android.telephony.IFinancialSmsCallback;
 import android.text.TextUtils;
@@ -60,6 +61,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.telephony.SmsApplication;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
 import com.android.internal.util.CollectionUtils;
@@ -377,13 +379,16 @@
     }
 
     @Override
-    public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
+    public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId,
+            @Nullable String removedHolder, @Nullable String addedHolder) {
         mListenerHandler.sendMessage(PooledLambda.obtainMessage(
-                RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId));
+                RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId,
+                removedHolder, addedHolder));
     }
 
     @WorkerThread
-    private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
+    private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId,
+            @Nullable String removedHolder, @Nullable String addedHolder) {
         RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
         if (listeners != null) {
             notifyRoleHoldersChangedForListeners(listeners, roleName, userId);
@@ -394,6 +399,12 @@
         if (allUsersListeners != null) {
             notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId);
         }
+
+        // Legacy: sms app changed broadcasts
+        if (RoleManager.ROLE_SMS.equals(roleName)) {
+            SmsApplication.broadcastSmsAppChange(getContext(), UserHandle.of(userId),
+                    removedHolder, addedHolder);
+        }
     }
 
     @WorkerThread
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index c7e3fa4..6375b48 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -294,7 +294,7 @@
         }
 
         if (changed) {
-            mCallback.onRoleHoldersChanged(roleName, mUserId);
+            mCallback.onRoleHoldersChanged(roleName, mUserId, null, packageName);
         }
         return true;
     }
@@ -328,7 +328,7 @@
         }
 
         if (changed) {
-            mCallback.onRoleHoldersChanged(roleName, mUserId);
+            mCallback.onRoleHoldersChanged(roleName, mUserId, packageName, null);
         }
         return true;
     }
@@ -632,6 +632,7 @@
          * @param roleName the name of the role whose holders are changed
          * @param userId the user id for this role holder change
          */
-        void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId);
+        void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId,
+                @Nullable String removedHolder, @Nullable String addedHolder);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/java/com/android/internal/telephony/SmsApplication.java
index 44dc24b..98f52cb 100644
--- a/telephony/java/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/java/com/android/internal/telephony/SmsApplication.java
@@ -17,6 +17,7 @@
 package com.android.internal.telephony;
 
 import android.Manifest.permission;
+import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.role.RoleManager;
 import android.content.ComponentName;
@@ -662,49 +663,69 @@
             }
 
             defaultSmsAppChanged(context);
+        }
+    }
 
-            if (DEBUG_MULTIUSER) {
-                Log.i(LOG_TAG, "setDefaultApplicationInternal oldAppData=" + oldAppData);
-            }
-            if (oldAppData != null && oldAppData.mSmsAppChangedReceiverClass != null) {
-                // Notify the old sms app that it's no longer the default
-                final Intent oldAppIntent =
-                        new Intent(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
-                final ComponentName component = new ComponentName(oldAppData.mPackageName,
-                        oldAppData.mSmsAppChangedReceiverClass);
-                oldAppIntent.setComponent(component);
-                oldAppIntent.putExtra(Telephony.Sms.Intents.EXTRA_IS_DEFAULT_SMS_APP, false);
-                if (DEBUG_MULTIUSER) {
-                    Log.i(LOG_TAG, "setDefaultApplicationInternal old=" + oldAppData.mPackageName);
-                }
-                context.sendBroadcastAsUser(oldAppIntent, userHandle);
-            }
-            // Notify the new sms app that it's now the default (if the new sms app has a receiver
-            // to handle the changed default sms intent).
-            if (DEBUG_MULTIUSER) {
-                Log.i(LOG_TAG, "setDefaultApplicationInternal new applicationData=" +
-                        applicationData);
-            }
-            if (applicationData.mSmsAppChangedReceiverClass != null) {
-                final Intent intent =
-                        new Intent(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
-                final ComponentName component = new ComponentName(applicationData.mPackageName,
-                        applicationData.mSmsAppChangedReceiverClass);
-                intent.setComponent(component);
-                intent.putExtra(Telephony.Sms.Intents.EXTRA_IS_DEFAULT_SMS_APP, true);
-                if (DEBUG_MULTIUSER) {
-                    Log.i(LOG_TAG, "setDefaultApplicationInternal new=" + packageName);
-                }
-                context.sendBroadcastAsUser(intent, userHandle);
-            }
+    /**
+     * Sends broadcasts on sms app change:
+     * {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED}
+     * {@link Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
+     */
+    public static void broadcastSmsAppChange(Context context,
+            UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) {
+        Collection<SmsApplicationData> apps = getApplicationCollection(context);
 
-            // Send an implicit broadcast for the system server.
-            // (or anyone with MONITOR_DEFAULT_SMS_PACKAGE, really.)
+        broadcastSmsAppChange(context, userHandle,
+                getApplicationForPackage(apps, oldPackage),
+                getApplicationForPackage(apps, newPackage));
+    }
+
+    private static void broadcastSmsAppChange(Context context, UserHandle userHandle,
+            @Nullable SmsApplicationData oldAppData,
+            @Nullable SmsApplicationData applicationData) {
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "setDefaultApplicationInternal oldAppData=" + oldAppData);
+        }
+        if (oldAppData != null && oldAppData.mSmsAppChangedReceiverClass != null) {
+            // Notify the old sms app that it's no longer the default
+            final Intent oldAppIntent =
+                    new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
+            final ComponentName component = new ComponentName(oldAppData.mPackageName,
+                    oldAppData.mSmsAppChangedReceiverClass);
+            oldAppIntent.setComponent(component);
+            oldAppIntent.putExtra(Intents.EXTRA_IS_DEFAULT_SMS_APP, false);
+            if (DEBUG_MULTIUSER) {
+                Log.i(LOG_TAG, "setDefaultApplicationInternal old=" + oldAppData.mPackageName);
+            }
+            context.sendBroadcastAsUser(oldAppIntent, userHandle);
+        }
+        // Notify the new sms app that it's now the default (if the new sms app has a receiver
+        // to handle the changed default sms intent).
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "setDefaultApplicationInternal new applicationData=" +
+                    applicationData);
+        }
+        if (applicationData != null && applicationData.mSmsAppChangedReceiverClass != null) {
             final Intent intent =
-                    new Intent(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
-            context.sendBroadcastAsUser(intent, userHandle,
-                    permission.MONITOR_DEFAULT_SMS_PACKAGE);
+                    new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
+            final ComponentName component = new ComponentName(applicationData.mPackageName,
+                    applicationData.mSmsAppChangedReceiverClass);
+            intent.setComponent(component);
+            intent.putExtra(Intents.EXTRA_IS_DEFAULT_SMS_APP, true);
+            if (DEBUG_MULTIUSER) {
+                Log.i(LOG_TAG, "setDefaultApplicationInternal new=" + applicationData.mPackageName);
+            }
+            context.sendBroadcastAsUser(intent, userHandle);
+        }
 
+        // Send an implicit broadcast for the system server.
+        // (or anyone with MONITOR_DEFAULT_SMS_PACKAGE, really.)
+        final Intent intent =
+                new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
+        context.sendBroadcastAsUser(intent, userHandle,
+                permission.MONITOR_DEFAULT_SMS_PACKAGE);
+
+        if (applicationData != null) {
             MetricsLogger.action(context, MetricsEvent.ACTION_DEFAULT_SMS_APP_CHANGED,
                     applicationData.mPackageName);
         }