diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index caa275d266e92..106dc2111b4d9 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -56,7 +56,6 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.infra.AndroidFuture; import com.android.internal.infra.ThrottledRunnable; -import com.android.internal.telephony.SmsApplication; import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.internal.util.CollectionUtils; @@ -392,16 +391,13 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } @Override - public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId, - @Nullable String removedHolder, @Nullable String addedHolder) { + public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) { mListenerHandler.sendMessage(PooledLambda.obtainMessage( - RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId, - removedHolder, addedHolder)); + RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId)); } @WorkerThread - private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId, - @Nullable String removedHolder, @Nullable String addedHolder) { + private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) { RemoteCallbackList listeners = getListeners(userId); if (listeners != null) { notifyRoleHoldersChangedForListeners(listeners, roleName, userId); @@ -412,12 +408,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C 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 7751397d9c31f..7d774505cac69 100644 --- a/services/core/java/com/android/server/role/RoleUserState.java +++ b/services/core/java/com/android/server/role/RoleUserState.java @@ -281,7 +281,7 @@ public class RoleUserState { } if (changed) { - mCallback.onRoleHoldersChanged(roleName, mUserId, null, packageName); + mCallback.onRoleHoldersChanged(roleName, mUserId); } return true; } @@ -313,7 +313,7 @@ public class RoleUserState { } if (changed) { - mCallback.onRoleHoldersChanged(roleName, mUserId, packageName, null); + mCallback.onRoleHoldersChanged(roleName, mUserId); } return true; } @@ -566,7 +566,6 @@ public class RoleUserState { * @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, - @Nullable String removedHolder, @Nullable String addedHolder); + void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId); } } diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java index 96996a1ae8acb..32533cbf97fb9 100644 --- a/telephony/common/com/android/internal/telephony/SmsApplication.java +++ b/telephony/common/com/android/internal/telephony/SmsApplication.java @@ -17,8 +17,10 @@ package com.android.internal.telephony; import android.Manifest.permission; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; +import android.app.role.OnRoleHoldersChangedListener; import android.app.role.RoleManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; @@ -38,17 +40,20 @@ import android.os.Binder; import android.os.Build; import android.os.Process; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Telephony; import android.provider.Telephony.Sms.Intents; import android.telephony.PackageChangeReceiver; import android.telephony.TelephonyManager; import android.util.Log; +import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -86,6 +91,8 @@ public final class SmsApplication { private static SmsPackageMonitor sSmsPackageMonitor = null; + private static SmsRoleListener sSmsRoleListener = null; + public static class SmsApplicationData { /** * Name of this SMS app for display. @@ -686,7 +693,7 @@ public final class SmsApplication { * {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED} * {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL} */ - public static void broadcastSmsAppChange(Context context, + private static void broadcastSmsAppChange(Context context, UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) { Collection apps = getApplicationCollection(context); @@ -845,9 +852,51 @@ public final class SmsApplication { } } + /** + * Tracks SMS role changes and sends broadcasts for default SMS app change. + */ + private static final class SmsRoleListener implements OnRoleHoldersChangedListener { + private final Context mContext; + private final RoleManager mRoleManager; + private final SparseArray mSmsPackageNames = new SparseArray<>(); + + public SmsRoleListener(@NonNull Context context) { + mContext = context; + mRoleManager = context.getSystemService(RoleManager.class); + final List users = context.getSystemService(UserManager.class) + .getUserHandles(true); + final int usersSize = users.size(); + for (int i = 0; i < usersSize; i++) { + final UserHandle user = users.get(i); + mSmsPackageNames.put(user.getIdentifier(), getSmsPackageName(user)); + } + mRoleManager.addOnRoleHoldersChangedListenerAsUser(context.getMainExecutor(), this, + UserHandle.ALL); + } + + @Override + public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) { + if (!Objects.equals(roleName, RoleManager.ROLE_SMS)) { + return; + } + final int userId = user.getIdentifier(); + final String newSmsPackageName = getSmsPackageName(user); + broadcastSmsAppChange(mContext, user, mSmsPackageNames.get(userId), newSmsPackageName); + mSmsPackageNames.put(userId, newSmsPackageName); + } + + @Nullable + private String getSmsPackageName(@NonNull UserHandle user) { + final List roleHolders = mRoleManager.getRoleHoldersAsUser( + RoleManager.ROLE_SMS, user); + return !roleHolders.isEmpty() ? roleHolders.get(0) : null; + } + } + public static void initSmsPackageMonitor(Context context) { sSmsPackageMonitor = new SmsPackageMonitor(context); sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL); + sSmsRoleListener = new SmsRoleListener(context); } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java index 8013bd8c32f5b..7ee19fb37244b 100644 --- a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java +++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java @@ -46,6 +46,7 @@ import android.content.pm.ServiceInfo; import android.net.Uri; import android.os.Handler; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Telephony; import android.telephony.TelephonyManager; @@ -103,6 +104,7 @@ public class SmsApplicationTest { @Mock private TelephonyManager mTelephonyManager; @Mock private RoleManager mRoleManager; @Mock private PackageManager mPackageManager; + @Mock private UserManager mUserManager; @Mock private AppOpsManager mAppOpsManager; @Before @@ -112,6 +114,7 @@ public class SmsApplicationTest { when(mContext.getSystemService(Context.ROLE_SERVICE)).thenReturn(mRoleManager); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager); when(mContext.createContextAsUser(isNotNull(), anyInt())).thenReturn(mContext); @@ -132,6 +135,8 @@ public class SmsApplicationTest { when(mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)).thenReturn(true); when(mRoleManager.getSmsRoleHolder(anyInt())) .thenReturn(TEST_COMPONENT_NAME.getPackageName()); + when(mUserManager.getUserHandles(true)) + .thenReturn(Collections.singletonList(UserHandle.SYSTEM)); for (String opStr : APP_OPS_TO_CHECK) { when(mAppOpsManager.unsafeCheckOp(