diff options
16 files changed, 185 insertions, 62 deletions
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp index 9081af4..49e9688 100644 --- a/common/networkstackclient/Android.bp +++ b/common/networkstackclient/Android.bp @@ -71,7 +71,7 @@ aidl_interface { "src/android/net/TcpKeepalivePacketDataParcelable.aidl", "src/android/net/dhcp/DhcpLeaseParcelable.aidl", "src/android/net/dhcp/DhcpServingParamsParcel.aidl", - "src/android/net/dhcp/IDhcpLeaseCallbacks.aidl", + "src/android/net/dhcp/IDhcpEventCallbacks.aidl", "src/android/net/dhcp/IDhcpServer.aidl", "src/android/net/dhcp/IDhcpServerCallbacks.aidl", "src/android/net/ip/IIpClient.aidl", diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpLeaseCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpEventCallbacks.aidl index 673afe4..dfcaf98 100644 --- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpLeaseCallbacks.aidl +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpEventCallbacks.aidl @@ -16,6 +16,7 @@ // later when a module using the interface is updated, e.g., Mainline modules. package android.net.dhcp; -interface IDhcpLeaseCallbacks { +interface IDhcpEventCallbacks { oneway void onLeasesChanged(in List<android.net.dhcp.DhcpLeaseParcelable> newLeases); + oneway void onNewPrefixRequest(in android.net.IpPrefix currentPrefix); } diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServer.aidl index 3372062..ef936cc 100644 --- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServer.aidl +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServer.aidl @@ -19,7 +19,7 @@ package android.net.dhcp; /* @hide */ interface IDhcpServer { oneway void start(in android.net.INetworkStackStatusCallback cb) = 0; - oneway void startWithCallbacks(in android.net.INetworkStackStatusCallback statusCb, in android.net.dhcp.IDhcpLeaseCallbacks leaseCb) = 3; + oneway void startWithCallbacks(in android.net.INetworkStackStatusCallback statusCb, in android.net.dhcp.IDhcpEventCallbacks eventCb) = 3; oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb) = 1; oneway void stop(in android.net.INetworkStackStatusCallback cb) = 2; const int STATUS_UNKNOWN = 0; diff --git a/common/networkstackclient/src/android/net/dhcp/IDhcpLeaseCallbacks.aidl b/common/networkstackclient/src/android/net/dhcp/IDhcpEventCallbacks.aidl index cf2dfa8..155c528 100644 --- a/common/networkstackclient/src/android/net/dhcp/IDhcpLeaseCallbacks.aidl +++ b/common/networkstackclient/src/android/net/dhcp/IDhcpEventCallbacks.aidl @@ -16,9 +16,10 @@ package android.net.dhcp; +import android.net.IpPrefix; import android.net.dhcp.DhcpLeaseParcelable; -oneway interface IDhcpLeaseCallbacks { +oneway interface IDhcpEventCallbacks { /** * Called when a lease is committed or released on the DHCP server. * @@ -27,4 +28,15 @@ oneway interface IDhcpLeaseCallbacks { * @param newLeases The new list of leases tracked by the server. */ void onLeasesChanged(in List<DhcpLeaseParcelable> newLeases); -}
\ No newline at end of file + + /** + * Called when DHCP server receives DHCPDECLINE message and only if a new IPv4 address prefix + * (e.g. a different subnet prefix) is requested. + * + * <p>When this callback is called, IpServer must call IDhcpServer#updateParams with a new + * prefix, as processing of DHCP packets should be paused until the new prefix and route + * configuration on IpServer is completed. + * @param currentPrefix The current prefix parameter serving on DHCP server. + */ + void onNewPrefixRequest(in IpPrefix currentPrefix); +} diff --git a/common/networkstackclient/src/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/src/android/net/dhcp/IDhcpServer.aidl index dd93174..973ffb0 100644 --- a/common/networkstackclient/src/android/net/dhcp/IDhcpServer.aidl +++ b/common/networkstackclient/src/android/net/dhcp/IDhcpServer.aidl @@ -18,7 +18,7 @@ package android.net.dhcp; import android.net.INetworkStackStatusCallback; import android.net.dhcp.DhcpServingParamsParcel; -import android.net.dhcp.IDhcpLeaseCallbacks; +import android.net.dhcp.IDhcpEventCallbacks; /** @hide */ oneway interface IDhcpServer { @@ -29,7 +29,7 @@ oneway interface IDhcpServer { void start(in INetworkStackStatusCallback cb) = 0; void startWithCallbacks(in INetworkStackStatusCallback statusCb, - in IDhcpLeaseCallbacks leaseCb) = 3; + in IDhcpEventCallbacks eventCb) = 3; void updateParams(in DhcpServingParamsParcel params, in INetworkStackStatusCallback cb) = 1; void stop(in INetworkStackStatusCallback cb) = 2; diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index b9d47dc..249cabf 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -17,12 +17,10 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="notification_channel_name_connected" msgid="1795068343200033922">"கேப்டிவ் போர்டல் அங்கீகரிப்பு"</string> - <!-- no translation found for notification_channel_description_connected (7239184168268014518) --> - <skip /> + <string name="notification_channel_description_connected" msgid="7239184168268014518">"கேப்டிவ் போர்டல் நெட்வொர்க்கில் சாதனம் வெற்றிகரமாக அங்கீகரிக்கப்பட்டதும் அறிவிப்புகள் காட்டப்படும்"</string> <string name="notification_channel_name_network_venue_info" msgid="6526543187249265733">"நெட்வொர்க் முகவரித் தகவல்"</string> <string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"நெட்வொர்க்கிற்கு முகவரித் தகவல் பக்கம் இருப்பதைக் குறிப்பிட அறிவிப்புகள் காட்டப்படும்"</string> <string name="connected" msgid="4563643884927480998">"இணைக்கப்பட்டது"</string> <string name="tap_for_info" msgid="6849746325626883711">"இணைக்கப்பட்டுள்ளது/இணையதளத்தைப் பார்க்க, தட்டவும்"</string> - <!-- no translation found for application_label (8095087899576605955) --> - <skip /> + <string name="application_label" msgid="8095087899576605955">"இணைப்புநிலை நிர்வாகி"</string> </resources> diff --git a/res/values/config.xml b/res/values/config.xml index 13c9326..a2f3959 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -39,6 +39,10 @@ </string-array> <string-array name="config_captive_portal_fallback_probe_specs" translatable="false"> </string-array> + <string-array name="config_captive_portal_http_urls" translatable="false"> + </string-array> + <string-array name="config_captive_portal_https_urls" translatable="false"> + </string-array> <!-- Customized default DNS Servers address. --> <string-array name="config_default_dns_servers" translatable="false"> diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml index 717c5ca..052266d 100644 --- a/res/values/overlayable.xml +++ b/res/values/overlayable.xml @@ -20,6 +20,8 @@ <item type="integer" name="config_captive_portal_dns_probe_timeout"/> <item type="string" name="config_captive_portal_http_url"/> <item type="string" name="config_captive_portal_https_url"/> + <item type="array" name="config_captive_portal_http_urls"/> + <item type="array" name="config_captive_portal_https_urls"/> <item type="array" name="config_captive_portal_fallback_urls"/> <item type="bool" name="config_no_sim_card_uses_neighbor_mcc"/> <!-- Configuration value for DhcpResults --> diff --git a/src/android/net/dhcp/DhcpLeaseRepository.java b/src/android/net/dhcp/DhcpLeaseRepository.java index 1dc2f7f..d0dc389 100644 --- a/src/android/net/dhcp/DhcpLeaseRepository.java +++ b/src/android/net/dhcp/DhcpLeaseRepository.java @@ -89,7 +89,7 @@ class DhcpLeaseRepository { private long mNextExpirationCheck = EXPIRATION_NEVER; @NonNull - private RemoteCallbackList<IDhcpLeaseCallbacks> mLeaseCallbacks = new RemoteCallbackList<>(); + private RemoteCallbackList<IDhcpEventCallbacks> mEventCallbacks = new RemoteCallbackList<>(); static class DhcpLeaseException extends Exception { DhcpLeaseException(String message) { @@ -381,15 +381,15 @@ class DhcpLeaseRepository { leaseParcelables.add(committedLease.toParcelable()); } - final int cbCount = mLeaseCallbacks.beginBroadcast(); + final int cbCount = mEventCallbacks.beginBroadcast(); for (int i = 0; i < cbCount; i++) { try { - mLeaseCallbacks.getBroadcastItem(i).onLeasesChanged(leaseParcelables); + mEventCallbacks.getBroadcastItem(i).onLeasesChanged(leaseParcelables); } catch (RemoteException e) { mLog.e("Could not send lease callback", e); } } - mLeaseCallbacks.finishBroadcast(); + mEventCallbacks.finishBroadcast(); } public void markLeaseDeclined(@NonNull Inet4Address addr) { @@ -425,9 +425,9 @@ class DhcpLeaseRepository { /** * Add callbacks that will be called on leases update. */ - public void addLeaseCallbacks(@NonNull IDhcpLeaseCallbacks cb) { + public void addLeaseCallbacks(@NonNull IDhcpEventCallbacks cb) { Objects.requireNonNull(cb, "Callbacks must be non-null"); - mLeaseCallbacks.register(cb); + mEventCallbacks.register(cb); } /** diff --git a/src/android/net/dhcp/DhcpServer.java b/src/android/net/dhcp/DhcpServer.java index 9c5b3c6..064aa5d 100644 --- a/src/android/net/dhcp/DhcpServer.java +++ b/src/android/net/dhcp/DhcpServer.java @@ -285,11 +285,11 @@ public class DhcpServer extends IDhcpServer.Stub { */ @Override public void startWithCallbacks(@Nullable INetworkStackStatusCallback statusCb, - @Nullable IDhcpLeaseCallbacks leaseCb) { + @Nullable IDhcpEventCallbacks eventCb) { mDeps.checkCaller(); mHandlerThread.start(); mHandler = new ServerHandler(mHandlerThread.getLooper()); - sendMessage(CMD_START_DHCP_SERVER, new Pair<>(statusCb, leaseCb)); + sendMessage(CMD_START_DHCP_SERVER, new Pair<>(statusCb, eventCb)); } /** @@ -356,8 +356,8 @@ public class DhcpServer extends IDhcpServer.Stub { cb = pair.second; break; case CMD_START_DHCP_SERVER: - final Pair<INetworkStackStatusCallback, IDhcpLeaseCallbacks> obj = - (Pair<INetworkStackStatusCallback, IDhcpLeaseCallbacks>) msg.obj; + final Pair<INetworkStackStatusCallback, IDhcpEventCallbacks> obj = + (Pair<INetworkStackStatusCallback, IDhcpEventCallbacks>) msg.obj; cb = obj.first; if (obj.second != null) { mLeaseRepo.addLeaseCallbacks(obj.second); diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java index 9d913fc..bc41549 100644 --- a/src/android/net/util/NetworkStackUtils.java +++ b/src/android/net/util/NetworkStackUtils.java @@ -56,6 +56,18 @@ public class NetworkStackUtils { "captive_portal_other_fallback_urls"; /** + * A comma separated list of URLs used for captive portal detection in addition to the HTTP url + * associated with the CAPTIVE_PORTAL_HTTP_URL settings. + */ + public static final String CAPTIVE_PORTAL_OTHER_HTTP_URLS = "captive_portal_other_http_urls"; + + /** + * A comma separated list of URLs used for network validation. in addition to the HTTPS url + * associated with the CAPTIVE_PORTAL_HTTPS_URL settings. + */ + public static final String CAPTIVE_PORTAL_OTHER_HTTPS_URLS = "captive_portal_other_https_urls"; + + /** * Which User-Agent string to use in the header of the captive portal detection probes. * The User-Agent field is unset when this setting has no value (HttpUrlConnection default). */ @@ -112,6 +124,17 @@ public class NetworkStackUtils { public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; /** + * The default list of HTTP URLs to use for detecting captive portals. + */ + public static final String[] DEFAULT_CAPTIVE_PORTAL_HTTP_URLS = + new String [] {"http://connectivitycheck.gstatic.com/generate_204"}; + /** + * The default list of HTTPS URLs for network validation, to use for confirming internet + * connectivity. + */ + public static final String[] DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS = + new String [] {"https://www.google.com/generate_204"}; + /** * @deprecated Considering boolean experiment flag is likely to cause misconfiguration * particularly when NetworkStack module rolls back to previous version. It's * much safer to determine whether or not to enable one specific experimental diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java index d16fcf5..7ea61fa 100644 --- a/src/com/android/server/connectivity/NetworkMonitor.java +++ b/src/com/android/server/connectivity/NetworkMonitor.java @@ -63,8 +63,12 @@ import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_IGNORE; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_PROMPT; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS; +import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_HTTPS_URLS; +import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_HTTP_URLS; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USER_AGENT; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS; +import static android.net.util.NetworkStackUtils.DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS; +import static android.net.util.NetworkStackUtils.DEFAULT_CAPTIVE_PORTAL_HTTP_URLS; import static android.net.util.NetworkStackUtils.DISMISS_PORTAL_IN_VALIDATED_NETWORK; import static android.net.util.NetworkStackUtils.isEmpty; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; @@ -358,9 +362,11 @@ public class NetworkMonitor extends StateMachine { private final TcpSocketTracker mTcpTracker; // Configuration values for captive portal detection probes. private final String mCaptivePortalUserAgent; - private final URL mCaptivePortalHttpsUrl; - private final URL mCaptivePortalHttpUrl; private final URL[] mCaptivePortalFallbackUrls; + @NonNull + private final URL[] mCaptivePortalHttpUrls; + @NonNull + private final URL[] mCaptivePortalHttpsUrls; @Nullable private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs; @@ -480,8 +486,8 @@ public class NetworkMonitor extends StateMachine { mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled(); mUseHttps = getUseHttpsValidation(); mCaptivePortalUserAgent = getCaptivePortalUserAgent(); - mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl()); - mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl()); + mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls(); + mCaptivePortalHttpUrls = makeCaptivePortalHttpUrls(); mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(); mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs(); mRandom = deps.getRandom(); @@ -615,7 +621,7 @@ public class NetworkMonitor extends StateMachine { private void notifyNetworkTested( int result, @Nullable String redirectUrl, PersistableBundle extras) { try { - if (mCallbackVersion <= 4) { + if (mCallbackVersion <= 5) { mCallback.notifyNetworkTested(result, redirectUrl); } else { mCallback.notifyNetworkTestedWithExtras( @@ -1594,19 +1600,8 @@ public class NetworkMonitor extends StateMachine { try { final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL, null); - - final URL[] settingProviderUrls; - if (!TextUtils.isEmpty(firstUrl)) { - final String otherUrls = mDependencies.getDeviceConfigProperty( - NAMESPACE_CONNECTIVITY, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, ""); - // otherUrls may be empty, but .split() ignores trailing empty strings - final String separator = ","; - final String[] urls = (firstUrl + separator + otherUrls).split(separator); - settingProviderUrls = convertStrings(urls, this::makeURL, new URL[0]); - } else { - settingProviderUrls = new URL[0]; - } - + final URL[] settingProviderUrls = + combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS); return getProbeUrlArrayConfig(settingProviderUrls, R.array.config_captive_portal_fallback_urls, R.array.default_captive_portal_fallback_urls, this::makeURL); @@ -1638,6 +1633,49 @@ public class NetworkMonitor extends StateMachine { } } + private URL[] makeCaptivePortalHttpsUrls() { + final String firstUrl = getCaptivePortalServerHttpsUrl(); + try { + final URL[] settingProviderUrls = + combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_HTTPS_URLS); + return getProbeUrlArrayConfig(settingProviderUrls, + R.array.config_captive_portal_https_urls, + DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS, this::makeURL); + } catch (Exception e) { + // Don't let a misconfiguration bootloop the system. + Log.e(TAG, "Error parsing configured https URLs", e); + // Ensure URL aligned with legacy configuration. + return new URL[]{makeURL(firstUrl)}; + } + } + + private URL[] makeCaptivePortalHttpUrls() { + final String firstUrl = getCaptivePortalServerHttpUrl(); + try { + final URL[] settingProviderUrls = + combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_HTTP_URLS); + return getProbeUrlArrayConfig(settingProviderUrls, + R.array.config_captive_portal_http_urls, + DEFAULT_CAPTIVE_PORTAL_HTTP_URLS, this::makeURL); + } catch (Exception e) { + // Don't let a misconfiguration bootloop the system. + Log.e(TAG, "Error parsing configured http URLs", e); + // Ensure URL aligned with legacy configuration. + return new URL[]{makeURL(firstUrl)}; + } + } + + private URL[] combineCaptivePortalUrls(final String firstUrl, final String name) { + if (TextUtils.isEmpty(firstUrl)) return new URL[0]; + + final String otherUrls = mDependencies.getDeviceConfigProperty( + NAMESPACE_CONNECTIVITY, name, ""); + // otherUrls may be empty, but .split() ignores trailing empty strings + final String separator = ","; + final String[] urls = (firstUrl + separator + otherUrls).split(separator); + return convertStrings(urls, this::makeURL, new URL[0]); + } + /** * Read a setting from a resource or the settings provider. * @@ -1678,6 +1716,24 @@ public class NetworkMonitor extends StateMachine { private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId, @ArrayRes int defaultResId, @NonNull Function<String, T> resourceConverter) { final Resources res = getContextByMccIfNoSimCardOrDefault().getResources(); + return getProbeUrlArrayConfig(providerValue, configResId, res.getStringArray(defaultResId), + resourceConverter); + } + + /** + * Get an array configuration from resources or the settings provider. + * + * <p>The configuration resource is prioritized, then the provider values, then the default + * resource values. + * @param providerValue Values obtained from the setting provider. + * @param configResId ID of the configuration resource. + * @param defaultConfig Values of default configuration. + * @param resourceConverter Converter from the resource strings to stored setting class. Null + * return values are ignored. + */ + private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId, + String[] defaultConfig, @NonNull Function<String, T> resourceConverter) { + final Resources res = getContextByMccIfNoSimCardOrDefault().getResources(); String[] configValue = res.getStringArray(configResId); if (configValue.length == 0) { @@ -1685,7 +1741,7 @@ public class NetworkMonitor extends StateMachine { return providerValue; } - configValue = res.getStringArray(defaultResId); + configValue = defaultConfig; } return convertStrings(configValue, resourceConverter, Arrays.copyOf(providerValue, 0)); @@ -1746,8 +1802,8 @@ public class NetworkMonitor extends StateMachine { } URL pacUrl = null; - URL httpsUrl = mCaptivePortalHttpsUrl; - URL httpUrl = mCaptivePortalHttpUrl; + final URL[] httpsUrls = mCaptivePortalHttpsUrls; + final URL[] httpUrls = mCaptivePortalHttpUrls; // On networks with a PAC instead of fetching a URL that should result in a 204 // response, we instead simply fetch the PAC script. This is done for a few reasons: @@ -1774,7 +1830,8 @@ public class NetworkMonitor extends StateMachine { } } - if ((pacUrl == null) && (httpUrl == null || httpsUrl == null)) { + if ((pacUrl == null) && (httpUrls.length == 0 || httpsUrls.length == 0 + || httpUrls[0] == null || httpsUrls[0] == null)) { return CaptivePortalProbeResult.FAILED; } @@ -1786,9 +1843,9 @@ public class NetworkMonitor extends StateMachine { reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); } else if (mUseHttps) { // Probe results are reported inside sendParallelHttpProbes. - result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl); + result = sendParallelHttpProbes(proxyInfo, httpsUrls[0], httpUrls[0]); } else { - result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); + result = sendDnsAndHttpProbes(proxyInfo, httpUrls[0], ValidationProbeEvent.PROBE_HTTP); reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); } diff --git a/tests/lib/src/com/android/testutils/NetworkStatsUtils.kt b/tests/lib/src/com/android/testutils/NetworkStatsUtils.kt index 51e9e4d..8324b25 100644 --- a/tests/lib/src/com/android/testutils/NetworkStatsUtils.kt +++ b/tests/lib/src/com/android/testutils/NetworkStatsUtils.kt @@ -29,16 +29,24 @@ fun orderInsensitiveEquals( if (compareTime && leftStats.getElapsedRealtime() != rightStats.getElapsedRealtime()) { return false } - if (leftStats.size() != rightStats.size()) return false + + // While operations such as add/subtract will preserve empty entries. This will make + // the result be hard to verify during test. Remove them before comparing since they + // are not really affect correctness. + // TODO (b/152827872): Remove empty entries after addition/subtraction. + val leftTrimmedEmpty = leftStats.removeEmptyEntries() + val rightTrimmedEmpty = rightStats.removeEmptyEntries() + + if (leftTrimmedEmpty.size() != rightTrimmedEmpty.size()) return false val left = NetworkStats.Entry() val right = NetworkStats.Entry() // Order insensitive compare. - for (i in 0 until leftStats.size()) { - leftStats.getValues(i, left) - val j: Int = rightStats.findIndexHinted(left.iface, left.uid, left.set, left.tag, + for (i in 0 until leftTrimmedEmpty.size()) { + leftTrimmedEmpty.getValues(i, left) + val j: Int = rightTrimmedEmpty.findIndexHinted(left.iface, left.uid, left.set, left.tag, left.metered, left.roaming, left.defaultNetwork, i) if (j == -1) return false - rightStats.getValues(j, right) + rightTrimmedEmpty.getValues(j, right) if (left != right) return false } return true @@ -58,5 +66,13 @@ fun assertNetworkStatsEquals( compareTime: Boolean = false ) { assertTrue(orderInsensitiveEquals(expected, actual, compareTime), - "expected: " + expected + "but was: " + actual) + "expected: " + expected + " but was: " + actual) +} + +/** + * Assert that after being parceled then unparceled, {@link NetworkStats} is equal to the original + * object. + */ +fun assertParcelingIsLossless(stats: NetworkStats) { + assertParcelingIsLossless(stats, { a, b -> orderInsensitiveEquals(a, b) }) } diff --git a/tests/lib/src/com/android/testutils/ParcelUtils.kt b/tests/lib/src/com/android/testutils/ParcelUtils.kt index 9cbd053..5784f7c 100644 --- a/tests/lib/src/com/android/testutils/ParcelUtils.kt +++ b/tests/lib/src/com/android/testutils/ParcelUtils.kt @@ -18,13 +18,13 @@ package com.android.testutils import android.os.Parcel import android.os.Parcelable -import kotlin.test.assertEquals +import kotlin.test.assertTrue import kotlin.test.fail /** * Return a new instance of `T` after being parceled then unparceled. */ -fun <T: Parcelable> parcelingRoundTrip(source: T): T { +fun <T : Parcelable> parcelingRoundTrip(source: T): T { val creator: Parcelable.Creator<T> try { creator = source.javaClass.getField("CREATOR").get(null) as Parcelable.Creator<T> @@ -46,13 +46,23 @@ fun <T: Parcelable> parcelingRoundTrip(source: T): T { /** * Assert that after being parceled then unparceled, `source` is equal to the original - * object. + * object. If a customized equals function is provided, uses the provided one. */ -fun <T: Parcelable> assertParcelingIsLossless(source: T) { - assertEquals(source, parcelingRoundTrip(source)) +@JvmOverloads +fun <T : Parcelable> assertParcelingIsLossless( + source: T, + equals: (T, T) -> Boolean = { a, b -> a == b } +) { + val actual = parcelingRoundTrip(source) + assertTrue(equals(source, actual), "Expected $source, but was $actual") } -fun <T: Parcelable> assertParcelSane(obj: T, fieldCount: Int) { +@JvmOverloads +fun <T : Parcelable> assertParcelSane( + obj: T, + fieldCount: Int, + equals: (T, T) -> Boolean = { a, b -> a == b } +) { assertFieldCountEquals(fieldCount, obj::class.java) - assertParcelingIsLossless(obj) + assertParcelingIsLossless(obj, equals) } diff --git a/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java b/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java index 82f9b50..4cd0e6c 100644 --- a/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java +++ b/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java @@ -98,7 +98,7 @@ public class DhcpLeaseRepositoryTest { private DhcpLeaseRepository mRepo; @NonNull @Mock - private IDhcpLeaseCallbacks mCallbacks; + private IDhcpEventCallbacks mCallbacks; private final Binder mCallbacksBinder = new Binder(); private static Inet4Address parseAddr4(String inet4Addr) { diff --git a/tests/unit/src/android/net/dhcp/DhcpServerTest.java b/tests/unit/src/android/net/dhcp/DhcpServerTest.java index a278a88..86f8a25 100644 --- a/tests/unit/src/android/net/dhcp/DhcpServerTest.java +++ b/tests/unit/src/android/net/dhcp/DhcpServerTest.java @@ -119,7 +119,7 @@ public class DhcpServerTest { @NonNull @Mock private DhcpPacketListener mPacketListener; @NonNull @Mock - private IDhcpLeaseCallbacks mLeaseCallbacks; + private IDhcpEventCallbacks mEventCallbacks; @NonNull @Captor private ArgumentCaptor<ByteBuffer> mSentPacketCaptor; @@ -207,9 +207,9 @@ public class DhcpServerTest { @Test public void testStartWithCallbacks() throws Exception { - mServer.startWithCallbacks(mAssertSuccessCallback, mLeaseCallbacks); + mServer.startWithCallbacks(mAssertSuccessCallback, mEventCallbacks); mLooper.processAllMessages(); - verify(mRepository).addLeaseCallbacks(eq(mLeaseCallbacks)); + verify(mRepository).addLeaseCallbacks(eq(mEventCallbacks)); } @Test |