diff --git a/service/src/com/android/server/connectivity/SatelliteAccessController.java b/service/src/com/android/server/connectivity/SatelliteAccessController.java index 0968afffbf5bbf659d515d44cd61eb50f04b8a39..b53abce8fe89f144aa5cc3454ec1db2a94694e18 100644 --- a/service/src/com/android/server/connectivity/SatelliteAccessController.java +++ b/service/src/com/android/server/connectivity/SatelliteAccessController.java @@ -26,8 +26,10 @@ import android.content.pm.PackageManager; import android.os.Handler; import android.os.Process; import android.os.UserHandle; +import android.os.UserManager; import android.util.ArraySet; import android.util.Log; +import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; @@ -44,13 +46,18 @@ import java.util.function.Consumer; */ public class SatelliteAccessController { private static final String TAG = SatelliteAccessController.class.getSimpleName(); - private final PackageManager mPackageManager; + private final Context mContext; private final Dependencies mDeps; private final DefaultMessageRoleListener mDefaultMessageRoleListener; + private final UserManager mUserManager; private final Consumer<Set<Integer>> mCallback; - private final Set<Integer> mSatelliteNetworkPreferredUidCache = new ArraySet<>(); private final Handler mConnectivityServiceHandler; + // At this sparseArray, Key is userId and values are uids of SMS apps that are allowed + // to use satellite network as fallback. + private final SparseArray<Set<Integer>> mAllUsersSatelliteNetworkFallbackUidCache = + new SparseArray<>(); + /** * Monitor {@link android.app.role.OnRoleHoldersChangedListener#onRoleHoldersChanged(String, * UserHandle)}, @@ -59,10 +66,10 @@ public class SatelliteAccessController { private final class DefaultMessageRoleListener implements OnRoleHoldersChangedListener { @Override - public void onRoleHoldersChanged(String role, UserHandle user) { + public void onRoleHoldersChanged(String role, UserHandle userHandle) { if (RoleManager.ROLE_SMS.equals(role)) { Log.i(TAG, "ROLE_SMS Change detected "); - onRoleSmsChanged(); + onRoleSmsChanged(userHandle); } } @@ -71,7 +78,7 @@ public class SatelliteAccessController { mDeps.addOnRoleHoldersChangedListenerAsUser( mConnectivityServiceHandler::post, this, UserHandle.ALL); } catch (RuntimeException e) { - Log.e(TAG, "Could not register satellite controller listener due to " + e); + Log.wtf(TAG, "Could not register satellite controller listener due to " + e); } } } @@ -89,9 +96,9 @@ public class SatelliteAccessController { mRoleManager = context.getSystemService(RoleManager.class); } - /** See {@link RoleManager#getRoleHolders(String)} */ - public List<String> getRoleHolders(String roleName) { - return mRoleManager.getRoleHolders(roleName); + /** See {@link RoleManager#getRoleHoldersAsUser(String, UserHandle)} */ + public List<String> getRoleHoldersAsUser(String roleName, UserHandle userHandle) { + return mRoleManager.getRoleHoldersAsUser(roleName, userHandle); } /** See {@link RoleManager#addOnRoleHoldersChangedListenerAsUser} */ @@ -105,81 +112,107 @@ public class SatelliteAccessController { SatelliteAccessController(@NonNull final Context c, @NonNull final Dependencies deps, Consumer<Set<Integer>> callback, @NonNull final Handler connectivityServiceInternalHandler) { + mContext = c; mDeps = deps; - mPackageManager = c.getPackageManager(); + mUserManager = mContext.getSystemService(UserManager.class); mDefaultMessageRoleListener = new DefaultMessageRoleListener(); mCallback = callback; mConnectivityServiceHandler = connectivityServiceInternalHandler; } - private void updateSatelliteNetworkPreferredUidListCache(List<String> packageNames) { - for (String packageName : packageNames) { - // Check if SATELLITE_COMMUNICATION permission is enabled for default sms application - // package before adding it part of satellite network preferred uid cache list. - if (isSatellitePermissionEnabled(packageName)) { - mSatelliteNetworkPreferredUidCache.add(getUidForPackage(packageName)); + private Set<Integer> updateSatelliteNetworkFallbackUidListCache(List<String> packageNames, + @NonNull UserHandle userHandle) { + Set<Integer> fallbackUids = new ArraySet<>(); + PackageManager pm = + mContext.createContextAsUser(userHandle, 0).getPackageManager(); + if (pm != null) { + for (String packageName : packageNames) { + // Check if SATELLITE_COMMUNICATION permission is enabled for default sms + // application package before adding it part of satellite network fallback uid + // cache list. + if (isSatellitePermissionEnabled(pm, packageName)) { + int uid = getUidForPackage(pm, packageName); + if (uid != Process.INVALID_UID) { + fallbackUids.add(uid); + } + } } + } else { + Log.wtf(TAG, "package manager found null"); } + return fallbackUids; } //Check if satellite communication is enabled for the package - private boolean isSatellitePermissionEnabled(String packageName) { - if (mPackageManager != null) { - return mPackageManager.checkPermission( - Manifest.permission.SATELLITE_COMMUNICATION, packageName) - == PackageManager.PERMISSION_GRANTED; - } - return false; + private boolean isSatellitePermissionEnabled(PackageManager packageManager, + String packageName) { + return packageManager.checkPermission( + Manifest.permission.SATELLITE_COMMUNICATION, packageName) + == PackageManager.PERMISSION_GRANTED; } - private int getUidForPackage(String pkgName) { + private int getUidForPackage(PackageManager packageManager, String pkgName) { if (pkgName == null) { return Process.INVALID_UID; } try { - if (mPackageManager != null) { - ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(pkgName, 0); - if (applicationInfo != null) { - return applicationInfo.uid; - } - } + ApplicationInfo applicationInfo = packageManager.getApplicationInfo(pkgName, 0); + return applicationInfo.uid; } catch (PackageManager.NameNotFoundException exception) { Log.e(TAG, "Unable to find uid for package: " + pkgName); } return Process.INVALID_UID; } - //on Role sms change triggered by OnRoleHoldersChangedListener() - private void onRoleSmsChanged() { - final List<String> packageNames = getRoleSmsChangedPackageName(); + // on Role sms change triggered by OnRoleHoldersChangedListener() + // TODO(b/326373613): using UserLifecycleListener, callback to be received when user removed for + // user delete scenario. This to be used to update uid list and ML Layer request can also be + // updated. + private void onRoleSmsChanged(@NonNull UserHandle userHandle) { + int userId = userHandle.getIdentifier(); + if (userId == Process.INVALID_UID) { + Log.wtf(TAG, "Invalid User Id"); + return; + } - // Create a new Set - Set<Integer> previousSatellitePreferredUid = new ArraySet<>( - mSatelliteNetworkPreferredUidCache); + //Returns empty list if no package exists + final List<String> packageNames = + mDeps.getRoleHoldersAsUser(RoleManager.ROLE_SMS, userHandle); - mSatelliteNetworkPreferredUidCache.clear(); + // Store previous satellite fallback uid available + final Set<Integer> prevUidsForUser = + mAllUsersSatelliteNetworkFallbackUidCache.get(userId, new ArraySet<>()); - if (packageNames != null) { - Log.i(TAG, "role_sms_packages: " + packageNames); - // On Role change listener, update the satellite network preferred uid cache list - updateSatelliteNetworkPreferredUidListCache(packageNames); - Log.i(TAG, "satellite_preferred_uid: " + mSatelliteNetworkPreferredUidCache); - } else { - Log.wtf(TAG, "package name was found null"); - } + Log.i(TAG, "currentUser : role_sms_packages: " + userId + " : " + packageNames); + final Set<Integer> newUidsForUser = !packageNames.isEmpty() + ? updateSatelliteNetworkFallbackUidListCache(packageNames, userHandle) + : new ArraySet<>(); + Log.i(TAG, "satellite_fallback_uid: " + newUidsForUser); // on Role change, update the multilayer request at ConnectivityService with updated - // satellite network preferred uid cache list if changed or to revoke for previous default - // sms app - if (!mSatelliteNetworkPreferredUidCache.equals(previousSatellitePreferredUid)) { - Log.i(TAG, "update multi layer request"); - mCallback.accept(mSatelliteNetworkPreferredUidCache); + // satellite network fallback uid cache list of multiple users as applicable + if (newUidsForUser.equals(prevUidsForUser)) { + return; + } + + mAllUsersSatelliteNetworkFallbackUidCache.put(userId, newUidsForUser); + + // Merge all uids of multiple users available + Set<Integer> mergedSatelliteNetworkFallbackUidCache = new ArraySet<>(); + for (int i = 0; i < mAllUsersSatelliteNetworkFallbackUidCache.size(); i++) { + mergedSatelliteNetworkFallbackUidCache.addAll( + mAllUsersSatelliteNetworkFallbackUidCache.valueAt(i)); } + Log.i(TAG, "merged uid list for multi layer request : " + + mergedSatelliteNetworkFallbackUidCache); + + // trigger multiple layer request for satellite network fallback of multi user uids + mCallback.accept(mergedSatelliteNetworkFallbackUidCache); } - private List<String> getRoleSmsChangedPackageName() { + private List<String> getRoleSmsChangedPackageName(UserHandle userHandle) { try { - return mDeps.getRoleHolders(RoleManager.ROLE_SMS); + return mDeps.getRoleHoldersAsUser(RoleManager.ROLE_SMS, userHandle); } catch (RuntimeException e) { Log.wtf(TAG, "Could not get package name at role sms change update due to: " + e); return null; @@ -188,7 +221,16 @@ public class SatelliteAccessController { /** Register OnRoleHoldersChangedListener */ public void start() { - mConnectivityServiceHandler.post(this::onRoleSmsChanged); + mConnectivityServiceHandler.post(this::updateAllUserRoleSmsUids); mDefaultMessageRoleListener.register(); } + + private void updateAllUserRoleSmsUids() { + List<UserHandle> existingUsers = mUserManager.getUserHandles(true /* excludeDying */); + // Iterate through the user handles and obtain their uids with role sms and satellite + // communication permission + for (UserHandle userHandle : existingUsers) { + onRoleSmsChanged(userHandle); + } + } } diff --git a/tests/unit/java/com/android/server/connectivity/SatelliteAccessControllerTest.kt b/tests/unit/java/com/android/server/connectivity/SatelliteAccessControllerTest.kt index 64a515a781972c13498838ef75d7518a4d3179bf..193078b57db06a6416e600d7887a08c51e33200c 100644 --- a/tests/unit/java/com/android/server/connectivity/SatelliteAccessControllerTest.kt +++ b/tests/unit/java/com/android/server/connectivity/SatelliteAccessControllerTest.kt @@ -21,9 +21,12 @@ import android.app.role.RoleManager import android.content.Context import android.content.pm.ApplicationInfo import android.content.pm.PackageManager +import android.content.pm.UserInfo import android.os.Build import android.os.Handler import android.os.UserHandle +import android.util.ArraySet +import com.android.server.makeMockUserManager import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner import org.junit.Before @@ -36,18 +39,31 @@ import org.mockito.ArgumentMatchers.eq import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock import org.mockito.Mockito.never -import org.mockito.Mockito.times import org.mockito.Mockito.verify import java.util.concurrent.Executor import java.util.function.Consumer -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue -private const val DEFAULT_MESSAGING_APP1 = "default_messaging_app_1" -private const val DEFAULT_MESSAGING_APP2 = "default_messaging_app_2" -private const val DEFAULT_MESSAGING_APP1_UID = 1234 -private const val DEFAULT_MESSAGING_APP2_UID = 5678 +private const val USER = 0 +val USER_INFO = UserInfo(USER, "" /* name */, UserInfo.FLAG_PRIMARY) +val USER_HANDLE = UserHandle(USER) +private const val PRIMARY_USER = 0 +private const val SECONDARY_USER = 10 +private val PRIMARY_USER_HANDLE = UserHandle.of(PRIMARY_USER) +private val SECONDARY_USER_HANDLE = UserHandle.of(SECONDARY_USER) +// sms app names +private const val SMS_APP1 = "sms_app_1" +private const val SMS_APP2 = "sms_app_2" +// sms app ids +private const val SMS_APP_ID1 = 100 +private const val SMS_APP_ID2 = 101 +// UID for app1 and app2 on primary user +// These app could become default sms app for user1 +private val PRIMARY_USER_SMS_APP_UID1 = UserHandle.getUid(PRIMARY_USER, SMS_APP_ID1) +private val PRIMARY_USER_SMS_APP_UID2 = UserHandle.getUid(PRIMARY_USER, SMS_APP_ID2) +// UID for app1 and app2 on secondary user +// These app could become default sms app for user2 +private val SECONDARY_USER_SMS_APP_UID1 = UserHandle.getUid(SECONDARY_USER, SMS_APP_ID1) +private val SECONDARY_USER_SMS_APP_UID2 = UserHandle.getUid(SECONDARY_USER, SMS_APP_ID2) @RunWith(DevSdkIgnoreRunner::class) @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) @@ -58,33 +74,36 @@ class SatelliteAccessControllerTest { private val mRoleManager = mock(SatelliteAccessController.Dependencies::class.java) private val mCallback = mock(Consumer::class.java) as Consumer<Set<Int>> - private val mSatelliteAccessController by lazy { - SatelliteAccessController(context, mRoleManager, mCallback, mHandler)} - private var mRoleHolderChangedListener: OnRoleHoldersChangedListener? = null + private val mSatelliteAccessController = + SatelliteAccessController(context, mRoleManager, mCallback, mHandler) + private lateinit var mRoleHolderChangedListener: OnRoleHoldersChangedListener @Before @Throws(PackageManager.NameNotFoundException::class) fun setup() { + makeMockUserManager(USER_INFO, USER_HANDLE) + doReturn(context).`when`(context).createContextAsUser(any(), anyInt()) doReturn(mPackageManager).`when`(context).packageManager + doReturn(PackageManager.PERMISSION_GRANTED) .`when`(mPackageManager) - .checkPermission(Manifest.permission.SATELLITE_COMMUNICATION, DEFAULT_MESSAGING_APP1) + .checkPermission(Manifest.permission.SATELLITE_COMMUNICATION, SMS_APP1) doReturn(PackageManager.PERMISSION_GRANTED) .`when`(mPackageManager) - .checkPermission(Manifest.permission.SATELLITE_COMMUNICATION, DEFAULT_MESSAGING_APP2) + .checkPermission(Manifest.permission.SATELLITE_COMMUNICATION, SMS_APP2) - // Initialise default message application package1 + // Initialise default message application primary user package1 val applicationInfo1 = ApplicationInfo() - applicationInfo1.uid = DEFAULT_MESSAGING_APP1_UID + applicationInfo1.uid = PRIMARY_USER_SMS_APP_UID1 doReturn(applicationInfo1) .`when`(mPackageManager) - .getApplicationInfo(eq(DEFAULT_MESSAGING_APP1), anyInt()) + .getApplicationInfo(eq(SMS_APP1), anyInt()) - // Initialise default message application package2 + // Initialise default message application primary user package2 val applicationInfo2 = ApplicationInfo() - applicationInfo2.uid = DEFAULT_MESSAGING_APP2_UID + applicationInfo2.uid = PRIMARY_USER_SMS_APP_UID2 doReturn(applicationInfo2) .`when`(mPackageManager) - .getApplicationInfo(eq(DEFAULT_MESSAGING_APP2), anyInt()) + .getApplicationInfo(eq(SMS_APP2), anyInt()) // Get registered listener using captor val listenerCaptor = ArgumentCaptor.forClass( @@ -97,80 +116,107 @@ class SatelliteAccessControllerTest { } @Test - fun test_onRoleHoldersChanged_SatellitePreferredUid_Changed() { - doReturn(listOf<String>()).`when`(mRoleManager).getRoleHolders(RoleManager.ROLE_SMS) - val satelliteNetworkPreferredSet = - ArgumentCaptor.forClass(Set::class.java) as ArgumentCaptor<Set<Int>> - mRoleHolderChangedListener?.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.ALL) - verify(mCallback, never()).accept(satelliteNetworkPreferredSet.capture()) - - // check DEFAULT_MESSAGING_APP1 is available as satellite network preferred uid - doReturn(listOf(DEFAULT_MESSAGING_APP1)) - .`when`(mRoleManager).getRoleHolders(RoleManager.ROLE_SMS) - mRoleHolderChangedListener?.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.ALL) - verify(mCallback).accept(satelliteNetworkPreferredSet.capture()) - var satelliteNetworkPreferredUids = satelliteNetworkPreferredSet.value - assertEquals(1, satelliteNetworkPreferredUids.size) - assertTrue(satelliteNetworkPreferredUids.contains(DEFAULT_MESSAGING_APP1_UID)) - assertFalse(satelliteNetworkPreferredUids.contains(DEFAULT_MESSAGING_APP2_UID)) - - // check DEFAULT_MESSAGING_APP1 and DEFAULT_MESSAGING_APP2 is available - // as satellite network preferred uid - val dmas: MutableList<String> = ArrayList() - dmas.add(DEFAULT_MESSAGING_APP1) - dmas.add(DEFAULT_MESSAGING_APP2) - doReturn(dmas).`when`(mRoleManager).getRoleHolders(RoleManager.ROLE_SMS) - mRoleHolderChangedListener?.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.ALL) - verify(mCallback, times(2)) - .accept(satelliteNetworkPreferredSet.capture()) - satelliteNetworkPreferredUids = satelliteNetworkPreferredSet.value - assertEquals(2, satelliteNetworkPreferredUids.size) - assertTrue(satelliteNetworkPreferredUids.contains(DEFAULT_MESSAGING_APP1_UID)) - assertTrue(satelliteNetworkPreferredUids.contains(DEFAULT_MESSAGING_APP2_UID)) - - // check no uid is available as satellite network preferred uid - doReturn(listOf<String>()).`when`(mRoleManager).getRoleHolders(RoleManager.ROLE_SMS) - mRoleHolderChangedListener?.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.ALL) - verify(mCallback, times(3)) - .accept(satelliteNetworkPreferredSet.capture()) - satelliteNetworkPreferredUids = satelliteNetworkPreferredSet.value - assertEquals(0, satelliteNetworkPreferredUids.size) - assertFalse(satelliteNetworkPreferredUids.contains(DEFAULT_MESSAGING_APP1_UID)) - assertFalse(satelliteNetworkPreferredUids.contains(DEFAULT_MESSAGING_APP2_UID)) - - // No Change received at OnRoleSmsChanged, check callback not triggered - doReturn(listOf<String>()).`when`(mRoleManager).getRoleHolders(RoleManager.ROLE_SMS) - mRoleHolderChangedListener?.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.ALL) - verify(mCallback, times(3)) - .accept(satelliteNetworkPreferredSet.capture()) + fun test_onRoleHoldersChanged_SatelliteFallbackUid_Changed_SingleUser() { + doReturn(listOf<String>()).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback, never()).accept(any()) + + // check DEFAULT_MESSAGING_APP1 is available as satellite network fallback uid + doReturn(listOf(SMS_APP1)) + .`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback).accept(setOf(PRIMARY_USER_SMS_APP_UID1)) + + // check SMS_APP2 is available as satellite network Fallback uid + doReturn(listOf(SMS_APP2)).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback).accept(setOf(PRIMARY_USER_SMS_APP_UID2)) + + // check no uid is available as satellite network fallback uid + doReturn(listOf<String>()).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback).accept(ArraySet()) } @Test fun test_onRoleHoldersChanged_NoSatelliteCommunicationPermission() { - doReturn(listOf<Any>()).`when`(mRoleManager).getRoleHolders(RoleManager.ROLE_SMS) - val satelliteNetworkPreferredSet = - ArgumentCaptor.forClass(Set::class.java) as ArgumentCaptor<Set<Int>> - mRoleHolderChangedListener?.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.ALL) - verify(mCallback, never()).accept(satelliteNetworkPreferredSet.capture()) + doReturn(listOf<Any>()).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback, never()).accept(any()) - // check DEFAULT_MESSAGING_APP1 is not available as satellite network preferred uid + // check DEFAULT_MESSAGING_APP1 is not available as satellite network fallback uid // since satellite communication permission not available. doReturn(PackageManager.PERMISSION_DENIED) .`when`(mPackageManager) - .checkPermission(Manifest.permission.SATELLITE_COMMUNICATION, DEFAULT_MESSAGING_APP1) - doReturn(listOf(DEFAULT_MESSAGING_APP1)) - .`when`(mRoleManager).getRoleHolders(RoleManager.ROLE_SMS) - mRoleHolderChangedListener?.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.ALL) - verify(mCallback, never()).accept(satelliteNetworkPreferredSet.capture()) + .checkPermission(Manifest.permission.SATELLITE_COMMUNICATION, SMS_APP1) + doReturn(listOf(SMS_APP1)) + .`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback, never()).accept(any()) } @Test fun test_onRoleHoldersChanged_RoleSms_NotAvailable() { - doReturn(listOf(DEFAULT_MESSAGING_APP1)) - .`when`(mRoleManager).getRoleHolders(RoleManager.ROLE_SMS) - val satelliteNetworkPreferredSet = - ArgumentCaptor.forClass(Set::class.java) as ArgumentCaptor<Set<Int>> - mRoleHolderChangedListener?.onRoleHoldersChanged(RoleManager.ROLE_BROWSER, UserHandle.ALL) - verify(mCallback, never()).accept(satelliteNetworkPreferredSet.capture()) + doReturn(listOf(SMS_APP1)) + .`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_BROWSER, + PRIMARY_USER_HANDLE) + verify(mCallback, never()).accept(any()) + } + + @Test + fun test_onRoleHoldersChanged_SatelliteNetworkFallbackUid_Changed_multiUser() { + doReturn(listOf<String>()).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback, never()).accept(any()) + + // check SMS_APP1 is available as satellite network fallback uid at primary user + doReturn(listOf(SMS_APP1)) + .`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback).accept(setOf(PRIMARY_USER_SMS_APP_UID1)) + + // check SMS_APP2 is available as satellite network fallback uid at primary user + doReturn(listOf(SMS_APP2)).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE) + verify(mCallback).accept(setOf(PRIMARY_USER_SMS_APP_UID2)) + + // check SMS_APP1 is available as satellite network fallback uid at secondary user + val applicationInfo1 = ApplicationInfo() + applicationInfo1.uid = SECONDARY_USER_SMS_APP_UID1 + doReturn(applicationInfo1).`when`(mPackageManager) + .getApplicationInfo(eq(SMS_APP1), anyInt()) + doReturn(listOf(SMS_APP1)).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + SECONDARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, SECONDARY_USER_HANDLE) + verify(mCallback).accept(setOf(PRIMARY_USER_SMS_APP_UID2, SECONDARY_USER_SMS_APP_UID1)) + + // check no uid is available as satellite network fallback uid at primary user + doReturn(listOf<String>()).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + PRIMARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, + PRIMARY_USER_HANDLE) + verify(mCallback).accept(setOf(SECONDARY_USER_SMS_APP_UID1)) + + // check SMS_APP2 is available as satellite network fallback uid at secondary user + applicationInfo1.uid = SECONDARY_USER_SMS_APP_UID2 + doReturn(applicationInfo1).`when`(mPackageManager) + .getApplicationInfo(eq(SMS_APP2), anyInt()) + doReturn(listOf(SMS_APP2)) + .`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, SECONDARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, SECONDARY_USER_HANDLE) + verify(mCallback).accept(setOf(SECONDARY_USER_SMS_APP_UID2)) + + // check no uid is available as satellite network fallback uid at secondary user + doReturn(listOf<String>()).`when`(mRoleManager).getRoleHoldersAsUser(RoleManager.ROLE_SMS, + SECONDARY_USER_HANDLE) + mRoleHolderChangedListener.onRoleHoldersChanged(RoleManager.ROLE_SMS, SECONDARY_USER_HANDLE) + verify(mCallback).accept(ArraySet()) } }