Merge "NetworkCapabilities: Hide copy constructor"
diff --git a/framework/aidl-export/android/net/IpPrefix.aidl b/framework/aidl-export/android/net/IpPrefix.aidl
index 0d70f2a..3495efc 100644
--- a/framework/aidl-export/android/net/IpPrefix.aidl
+++ b/framework/aidl-export/android/net/IpPrefix.aidl
@@ -18,5 +18,5 @@
package android.net;
// @JavaOnlyStableParcelable only affects the parcelable when built as stable aidl (aidl_interface
-// build rule). IpPrefix is also used in cpp but only as non-stable aidl.
-@JavaOnlyStableParcelable parcelable IpPrefix cpp_header "binder/IpPrefix.h";
+// build rule).
+@JavaOnlyStableParcelable parcelable IpPrefix;
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 82d5d6e..f95d377 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -175,10 +175,12 @@
}
public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
- ctor public VpnTransportInfo(int);
+ ctor public VpnTransportInfo(int, @Nullable String);
method public int describeContents();
+ method @NonNull public android.net.VpnTransportInfo makeCopy(long);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
+ field @Nullable public final String sessionId;
field public final int type;
}
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index c6f4e0b..92ed7fc 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -3140,18 +3140,27 @@
}
/**
- * Set a network-independent global http proxy. This is not normally what you want
- * for typical HTTP proxies - they are general network dependent. However if you're
- * doing something unusual like general internal filtering this may be useful. On
- * a private network where the proxy is not accessible, you may break HTTP using this.
+ * Set a network-independent global HTTP proxy.
*
- * @param p A {@link ProxyInfo} object defining the new global
- * HTTP proxy. A {@code null} value will clear the global HTTP proxy.
+ * This sets an HTTP proxy that applies to all networks and overrides any network-specific
+ * proxy. If set, HTTP libraries that are proxy-aware will use this global proxy when
+ * accessing any network, regardless of what the settings for that network are.
+ *
+ * Note that HTTP proxies are by nature typically network-dependent, and setting a global
+ * proxy is likely to break networking on multiple networks. This method is only meant
+ * for device policy clients looking to do general internal filtering or similar use cases.
+ *
+ * {@see #getGlobalProxy}
+ * {@see LinkProperties#getHttpProxy}
+ *
+ * @param p A {@link ProxyInfo} object defining the new global HTTP proxy. Calling this
+ * method with a {@code null} value will clear the global HTTP proxy.
* @hide
*/
+ // Used by Device Policy Manager to set the global proxy.
@SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
- public void setGlobalProxy(@Nullable ProxyInfo p) {
+ public void setGlobalProxy(@Nullable final ProxyInfo p) {
try {
mService.setGlobalProxy(p);
} catch (RemoteException e) {
diff --git a/framework/src/android/net/DnsResolver.java b/framework/src/android/net/DnsResolver.java
index 3f7660f..dac88ad 100644
--- a/framework/src/android/net/DnsResolver.java
+++ b/framework/src/android/net/DnsResolver.java
@@ -500,7 +500,7 @@
try {
resp = resNetworkResult(fd); // Closes fd, marks it invalid.
} catch (ErrnoException e) {
- Log.e(TAG, "resNetworkResult:" + e.toString());
+ Log.w(TAG, "resNetworkResult:" + e.toString());
exception = e;
}
}
diff --git a/framework/src/android/net/VpnTransportInfo.java b/framework/src/android/net/VpnTransportInfo.java
index cd8f4c0..ba83a44 100644
--- a/framework/src/android/net/VpnTransportInfo.java
+++ b/framework/src/android/net/VpnTransportInfo.java
@@ -17,11 +17,14 @@
package android.net;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import java.util.Objects;
@@ -38,8 +41,26 @@
/** Type of this VPN. */
public final int type;
- public VpnTransportInfo(int type) {
+ @Nullable
+ public final String sessionId;
+
+ @Override
+ public long getApplicableRedactions() {
+ return REDACT_FOR_NETWORK_SETTINGS;
+ }
+
+ /**
+ * Create a copy of a {@link VpnTransportInfo} with the sessionId redacted if necessary.
+ */
+ @NonNull
+ public VpnTransportInfo makeCopy(long redactions) {
+ return new VpnTransportInfo(type,
+ ((redactions & REDACT_FOR_NETWORK_SETTINGS) != 0) ? null : sessionId);
+ }
+
+ public VpnTransportInfo(int type, @Nullable String sessionId) {
this.type = type;
+ this.sessionId = sessionId;
}
@Override
@@ -47,17 +68,17 @@
if (!(o instanceof VpnTransportInfo)) return false;
VpnTransportInfo that = (VpnTransportInfo) o;
- return this.type == that.type;
+ return (this.type == that.type) && TextUtils.equals(this.sessionId, that.sessionId);
}
@Override
public int hashCode() {
- return Objects.hash(type);
+ return Objects.hash(type, sessionId);
}
@Override
public String toString() {
- return String.format("VpnTransportInfo{type=%d}", type);
+ return String.format("VpnTransportInfo{type=%d, sessionId=%s}", type, sessionId);
}
@Override
@@ -68,12 +89,13 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(type);
+ dest.writeString(sessionId);
}
public static final @NonNull Creator<VpnTransportInfo> CREATOR =
new Creator<VpnTransportInfo>() {
public VpnTransportInfo createFromParcel(Parcel in) {
- return new VpnTransportInfo(in.readInt());
+ return new VpnTransportInfo(in.readInt(), in.readString());
}
public VpnTransportInfo[] newArray(int size) {
return new VpnTransportInfo[size];
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index c997e2a..629006a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1281,14 +1281,22 @@
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
+ mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
// Listen for user add/removes to inform PermissionMonitor.
// Should run on mHandler to avoid any races.
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_USER_ADDED);
- intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+ final IntentFilter userIntentFilter = new IntentFilter();
+ userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
+ userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mUserAllContext.registerReceiver(mUserIntentReceiver, userIntentFilter,
+ null /* broadcastPermission */, mHandler);
- mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
- mUserAllContext.registerReceiver(mIntentReceiver, intentFilter,
+ // Listen to package add/removes for netd
+ final IntentFilter packageIntentFilter = new IntentFilter();
+ packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ packageIntentFilter.addDataScheme("package");
+ mUserAllContext.registerReceiver(mPackageIntentReceiver, packageIntentFilter,
null /* broadcastPermission */, mHandler);
mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mHandler, mNetd);
@@ -4958,7 +4966,7 @@
}
@Override
- public void setGlobalProxy(final ProxyInfo proxyProperties) {
+ public void setGlobalProxy(@Nullable final ProxyInfo proxyProperties) {
PermissionUtils.enforceNetworkStackPermission(mContext);
mProxyTracker.setGlobalProxy(proxyProperties);
}
@@ -5303,14 +5311,14 @@
}
}
- private void onUserAdded(UserHandle user) {
+ private void onUserAdded(@NonNull final UserHandle user) {
mPermissionMonitor.onUserAdded(user);
if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
handleSetOemNetworkPreference(mOemNetworkPreferences, null);
}
}
- private void onUserRemoved(UserHandle user) {
+ private void onUserRemoved(@NonNull final UserHandle user) {
mPermissionMonitor.onUserRemoved(user);
// If there was a network preference for this user, remove it.
handleSetProfileNetworkPreference(new ProfileNetworkPreferences.Preference(user, null),
@@ -5320,7 +5328,18 @@
}
}
- private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ private void onPackageChanged(@NonNull final String packageName) {
+ // This is necessary in case a package is added or removed, but also when it's replaced to
+ // run as a new UID by its manifest rules. Also, if a separate package shares the same UID
+ // as one in the preferences, then it should follow the same routing as that other package,
+ // which means updating the rules is never to be needed in this case (whether it joins or
+ // leaves a UID with a preference).
+ if (isMappedInOemNetworkPreference(packageName)) {
+ handleSetOemNetworkPreference(mOemNetworkPreferences, null);
+ }
+ }
+
+ private final BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
ensureRunningOnConnectivityServiceThread();
@@ -5343,6 +5362,22 @@
}
};
+ private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ ensureRunningOnConnectivityServiceThread();
+ switch (intent.getAction()) {
+ case Intent.ACTION_PACKAGE_ADDED:
+ case Intent.ACTION_PACKAGE_REMOVED:
+ case Intent.ACTION_PACKAGE_REPLACED:
+ onPackageChanged(intent.getData().getSchemeSpecificPart());
+ break;
+ default:
+ Log.wtf(TAG, "received unexpected intent: " + intent.getAction());
+ }
+ }
+ };
+
private final HashMap<Messenger, NetworkProviderInfo> mNetworkProviderInfos = new HashMap<>();
private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests = new HashMap<>();
@@ -6166,6 +6201,15 @@
@NonNull
private ProfileNetworkPreferences mProfileNetworkPreferences = new ProfileNetworkPreferences();
+ /**
+ * Determine whether a given package has a mapping in the current OemNetworkPreferences.
+ * @param packageName the package name to check existence of a mapping for.
+ * @return true if a mapping exists, false otherwise
+ */
+ private boolean isMappedInOemNetworkPreference(@NonNull final String packageName) {
+ return mOemNetworkPreferences.getNetworkPreferences().containsKey(packageName);
+ }
+
// The always-on request for an Internet-capable network that apps without a specific default
// fall back to.
@VisibleForTesting
@@ -6186,7 +6230,7 @@
* @return the NetworkRequestInfo tracking the given uid.
*/
@NonNull
- private NetworkRequestInfo getDefaultRequestTrackingUid(@NonNull final int uid) {
+ private NetworkRequestInfo getDefaultRequestTrackingUid(final int uid) {
for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
if (nri == mDefaultRequest) {
continue;
@@ -6633,7 +6677,7 @@
mDeps.reportNetworkInterfaceForTransports(mContext, iface,
caps.getTransportTypes());
} catch (Exception e) {
- loge("Exception adding interface: " + e);
+ logw("Exception adding interface: " + e);
}
}
}
@@ -9593,7 +9637,6 @@
new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference);
replaceDefaultNetworkRequestsForPreference(nris);
mOemNetworkPreferences = preference;
- // TODO http://b/176496396 persist data to shared preferences.
if (null != listener) {
try {
@@ -9750,7 +9793,6 @@
// packages are sent on a network preference as the system will watch for
// package installations associated with this network preference and update
// accordingly. This is done so as to minimize race conditions on app install.
- // TODO b/177092163 add app install watching.
continue;
}
}
diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java
index b7a42ec..fee65f0 100644
--- a/tests/net/java/android/net/VpnTransportInfoTest.java
+++ b/tests/net/java/android/net/VpnTransportInfoTest.java
@@ -16,6 +16,9 @@
package android.net;
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
+import static android.net.NetworkCapabilities.REDACT_NONE;
+
import static com.android.testutils.ParcelUtils.assertParcelSane;
import static org.junit.Assert.assertEquals;
@@ -33,23 +36,33 @@
@Test
public void testParceling() {
- VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
- assertParcelSane(v, 1 /* fieldCount */);
+ VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345");
+ assertParcelSane(v, 2 /* fieldCount */);
}
@Test
public void testEqualsAndHashCode() {
- VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
- VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE);
- VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
- VpnTransportInfo v4 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY);
- VpnTransportInfo v5 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM);
+ String session1 = "12345";
+ String session2 = "6789";
+ VpnTransportInfo v11 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
+ VpnTransportInfo v12 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, session1);
+ VpnTransportInfo v13 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
+ VpnTransportInfo v14 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session1);
+ VpnTransportInfo v15 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1);
+ VpnTransportInfo v21 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session2);
- assertNotEquals(v1, v2);
- assertNotEquals(v3, v4);
- assertNotEquals(v4, v5);
+ VpnTransportInfo v31 = v11.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
+ VpnTransportInfo v32 = v13.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
- assertEquals(v1, v3);
- assertEquals(v1.hashCode(), v3.hashCode());
+ assertNotEquals(v11, v12);
+ assertNotEquals(v13, v14);
+ assertNotEquals(v14, v15);
+ assertNotEquals(v14, v21);
+
+ assertEquals(v11, v13);
+ assertEquals(v31, v32);
+ assertEquals(v11.hashCode(), v13.hashCode());
+ assertEquals(REDACT_FOR_NETWORK_SETTINGS, v32.getApplicableRedactions());
+ assertEquals(session1, v15.makeCopy(REDACT_NONE).sessionId);
}
-}
\ No newline at end of file
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 2ed11e0..270941f 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -21,6 +21,9 @@
import static android.Manifest.permission.NETWORK_FACTORY;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.content.Intent.ACTION_PACKAGE_ADDED;
+import static android.content.Intent.ACTION_PACKAGE_REMOVED;
+import static android.content.Intent.ACTION_PACKAGE_REPLACED;
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.ACTION_USER_UNLOCKED;
@@ -1230,10 +1233,12 @@
if (mAgentRegistered) throw new IllegalStateException("already registered");
updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent");
mConfig = new VpnConfig();
+ mConfig.session = "MySession12345";
setUids(uids);
if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
mInterface = VPN_IFNAME;
- mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+ mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
+ mConfig.session));
mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
mNetworkCapabilities);
mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
@@ -2793,10 +2798,14 @@
}
private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
- final String myPackageName = mContext.getPackageName();
- when(mPackageManager.getPackageInfo(eq(myPackageName), eq(GET_PERMISSIONS)))
+ grantUsingBackgroundNetworksPermissionForUid(uid, mContext.getPackageName());
+ }
+
+ private void grantUsingBackgroundNetworksPermissionForUid(
+ final int uid, final String packageName) throws Exception {
+ when(mPackageManager.getPackageInfo(eq(packageName), eq(GET_PERMISSIONS)))
.thenReturn(buildPackageInfo(true, uid));
- mService.mPermissionMonitor.onPackageAdded(myPackageName, uid);
+ mService.mPermissionMonitor.onPackageAdded(packageName, uid);
}
@Test
@@ -10255,6 +10264,12 @@
.thenReturn(applicationInfo);
}
+ private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName)
+ throws Exception {
+ when(mPackageManager.getApplicationInfo(eq(packageName), anyInt()))
+ .thenThrow(new PackageManager.NameNotFoundException(packageName));
+ }
+
private void mockHasSystemFeature(@NonNull final String featureName,
@NonNull final boolean hasFeature) {
when(mPackageManager.hasSystemFeature(eq(featureName)))
@@ -10711,15 +10726,23 @@
@NonNull final UidRangeParcel[] uidRanges,
@NonNull final String testPackageName)
throws Exception {
- mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
-
// These tests work off a single UID therefore using 'start' is valid.
mockGetApplicationInfo(testPackageName, uidRanges[0].start);
+ setOemNetworkPreference(networkPrefToSetup, testPackageName);
+ }
+
+ private void setOemNetworkPreference(final int networkPrefToSetup,
+ @NonNull final String... testPackageNames)
+ throws Exception {
+ mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
+
// Build OemNetworkPreferences object
- final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
- .addNetworkPreference(testPackageName, networkPrefToSetup)
- .build();
+ final OemNetworkPreferences.Builder builder = new OemNetworkPreferences.Builder();
+ for (final String packageName : testPackageNames) {
+ builder.addNetworkPreference(packageName, networkPrefToSetup);
+ }
+ final OemNetworkPreferences pref = builder.build();
// Act on ConnectivityService.setOemNetworkPreference()
final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
@@ -11318,8 +11341,7 @@
// Arrange PackageManager mocks
final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
final UidRangeParcel[] uidRangesSingleUser =
- toUidRangeStableParcels(
- uidRangesForUids(TEST_PACKAGE_UID));
+ toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
final UidRangeParcel[] uidRangesBothUsers =
toUidRangeStableParcels(
uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
@@ -11366,6 +11388,84 @@
false /* shouldDestroyNetwork */);
}
+ @Test
+ public void testMultilayerForPackageChangesEvaluatesCorrectly()
+ throws Exception {
+ @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+ OEM_NETWORK_PREFERENCE_OEM_PAID;
+ final String packageScheme = "package:";
+
+ // Arrange PackageManager mocks
+ final String packageToInstall = "package.to.install";
+ final int packageToInstallUid = 81387;
+ final UidRangeParcel[] uidRangesSinglePackage =
+ toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
+ mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
+ mockGetApplicationInfoThrowsNameNotFound(packageToInstall);
+ setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME, packageToInstall);
+ grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid(), packageToInstall);
+
+ // Verify the starting state. No networks should be connected.
+ verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
+ OEM_PREF_ANY_NET_ID, 0 /* times */,
+ OEM_PREF_ANY_NET_ID, 0 /* times */,
+ false /* shouldDestroyNetwork */);
+
+ // Test that we correctly add the expected values for installed packages.
+ setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
+ verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
+ mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+ OEM_PREF_ANY_NET_ID, 0 /* times */,
+ false /* shouldDestroyNetwork */);
+
+ // Set the system to recognize the package to be installed
+ mockGetApplicationInfo(packageToInstall, packageToInstallUid);
+ final UidRangeParcel[] uidRangesAllPackages =
+ toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID, packageToInstallUid));
+
+ // Send a broadcast indicating a package was installed.
+ final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
+ addedIntent.setData(Uri.parse(packageScheme + packageToInstall));
+ processBroadcast(addedIntent);
+
+ // Test the single package is removed and the combined packages are added.
+ verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage,
+ mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+ mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+ false /* shouldDestroyNetwork */);
+
+ // Set the system to no longer recognize the package to be installed
+ mockGetApplicationInfoThrowsNameNotFound(packageToInstall);
+
+ // Send a broadcast indicating a package was removed.
+ final Intent removedIntent = new Intent(ACTION_PACKAGE_REMOVED);
+ removedIntent.setData(Uri.parse(packageScheme + packageToInstall));
+ processBroadcast(removedIntent);
+
+ // Test the combined packages are removed and the single package is added.
+ verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages,
+ mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+ mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+ false /* shouldDestroyNetwork */);
+
+ // Set the system to change the installed package's uid
+ final int replacedTestPackageUid = TEST_PACKAGE_UID + 1;
+ mockGetApplicationInfo(TEST_PACKAGE_NAME, replacedTestPackageUid);
+ final UidRangeParcel[] uidRangesReplacedPackage =
+ toUidRangeStableParcels(uidRangesForUids(replacedTestPackageUid));
+
+ // Send a broadcast indicating a package was replaced.
+ final Intent replacedIntent = new Intent(ACTION_PACKAGE_REPLACED);
+ replacedIntent.setData(Uri.parse(packageScheme + TEST_PACKAGE_NAME));
+ processBroadcast(replacedIntent);
+
+ // Test the original uid is removed and is replaced with the new uid.
+ verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage,
+ mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+ mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+ false /* shouldDestroyNetwork */);
+ }
+
/**
* Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
* NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback