diff options
13 files changed, 278 insertions, 89 deletions
diff --git a/Android.bp b/Android.bp index 856e11ec110d..b42ee007ab5f 100644 --- a/Android.bp +++ b/Android.bp @@ -872,38 +872,6 @@ aidl_interface { }, } -// TODO(b/77285514): remove this once the last few hidl interfaces have been -// updated to use hwbinder.stubs. -java_library { - name: "hwbinder", - sdk_version: "core_platform", - - srcs: [ - "core/java/android/os/HidlSupport.java", - "core/java/android/annotation/IntDef.java", - "core/java/android/annotation/IntRange.java", - "core/java/android/annotation/NonNull.java", - "core/java/android/annotation/Nullable.java", - "core/java/android/annotation/SystemApi.java", - "core/java/android/annotation/TestApi.java", - "core/java/android/os/HidlMemory.java", - "core/java/android/os/HwBinder.java", - "core/java/android/os/HwBlob.java", - "core/java/android/os/HwParcel.java", - "core/java/android/os/IHwBinder.java", - "core/java/android/os/IHwInterface.java", - "core/java/android/os/DeadObjectException.java", - "core/java/android/os/DeadSystemException.java", - "core/java/android/os/NativeHandle.java", - "core/java/android/os/RemoteException.java", - "core/java/android/util/AndroidException.java", - ], - libs: ["unsupportedappusage"], - - dxflags: ["--core-library"], - installable: false, -} - python_defaults { name: "base_default", version: { diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 3b7a617f2e16..fe8b9d6e4fa0 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -23,6 +23,7 @@ package android.app.usage { package android.content { public abstract class Context { + field public static final String PAC_PROXY_SERVICE = "pac_proxy"; field public static final String TEST_NETWORK_SERVICE = "test_network"; } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index fe9ed27a516f..4293ab0b7f25 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4026,6 +4026,7 @@ public abstract class Context { * @see android.net.PacProxyManager * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final String PAC_PROXY_SERVICE = "pac_proxy"; /** diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index cd6585cd3fa1..5fd0c33ca205 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -30,6 +30,7 @@ import com.android.i18n.timezone.ZoneInfoDb; import java.io.PrintWriter; import java.text.SimpleDateFormat; +import java.time.Instant; import java.time.LocalTime; import java.util.ArrayList; import java.util.Calendar; @@ -43,11 +44,39 @@ import java.util.List; public class TimeUtils { /** @hide */ public TimeUtils() {} /** {@hide} */ - private static SimpleDateFormat sLoggingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final SimpleDateFormat sLoggingFormat = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** @hide */ public static final SimpleDateFormat sDumpDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + + /** + * This timestamp is used in TimeUtils methods and by the SettingsUI to filter time zones + * to only "effective" ones in a country. It is compared against the notUsedAfter metadata that + * Android records for some time zones. + * + * <p>What is notUsedAfter?</p> + * Android chooses to avoid making users choose between functionally identical time zones at the + * expense of not being able to represent local times in the past. + * + * notUsedAfter exists because some time zones can "merge" with other time zones after a given + * point in time (i.e. they change to have identical transitions, offsets, display names, etc.). + * From the notUsedAfter time, the zone will express the same local time as the one it merged + * with. + * + * <p>Why hardcoded?</p> + * Rather than using System.currentTimeMillis(), a timestamp known to be in the recent past is + * used to ensure consistent behavior across devices and time, and avoid assumptions that the + * system clock on a device is currently set correctly. The fixed value should be updated + * occasionally, but it doesn't have to be very often as effective time zones for a country + * don't change very often. + * + * @hide + */ + public static final Instant MIN_USE_DATE_OF_TIMEZONE = + Instant.ofEpochMilli(1546300800000L); // 1/1/2019 00:00 UTC + /** * Tries to return a time zone that would have had the specified offset * and DST value at the specified moment in the specified country. @@ -109,7 +138,7 @@ public class TimeUtils { List<String> timeZoneIds = new ArrayList<>(); for (TimeZoneMapping timeZoneMapping : countryTimeZones.getTimeZoneMappings()) { - if (timeZoneMapping.isShownInPicker()) { + if (timeZoneMapping.isShownInPickerAt(MIN_USE_DATE_OF_TIMEZONE)) { timeZoneIds.add(timeZoneMapping.getTimeZoneId()); } } diff --git a/core/tests/coretests/src/android/window/OWNERS b/core/tests/coretests/src/android/window/OWNERS new file mode 100644 index 000000000000..6c80cf9e5945 --- /dev/null +++ b/core/tests/coretests/src/android/window/OWNERS @@ -0,0 +1,2 @@ +include /services/core/java/com/android/server/wm/OWNERS +charlesccchen@google.com diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt index cd96a1b481b6..f2f5c1b7f7f7 100644 --- a/packages/Connectivity/framework/api/module-lib-current.txt +++ b/packages/Connectivity/framework/api/module-lib-current.txt @@ -176,10 +176,12 @@ package android.net { } 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/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java index c6f4e0b354c4..92ed7fc29eb2 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -3140,18 +3140,27 @@ public class ConnectivityManager { } /** - * 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/packages/Connectivity/framework/src/android/net/DnsResolver.java b/packages/Connectivity/framework/src/android/net/DnsResolver.java index 3f7660f5709a..dac88ad90752 100644 --- a/packages/Connectivity/framework/src/android/net/DnsResolver.java +++ b/packages/Connectivity/framework/src/android/net/DnsResolver.java @@ -500,7 +500,7 @@ public final class DnsResolver { 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/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java index cd8f4c06de65..ba83a44d0d6c 100644 --- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java +++ b/packages/Connectivity/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 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable { /** 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 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable { 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 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable { @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 58a8cf64e45d..629006aa557e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1281,14 +1281,22 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public void setGlobalProxy(final ProxyInfo proxyProperties) { + public void setGlobalProxy(@Nullable final ProxyInfo proxyProperties) { PermissionUtils.enforceNetworkStackPermission(mContext); mProxyTracker.setGlobalProxy(proxyProperties); } @@ -5303,14 +5311,14 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - 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 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - 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 @@ public class ConnectivityService extends IConnectivityManager.Stub } }; + 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 @@ public class ConnectivityService extends IConnectivityManager.Stub @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 @@ public class ConnectivityService extends IConnectivityManager.Stub * @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; @@ -9593,7 +9637,6 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub // 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/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 57c25f6a04a6..0a76bdc21696 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -462,7 +462,7 @@ public class Vpn { .addTransportType(NetworkCapabilities.TRANSPORT_VPN) .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) - .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE)) + .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE, null)) .build(); loadAlwaysOnPackage(); @@ -526,7 +526,7 @@ public class Vpn { private void resetNetworkCapabilities() { mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) .setUids(null) - .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE)) + .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE, null)) .build(); } @@ -1256,7 +1256,7 @@ public class Vpn { capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId, mConfig.allowedApplications, mConfig.disallowedApplications)); - capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType())); + capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType(), mConfig.session)); // Only apps targeting Q and above can explicitly declare themselves as metered. // These VPNs are assumed metered unless they state otherwise. diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java index b7a42ec29356..fee65f06bcad 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 @@ public class VpnTransportInfoTest { @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); - - assertNotEquals(v1, v2); - assertNotEquals(v3, v4); - assertNotEquals(v4, v5); - - assertEquals(v1, v3); - assertEquals(v1.hashCode(), v3.hashCode()); + 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); + + VpnTransportInfo v31 = v11.makeCopy(REDACT_FOR_NETWORK_SETTINGS); + VpnTransportInfo v32 = v13.makeCopy(REDACT_FOR_NETWORK_SETTINGS); + + 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 2ed11e002b3d..270941fdab53 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.CONNECTIVITY_USE_RESTRICTED_NETWORKS; 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { } 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 @@ public class ConnectivityServiceTest { .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 @@ public class ConnectivityServiceTest { @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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { 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 |