Maintain a set self-certified apps in SatelliteAccessController
This is needed for tracking the applications which opted-in to
use the constrained data satellite network as its default by
adding the following property to the <application> tag of its
manifest:
<property
android:name="android.telephony.PROPERTY_SATELLITE_DATA_OPTIMIZED"
android:value="<package name>" />
Flag: EXEMPT flagged with a kill switch
Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.connectivity.SatelliteAccessControllerTest \
--update-device
Bug: 410731080
Change-Id: I00c0ce5e0d7aac1192272e79a19fbab4e3a5e6f1
This commit is contained in:
parent
830b579081
commit
fbe94c3b00
4 changed files with 298 additions and 40 deletions
|
|
@ -7735,6 +7735,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
final List<PackageInfo> apps = mContext.getPackageManager()
|
||||
.getInstalledPackagesAsUser(GET_PERMISSIONS, user.getIdentifier());
|
||||
mPermissionMonitor.onUserAddedWithInstalledPackageList(user, apps);
|
||||
if (mSatelliteAccessController != null) {
|
||||
mSatelliteAccessController.onUserAddedWithInstalledPackageList(user, apps);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -7757,12 +7760,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
public void onPackageAdded(@NonNull final String packageName, final int uid) {
|
||||
handlePackageChanged(packageName);
|
||||
mPermissionMonitor.onPackageAdded(packageName, uid);
|
||||
if (mSatelliteAccessController != null) {
|
||||
mSatelliteAccessController.onPackageAdded(packageName, uid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageRemoved(@NonNull final String packageName, final int uid) {
|
||||
handlePackageChanged(packageName);
|
||||
mPermissionMonitor.onPackageRemoved(packageName, uid);
|
||||
if (mSatelliteAccessController != null) {
|
||||
mSatelliteAccessController.onPackageRemoved(packageName, uid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ public final class ConnectivityFlags {
|
|||
|
||||
public static final String CLOSE_QUIC_CONNECTION = "close_quic_connection";
|
||||
|
||||
public static final String CONSTRAINED_DATA_SATELLITE_OPTIN =
|
||||
"constrained_data_satellite_optin";
|
||||
|
||||
private boolean mNoRematchAllRequestsOnRegister;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,22 +16,27 @@
|
|||
|
||||
package com.android.server.connectivity;
|
||||
|
||||
import static android.os.Process.INVALID_UID;
|
||||
|
||||
import static com.android.server.connectivity.ConnectivityFlags.CONSTRAINED_DATA_SATELLITE_OPTIN;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.app.role.OnRoleHoldersChangedListener;
|
||||
import android.app.role.RoleManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.net.module.util.DeviceConfigUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
|
@ -45,17 +50,32 @@ import java.util.function.Consumer;
|
|||
*/
|
||||
public class SatelliteAccessController {
|
||||
private static final String TAG = SatelliteAccessController.class.getSimpleName();
|
||||
// Shamelessly copied from telephony/satellite/SatelliteManager.java.
|
||||
@VisibleForTesting
|
||||
public static final String PROPERTY_SATELLITE_DATA_OPTIMIZED =
|
||||
"android.telephony.PROPERTY_SATELLITE_DATA_OPTIMIZED";
|
||||
// This value is taken from android.os.UserHandle#PER_USER_RANGE.
|
||||
@VisibleForTesting
|
||||
public static final int PER_USER_RANGE = 100000;
|
||||
private final Context mContext;
|
||||
private final Dependencies mDeps;
|
||||
private final DefaultMessageRoleListener mDefaultMessageRoleListener;
|
||||
private final Consumer<Set<Integer>> mCallback;
|
||||
private final Handler mConnectivityServiceHandler;
|
||||
private final PackageManager mPackageManager;
|
||||
private final boolean mSupportConstrainedDataSatelliteOptIn;
|
||||
|
||||
// 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<>();
|
||||
|
||||
// Set of UIDs that have declared the
|
||||
// {@code android.telephony.PROPERTY_SATELLITE_DATA_OPTIMIZED} property
|
||||
// with a value of package name in their manifest file. This variable will only be
|
||||
// accessed on the handler thread.
|
||||
private final Set<Integer> mSatelliteDataOptimizedUids = new ArraySet<>();
|
||||
|
||||
/**
|
||||
* Monitor {@link android.app.role.OnRoleHoldersChangedListener#onRoleHoldersChanged(String,
|
||||
* UserHandle)},
|
||||
|
|
@ -104,6 +124,12 @@ public class SatelliteAccessController {
|
|||
@NonNull OnRoleHoldersChangedListener listener, UserHandle user) {
|
||||
mRoleManager.addOnRoleHoldersChangedListenerAsUser(executor, listener, user);
|
||||
}
|
||||
|
||||
/** Return whether constrained data satellite opt-in is supported. */
|
||||
public boolean supportConstrainedDataSatelliteOptIn(Context context) {
|
||||
return DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context,
|
||||
CONSTRAINED_DATA_SATELLITE_OPTIN);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
@ -115,6 +141,8 @@ public class SatelliteAccessController {
|
|||
mDefaultMessageRoleListener = new DefaultMessageRoleListener();
|
||||
mCallback = callback;
|
||||
mConnectivityServiceHandler = connectivityServiceInternalHandler;
|
||||
mPackageManager = mContext.getPackageManager();
|
||||
mSupportConstrainedDataSatelliteOptIn = mDeps.supportConstrainedDataSatelliteOptIn(c);
|
||||
}
|
||||
|
||||
private Set<Integer> updateSatelliteNetworkFallbackUidListCache(List<String> packageNames,
|
||||
|
|
@ -129,7 +157,7 @@ public class SatelliteAccessController {
|
|||
// cache list.
|
||||
if (isSatellitePermissionEnabled(pm, packageName)) {
|
||||
int uid = getUidForPackage(pm, packageName);
|
||||
if (uid != Process.INVALID_UID) {
|
||||
if (uid != INVALID_UID) {
|
||||
fallbackUids.add(uid);
|
||||
}
|
||||
}
|
||||
|
|
@ -150,7 +178,7 @@ public class SatelliteAccessController {
|
|||
|
||||
private int getUidForPackage(PackageManager packageManager, String pkgName) {
|
||||
if (pkgName == null) {
|
||||
return Process.INVALID_UID;
|
||||
return INVALID_UID;
|
||||
}
|
||||
try {
|
||||
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(pkgName, 0);
|
||||
|
|
@ -158,13 +186,13 @@ public class SatelliteAccessController {
|
|||
} catch (PackageManager.NameNotFoundException exception) {
|
||||
Log.e(TAG, "Unable to find uid for package: " + pkgName);
|
||||
}
|
||||
return Process.INVALID_UID;
|
||||
return INVALID_UID;
|
||||
}
|
||||
|
||||
// on Role sms change triggered by OnRoleHoldersChangedListener()
|
||||
private void onRoleSmsChanged(@NonNull UserHandle userHandle) {
|
||||
int userId = userHandle.getIdentifier();
|
||||
if (userId == Process.INVALID_UID) {
|
||||
if (userId == INVALID_UID) {
|
||||
Log.wtf(TAG, "Invalid User Id");
|
||||
return;
|
||||
}
|
||||
|
|
@ -209,34 +237,10 @@ public class SatelliteAccessController {
|
|||
}
|
||||
|
||||
public void start() {
|
||||
mConnectivityServiceHandler.post(this::updateAllUserRoleSmsUids);
|
||||
|
||||
// register sms OnRoleHoldersChangedListener
|
||||
mDefaultMessageRoleListener.register();
|
||||
}
|
||||
|
||||
private void updateAllUserRoleSmsUids() {
|
||||
UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||
// get existing user handles of available users
|
||||
List<UserHandle> existingUsers = userManager.getUserHandles(true /*excludeDying*/);
|
||||
|
||||
// Iterate through the user handles and obtain their uids with role sms and satellite
|
||||
// communication permission
|
||||
Log.i(TAG, "existing users: " + existingUsers);
|
||||
for (UserHandle userHandle : existingUsers) {
|
||||
onRoleSmsChanged(userHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user is removed. See {link #ACTION_USER_REMOVED}.
|
||||
*
|
||||
* @param userHandle The userHandle of the removed user. See {@link #EXTRA_USER_HANDLE}.
|
||||
*/
|
||||
public void onUserRemoved(@NonNull UserHandle userHandle) {
|
||||
updateSatelliteFallbackUidListOnUserRemoval(userHandle.getIdentifier());
|
||||
}
|
||||
|
||||
private void updateSatelliteFallbackUidListOnUserRemoval(int userIdRemoved) {
|
||||
Log.i(TAG, "user id removed:" + userIdRemoved);
|
||||
if (mAllUsersSatelliteNetworkFallbackUidCache.contains(userIdRemoved)) {
|
||||
|
|
@ -244,4 +248,110 @@ public class SatelliteAccessController {
|
|||
reportSatelliteNetworkFallbackUids();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user is added. See {link #ACTION_USER_ADDED}.
|
||||
*
|
||||
* Note that this method will also be called at start up once on the handler thread
|
||||
* to iterate through all existing users.
|
||||
*
|
||||
* @param userHandle The userHandle of the added user. See {@link #EXTRA_USER_HANDLE}.
|
||||
* @param apps The list of packages which is installed on the user.
|
||||
*/
|
||||
public void onUserAddedWithInstalledPackageList(@NonNull UserHandle userHandle,
|
||||
@NonNull List<PackageInfo> apps) {
|
||||
// Obtain uids with role sms and satellite communication permission for the added user.
|
||||
onRoleSmsChanged(userHandle);
|
||||
|
||||
if (!mSupportConstrainedDataSatelliteOptIn) return;
|
||||
|
||||
final Set<Integer> satelliteDataOptimizedAppsForUser =
|
||||
getSatelliteDataOptimizedAppsForUser(apps);
|
||||
Log.i(TAG, "Add SatelliteDataOptimizedApps + for user " + userHandle + ": "
|
||||
+ satelliteDataOptimizedAppsForUser);
|
||||
mSatelliteDataOptimizedUids.addAll(satelliteDataOptimizedAppsForUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user is removed. See {link #ACTION_USER_REMOVED}.
|
||||
*
|
||||
* @param userHandle The integer userHandle of the removed user. See {@link #EXTRA_USER_HANDLE}.
|
||||
*/
|
||||
public void onUserRemoved(@NonNull UserHandle userHandle) {
|
||||
updateSatelliteFallbackUidListOnUserRemoval(userHandle.getIdentifier());
|
||||
if (mSupportConstrainedDataSatelliteOptIn) {
|
||||
removeSatelliteDataOptimizedAppsForUser(userHandle.getIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a package is added.
|
||||
*
|
||||
* @param packageName The name of the new package.
|
||||
* @param uid The uid of the new package.
|
||||
*/
|
||||
public void onPackageAdded(@NonNull final String packageName, final int uid) {
|
||||
if (mSupportConstrainedDataSatelliteOptIn && isSatelliteDataOptimizedApp(packageName)) {
|
||||
mSatelliteDataOptimizedUids.add(uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a package is removed.
|
||||
*
|
||||
* @param packageName The name of the removed package or null.
|
||||
* @param uid containing the integer uid previously assigned to the package.
|
||||
*/
|
||||
public void onPackageRemoved(@NonNull final String packageName, final int uid) {
|
||||
if (!mSupportConstrainedDataSatelliteOptIn) return;
|
||||
|
||||
// Scan for all apps sharing the same uid.
|
||||
final String [] pkgs = mPackageManager.getPackagesForUid(uid);
|
||||
if (pkgs != null) {
|
||||
for (String pkg : pkgs) {
|
||||
if (!pkg.equals(packageName) && isSatelliteDataOptimizedApp(pkg)) {
|
||||
return; // Early return if another satellite-optimized app shares the UID
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the loop completes without returning, it means no other
|
||||
// satellite-optimized app shares the UID.
|
||||
mSatelliteDataOptimizedUids.remove(uid);
|
||||
}
|
||||
|
||||
/** Checks if the given UID is in the set of satellite data optimized UIDs. */
|
||||
@VisibleForTesting
|
||||
public boolean isSatelliteDataOptimizedUid(int uid) {
|
||||
return mSatelliteDataOptimizedUids.contains(uid);
|
||||
}
|
||||
|
||||
/** Gets the number of satellite data optimized UIDs being tracked. */
|
||||
@VisibleForTesting
|
||||
public int getSatelliteDataOptimizedUidCount() {
|
||||
return mSatelliteDataOptimizedUids.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Set<Integer> getSatelliteDataOptimizedAppsForUser(@NonNull List<PackageInfo> apps) {
|
||||
final ArraySet<Integer> uids = new ArraySet<>();
|
||||
for (PackageInfo app : apps) {
|
||||
if (null == app.applicationInfo || app.applicationInfo.uid < 0) continue;
|
||||
if (isSatelliteDataOptimizedApp(app.packageName)) uids.add(app.applicationInfo.uid);
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
private boolean isSatelliteDataOptimizedApp(@NonNull String packageName) {
|
||||
try {
|
||||
final PackageManager.Property property = mPackageManager
|
||||
.getProperty(PROPERTY_SATELLITE_DATA_OPTIMIZED, packageName);
|
||||
return property.isString() && TextUtils.equals(property.getString(), packageName);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSatelliteDataOptimizedAppsForUser(int userIdToRemove) {
|
||||
mSatelliteDataOptimizedUids.removeIf(uid -> uid / PER_USER_RANGE == userIdToRemove);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import android.app.role.OnRoleHoldersChangedListener
|
|||
import android.app.role.RoleManager
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
|
|
@ -27,12 +28,21 @@ import android.os.Looper
|
|||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.util.ArraySet
|
||||
import com.android.server.connectivity.ConnectivityFlags.CONSTRAINED_DATA_SATELLITE_OPTIN
|
||||
import com.android.server.connectivity.SatelliteAccessController.PER_USER_RANGE
|
||||
import com.android.server.connectivity.SatelliteAccessController.PROPERTY_SATELLITE_DATA_OPTIMIZED
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import com.android.testutils.com.android.testutils.SetFeatureFlagsRule
|
||||
import com.android.testutils.com.android.testutils.SetFeatureFlagsRule.FeatureFlag
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.function.Consumer
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
|
|
@ -42,9 +52,9 @@ import org.mockito.ArgumentMatchers.eq
|
|||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.timeout
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when`
|
||||
|
||||
private const val PRIMARY_USER = 0
|
||||
private const val SECONDARY_USER = 10
|
||||
|
|
@ -69,22 +79,38 @@ private val PRIMARY_USER_SMS_APP_UID2 = UserHandle.getUid(PRIMARY_USER, SMS_APP_
|
|||
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)
|
||||
|
||||
private const val TEST_PACKAGE1 = "com.android.package1"
|
||||
private const val TEST_PACKAGE2 = "com.android.package2"
|
||||
private const val TEST_UID1 = 2001
|
||||
private const val TEST_UID2 = 2002 + SECONDARY_USER * PER_USER_RANGE // Under 2nd user.
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
class SatelliteAccessControllerTest {
|
||||
private val context = mock(Context::class.java)
|
||||
private val primaryUserContext = mock(Context::class.java)
|
||||
private val secondaryUserContext = mock(Context::class.java)
|
||||
private val packageManager = mock(PackageManager::class.java)
|
||||
private val mPackageManagerPrimaryUser = mock(PackageManager::class.java)
|
||||
private val mPackageManagerSecondaryUser = mock(PackageManager::class.java)
|
||||
private val mDeps = mock(SatelliteAccessController.Dependencies::class.java)
|
||||
private val mCallback = mock(Consumer::class.java) as Consumer<Set<Int>>
|
||||
private val userManager = mock(UserManager::class.java)
|
||||
private val mHandler = Handler(Looper.getMainLooper())
|
||||
private var mSatelliteAccessController =
|
||||
SatelliteAccessController(context, mDeps, mCallback, mHandler)
|
||||
private lateinit var mSatelliteAccessController: SatelliteAccessController
|
||||
private lateinit var mRoleHolderChangedListener: OnRoleHoldersChangedListener
|
||||
|
||||
private val featureFlags = HashSet<String>()
|
||||
|
||||
// This will set feature flags from @FeatureFlag annotations
|
||||
// into the map before setUp() runs.
|
||||
@get:Rule
|
||||
val setFeatureFlagsRule = SetFeatureFlagsRule(
|
||||
{ name, enabled ->
|
||||
if (enabled == true) featureFlags.add(name) else featureFlags.remove(name) },
|
||||
{ name -> featureFlags.contains(name) }
|
||||
)
|
||||
|
||||
private fun <T> mockService(name: String, clazz: Class<T>, service: T) {
|
||||
doReturn(name).`when`(context).getSystemServiceName(clazz)
|
||||
doReturn(service).`when`(context).getSystemService(name)
|
||||
|
|
@ -99,6 +125,10 @@ class SatelliteAccessControllerTest {
|
|||
fun setup() {
|
||||
doReturn(emptyList<UserHandle>()).`when`(userManager).getUserHandles(true)
|
||||
mockService(Context.USER_SERVICE, UserManager::class.java, userManager)
|
||||
doReturn(packageManager).`when`(context).packageManager
|
||||
doReturn(featureFlags.contains(CONSTRAINED_DATA_SATELLITE_OPTIN))
|
||||
.`when`(mDeps).supportConstrainedDataSatelliteOptIn(any())
|
||||
mSatelliteAccessController = SatelliteAccessController(context, mDeps, mCallback, mHandler)
|
||||
|
||||
doReturn(primaryUserContext).`when`(context).createContextAsUser(PRIMARY_USER_HANDLE, 0)
|
||||
doReturn(mPackageManagerPrimaryUser).`when`(primaryUserContext).packageManager
|
||||
|
|
@ -298,19 +328,6 @@ class SatelliteAccessControllerTest {
|
|||
return future.get()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnStartUpCallbackSatelliteFallbackUidWithExistingUsers() {
|
||||
doReturn(
|
||||
listOf(PRIMARY_USER_HANDLE)
|
||||
).`when`(userManager).getUserHandles(true)
|
||||
doReturn(listOf(SMS_APP1))
|
||||
.`when`(mDeps).getRoleHoldersAsUser(RoleManager.ROLE_SMS, PRIMARY_USER_HANDLE)
|
||||
// At start up, SatelliteAccessController must call CS callback with existing users'
|
||||
// default messaging apps uids.
|
||||
startSatelliteAccessController()
|
||||
verify(mCallback, timeout(500)).accept(setOf(PRIMARY_USER_SMS_APP_UID1))
|
||||
}
|
||||
|
||||
private fun startSatelliteAccessController() {
|
||||
mSatelliteAccessController.start()
|
||||
// Get registered listener using captor
|
||||
|
|
@ -322,4 +339,123 @@ class SatelliteAccessControllerTest {
|
|||
)
|
||||
mRoleHolderChangedListener = listenerCaptor.value
|
||||
}
|
||||
|
||||
private fun makePackageInfo(packageName: String, uid: Int) = PackageInfo().apply {
|
||||
this.packageName = packageName
|
||||
applicationInfo = ApplicationInfo().apply { this.uid = uid }
|
||||
}
|
||||
|
||||
private fun mockGetPackagesForUid(uid: Int, pkgs: Array<String>?) {
|
||||
`when`(packageManager.getPackagesForUid(uid)).thenReturn(pkgs)
|
||||
}
|
||||
|
||||
private fun mockIsSatelliteDataOptimizedApp(packageName: String, isOptimized: Boolean) {
|
||||
val property = mock(PackageManager.Property::class.java)
|
||||
`when`(property.isString).thenReturn(isOptimized)
|
||||
if (isOptimized) {
|
||||
`when`(property.string).thenReturn(packageName)
|
||||
}
|
||||
`when`(packageManager.getProperty(
|
||||
eq(PROPERTY_SATELLITE_DATA_OPTIMIZED),
|
||||
eq(packageName)
|
||||
)).thenReturn(property)
|
||||
}
|
||||
|
||||
@FeatureFlag(name = CONSTRAINED_DATA_SATELLITE_OPTIN)
|
||||
@Test
|
||||
fun testSatelliteOptimizedUids_onPackageAdded() {
|
||||
mockIsSatelliteDataOptimizedApp(TEST_PACKAGE1, true)
|
||||
mSatelliteAccessController.onPackageAdded(TEST_PACKAGE1, TEST_UID1)
|
||||
assertTrue(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 1)
|
||||
}
|
||||
|
||||
@FeatureFlag(name = CONSTRAINED_DATA_SATELLITE_OPTIN)
|
||||
@Test
|
||||
fun testSatelliteOptimizedUids_onPackageAdded_ignoresIfNotSatelliteOptimized() {
|
||||
mockIsSatelliteDataOptimizedApp(TEST_PACKAGE1, false)
|
||||
mSatelliteAccessController.onPackageAdded(TEST_PACKAGE1, TEST_UID1)
|
||||
assertFalse(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 0)
|
||||
}
|
||||
|
||||
@FeatureFlag(name = CONSTRAINED_DATA_SATELLITE_OPTIN)
|
||||
@Test
|
||||
fun testSatelliteOptimizedUids_onPackageRemoved_noOtherShareUid() {
|
||||
mockIsSatelliteDataOptimizedApp(TEST_PACKAGE1, true)
|
||||
mockGetPackagesForUid(TEST_UID1, arrayOf(TEST_PACKAGE1))
|
||||
|
||||
mSatelliteAccessController.onPackageAdded(TEST_PACKAGE1, TEST_UID1)
|
||||
assertTrue(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 1)
|
||||
mSatelliteAccessController.onPackageRemoved(TEST_PACKAGE1, TEST_UID1)
|
||||
assertFalse(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 0)
|
||||
}
|
||||
|
||||
@FeatureFlag(name = CONSTRAINED_DATA_SATELLITE_OPTIN)
|
||||
@Test
|
||||
fun testSatelliteOptimizedUids_onPackageRemoved_otherShareUid() {
|
||||
mockIsSatelliteDataOptimizedApp(TEST_PACKAGE1, true)
|
||||
mockIsSatelliteDataOptimizedApp(TEST_PACKAGE2, true)
|
||||
mockGetPackagesForUid(TEST_UID1, arrayOf(TEST_PACKAGE1, TEST_PACKAGE2))
|
||||
|
||||
// Verify uid is not removed if there is still another package shares the same uid.
|
||||
mSatelliteAccessController.onPackageAdded(TEST_PACKAGE1, TEST_UID1)
|
||||
assertTrue(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 1)
|
||||
mSatelliteAccessController.onPackageRemoved(TEST_PACKAGE1, TEST_UID1)
|
||||
assertTrue(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 1)
|
||||
|
||||
// Verify uid is removed if there is no other package with shared uid.
|
||||
mockGetPackagesForUid(TEST_UID1, null)
|
||||
mSatelliteAccessController.onPackageRemoved(TEST_PACKAGE2, TEST_UID1)
|
||||
assertFalse(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 0)
|
||||
}
|
||||
|
||||
@FeatureFlag(name = CONSTRAINED_DATA_SATELLITE_OPTIN)
|
||||
@Test
|
||||
fun testSatelliteOptimizedUids_onUserAddedRemoved() {
|
||||
mockIsSatelliteDataOptimizedApp(TEST_PACKAGE1, true)
|
||||
mockIsSatelliteDataOptimizedApp(TEST_PACKAGE2, true)
|
||||
val packageInfo1 = makePackageInfo(TEST_PACKAGE1, TEST_UID1)
|
||||
val packageInfo2 = makePackageInfo(TEST_PACKAGE2, TEST_UID2)
|
||||
|
||||
mSatelliteAccessController
|
||||
.onUserAddedWithInstalledPackageList(PRIMARY_USER_HANDLE, listOf(packageInfo1))
|
||||
mSatelliteAccessController
|
||||
.onUserAddedWithInstalledPackageList(SECONDARY_USER_HANDLE, listOf(packageInfo2))
|
||||
assertTrue(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
assertTrue(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID2))
|
||||
|
||||
mSatelliteAccessController.onUserRemoved(SECONDARY_USER_HANDLE)
|
||||
// Verify that the app associated with the non-removed user is not removed.
|
||||
assertTrue(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID1))
|
||||
// Verify that the app associated with the removed user is removed.
|
||||
assertFalse(mSatelliteAccessController.isSatelliteDataOptimizedUid(TEST_UID2))
|
||||
|
||||
mSatelliteAccessController.onUserRemoved(PRIMARY_USER_HANDLE)
|
||||
// Verify everything is removed.
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 0)
|
||||
}
|
||||
|
||||
@FeatureFlag(name = CONSTRAINED_DATA_SATELLITE_OPTIN, enabled = false)
|
||||
@Test
|
||||
fun testSatelliteOptimizedUids_featureDisabled() {
|
||||
mockIsSatelliteDataOptimizedApp(TEST_PACKAGE1, true)
|
||||
val packageInfo1 = makePackageInfo(TEST_PACKAGE1, TEST_UID1)
|
||||
|
||||
// Verify nothing changes and nothing crashes.
|
||||
mSatelliteAccessController
|
||||
.onUserAddedWithInstalledPackageList(PRIMARY_USER_HANDLE, listOf(packageInfo1))
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 0)
|
||||
mSatelliteAccessController.onPackageAdded(TEST_PACKAGE1, TEST_UID1)
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 0)
|
||||
mSatelliteAccessController.onPackageRemoved(TEST_PACKAGE1, TEST_UID1)
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 0)
|
||||
mSatelliteAccessController.onUserRemoved(PRIMARY_USER_HANDLE)
|
||||
assertEquals(mSatelliteAccessController.satelliteDataOptimizedUidCount, 0)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue