Loading common/networkstackclient/src/android/net/networkstack/ModuleNetworkStackClient.java +8 −11 Original line number Diff line number Diff line Loading @@ -16,12 +16,12 @@ package android.net.networkstack; import static android.content.Context.NETWORK_STACK_SERVICE; import static android.os.Build.VERSION.SDK_INT; import android.annotation.NonNull; import android.content.Context; import android.net.INetworkStackConnector; import android.net.NetworkStack; import android.os.Build; import android.os.IBinder; import android.util.Log; Loading @@ -47,14 +47,14 @@ public class ModuleNetworkStackClient extends NetworkStackClientBase { // TODO(b/149676685): change this check to "< R" once R is defined if (SDK_INT < Build.VERSION_CODES.Q || (SDK_INT == Build.VERSION_CODES.Q && "REL".equals(Build.VERSION.CODENAME))) { // NETWORK_STACK_SERVICE is not available through getSystemService before R // The NetworkStack connector is not available through NetworkStack before R throw new UnsupportedOperationException( "ModuleNetworkStackClient is not supported on API " + SDK_INT); } if (sInstance == null) { sInstance = new ModuleNetworkStackClient(); sInstance.startPolling(packageContext); sInstance.startPolling(); } return sInstance; } Loading @@ -64,10 +64,10 @@ public class ModuleNetworkStackClient extends NetworkStackClientBase { sInstance = null; } private void startPolling(Context context) { private void startPolling() { // If the service is already registered (as it will be most of the time), do not poll and // fulfill requests immediately. final IBinder nss = (IBinder) context.getSystemService(NETWORK_STACK_SERVICE); final IBinder nss = NetworkStack.getService(); if (nss != null) { // Calling onNetworkStackConnected here means that pending oneway Binder calls to the // NetworkStack get sent from the current thread and not a worker thread; this is fine Loading @@ -75,21 +75,18 @@ public class ModuleNetworkStackClient extends NetworkStackClientBase { onNetworkStackConnected(INetworkStackConnector.Stub.asInterface(nss)); return; } new Thread(new PollingRunner(context)).start(); new Thread(new PollingRunner()).start(); } private class PollingRunner implements Runnable { private final Context mContext; private PollingRunner(Context context) { mContext = context; } private PollingRunner() {} @Override public void run() { // Block until the NetworkStack connector is registered in ServiceManager. IBinder nss; while ((nss = (IBinder) mContext.getSystemService(NETWORK_STACK_SERVICE)) == null) { while ((nss = NetworkStack.getService()) == null) { try { Thread.sleep(200); } catch (InterruptedException e) { Loading res/values/strings.xml +4 −11 Original line number Diff line number Diff line Loading @@ -31,22 +31,15 @@ information page, so that the user can access that page. [CHAR LIMIT=300] --> <string name="notification_channel_description_network_venue_info">Notifications shown to indicate the network has a venue information page</string> <!-- Notifications are shown after the user logs in to a captive portal network, to indicate that the network should now have internet connectivity. This is the title of the notification, indicating that the device is connected to the network with the SSID given as parameter. [CHAR LIMIT=50] --> <string name="connected_to_ssid_param1">Connected to %1$s</string> <!-- A notification is shown after the user logs in to a captive portal network, to indicate that the network should now have internet connectivity. This is the title of the notification, indicating that the device is connected to the network without SSID information. [CHAR LIMIT=50] --> that the network should now have internet connectivity. This is the description of the notification, indicating that the device is connected to the network. [CHAR LIMIT=50] --> <string name="connected">Connected</string> <!-- Notifications are shown when a user connects to a network that advertises a venue information page, so that the user can access that page. This is the message of information page, so that the user can access that page. This is the description of the notification. [CHAR LIMIT=50] --> <string name="tap_for_info">Tap for venue information</string> <string name="tap_for_info">Connected / Tap to view website</string> <!-- The label of application. It's also a sender name of notification. [CHAR LIMIT=50]--> <string name="application_label">Connectivity Manager</string> Loading src/com/android/networkstack/NetworkStackNotifier.java +14 −16 Original line number Diff line number Diff line Loading @@ -181,6 +181,9 @@ public class NetworkStackNotifier { final TrackedNetworkStatus networkStatus = mNetworkStatus.get(network); // The required network attributes callbacks were not fired yet for this network if (networkStatus == null) return; // Don't show the notification when SSID is unknown to prevent sending something vague to // the user. final boolean hasSsid = !TextUtils.isEmpty(getSsid(networkStatus)); final CaptivePortalDataShim capportData = getCaptivePortalData(networkStatus); final boolean showVenueInfo = capportData != null && capportData.getVenueInfoUrl() != null Loading @@ -191,9 +194,11 @@ public class NetworkStackNotifier { && isVenueInfoNotificationEnabled() // Most browsers do not yet support opening a page on a non-default network, so the // venue info link should not be shown if the network is not the default one. && network.equals(mDefaultNetwork); && network.equals(mDefaultNetwork) && hasSsid; final boolean showValidated = networkStatus.mValidatedNotificationPending && networkStatus.isValidated(); networkStatus.mValidatedNotificationPending && networkStatus.isValidated() && hasSsid; final String notificationTag = getNotificationTag(network); final Resources res = mContext.getResources(); Loading @@ -216,7 +221,7 @@ public class NetworkStackNotifier { // channel even if the notification contains venue info: the "venue info" notification // then doubles as a "connected" notification. final String channel = showValidated ? CHANNEL_CONNECTED : CHANNEL_VENUE_INFO; builder = getNotificationBuilder(channel, networkStatus, res) builder = getNotificationBuilder(channel, networkStatus, res, getSsid(networkStatus)) .setContentText(res.getString(R.string.tap_for_info)) .setContentIntent(mDependencies.getActivityPendingIntent( getContextAsUser(mContext, UserHandle.CURRENT), Loading @@ -226,8 +231,10 @@ public class NetworkStackNotifier { } else if (showValidated) { if (networkStatus.mShownNotification == NOTE_CONNECTED) return; builder = getNotificationBuilder(CHANNEL_CONNECTED, networkStatus, res) builder = getNotificationBuilder(CHANNEL_CONNECTED, networkStatus, res, getSsid(networkStatus)) .setTimeoutAfter(CONNECTED_NOTIFICATION_TIMEOUT_MS) .setContentText(res.getString(R.string.connected)) .setContentIntent(mDependencies.getActivityPendingIntent( getContextAsUser(mContext, UserHandle.CURRENT), new Intent(Settings.ACTION_WIFI_SETTINGS), Loading Loading @@ -256,9 +263,10 @@ public class NetworkStackNotifier { } private Notification.Builder getNotificationBuilder(@NonNull String channelId, @NonNull TrackedNetworkStatus networkStatus, @NonNull Resources res) { @NonNull TrackedNetworkStatus networkStatus, @NonNull Resources res, @NonNull String ssid) { return new Notification.Builder(mContext, channelId) .setContentTitle(getConnectedNotificationTitle(res, networkStatus)) .setContentTitle(ssid) .setSmallIcon(R.drawable.icon_wifi); } Loading @@ -279,16 +287,6 @@ public class NetworkStackNotifier { return mNotificationManager.getNotificationChannel(CHANNEL_VENUE_INFO) != null; } private String getConnectedNotificationTitle(@NonNull Resources res, @NonNull TrackedNetworkStatus status) { final String ssid = getSsid(status); if (TextUtils.isEmpty(ssid)) { return res.getString(R.string.connected); } return res.getString(R.string.connected_to_ssid_param1, ssid); } private static String getNotificationTag(@NonNull Network network) { return Long.toString(network.getNetworkHandle()); } Loading tests/unit/src/android/net/networkstack/ModuleNetworkStackClientTest.kt +13 −6 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.net.IIpMemoryStoreCallbacks import android.net.INetworkMonitorCallbacks import android.net.INetworkStackConnector import android.net.Network import android.net.NetworkStack import android.net.dhcp.DhcpServingParamsParcel import android.net.dhcp.IDhcpServerCallbacks import android.net.ip.IIpClientCallbacks Loading @@ -28,6 +29,8 @@ import android.os.Build import android.os.IBinder import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.networkstack.apishim.ShimUtils import org.junit.After import org.junit.Assume.assumeTrue Loading @@ -36,11 +39,11 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.Mock import org.mockito.Mockito.doReturn import org.mockito.Mockito.never import org.mockito.Mockito.timeout import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.MockitoSession @RunWith(AndroidJUnit4::class) @SmallTest Loading @@ -49,6 +52,8 @@ class ModuleNetworkStackClientTest { private val TEST_NETWORK = Network(43) private val TEST_TIMEOUT_MS = 500L private var mSession: MockitoSession? = null @Mock private lateinit var mContext: Context @Mock Loading @@ -68,6 +73,7 @@ class ModuleNetworkStackClientTest { fun setUp() { // ModuleNetworkStackClient is only available after Q assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) mSession = mockitoSession().spyStatic(NetworkStack::class.java).startMocking() MockitoAnnotations.initMocks(this) doReturn(mConnector).`when`(mConnectorBinder).queryLocalInterface( INetworkStackConnector::class.qualifiedName!!) Loading @@ -75,12 +81,13 @@ class ModuleNetworkStackClientTest { @After fun tearDown() { mSession?.finishMocking() ModuleNetworkStackClient.resetInstanceForTest() } @Test fun testIpClientServiceAvailableImmediately() { doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } ModuleNetworkStackClient.getInstance(mContext).makeIpClient(TEST_IFNAME, mIpClientCb) verify(mConnector).makeIpClient(TEST_IFNAME, mIpClientCb) } Loading @@ -91,14 +98,14 @@ class ModuleNetworkStackClientTest { Thread.sleep(TEST_TIMEOUT_MS) verify(mConnector, never()).makeIpClient(any(), any()) doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } // Use a longer timeout as polling can cause larger delays verify(mConnector, timeout(TEST_TIMEOUT_MS * 4)).makeIpClient(TEST_IFNAME, mIpClientCb) } @Test fun testDhcpServerAvailableImmediately() { doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } val testParams = DhcpServingParamsParcel() ModuleNetworkStackClient.getInstance(mContext).makeDhcpServer(TEST_IFNAME, testParams, mDhcpServerCb) Loading @@ -107,7 +114,7 @@ class ModuleNetworkStackClientTest { @Test fun testNetworkMonitorAvailableImmediately() { doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } val testName = "NetworkMonitorName" ModuleNetworkStackClient.getInstance(mContext).makeNetworkMonitor(TEST_NETWORK, testName, mNetworkMonitorCb) Loading @@ -116,7 +123,7 @@ class ModuleNetworkStackClientTest { @Test fun testIpMemoryStoreAvailableImmediately() { doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } ModuleNetworkStackClient.getInstance(mContext).fetchIpMemoryStore(mIpMemoryStoreCb) verify(mConnector).fetchIpMemoryStore(mIpMemoryStoreCb) } Loading tests/unit/src/com/android/networkstack/NetworkStackNotifierTest.kt +14 −16 Original line number Diff line number Diff line Loading @@ -106,8 +106,8 @@ class NetworkStackNotifierTest { .addTransportType(TRANSPORT_WIFI) .addCapability(NET_CAPABILITY_VALIDATED) private val TEST_CONNECTED_NO_SSID_TITLE = "Connected without SSID" private val TEST_CONNECTED_SSID_TITLE = "Connected to TestSsid" private val TEST_CONNECTED_DESCRIPTION = "Connected" private val TEST_VENUE_DESCRIPTION = "Connected / Tap to view website" private val TEST_VENUE_INFO_URL = "https://testvenue.example.com/info" private val EMPTY_CAPPORT_LP = LinkProperties() Loading @@ -123,9 +123,8 @@ class NetworkStackNotifierTest { MockitoAnnotations.initMocks(this) mLooper = TestableLooper.get(this) doReturn(mResources).`when`(mContext).resources doReturn(TEST_CONNECTED_NO_SSID_TITLE).`when`(mResources).getString(R.string.connected) doReturn(TEST_CONNECTED_SSID_TITLE).`when`(mResources).getString( R.string.connected_to_ssid_param1, TEST_SSID) doReturn(TEST_CONNECTED_DESCRIPTION).`when`(mResources).getString(R.string.connected) doReturn(TEST_VENUE_DESCRIPTION).`when`(mResources).getString(R.string.tap_for_info) // applicationInfo is used by Notification.Builder val realContext = InstrumentationRegistry.getInstrumentation().context Loading Loading @@ -201,19 +200,15 @@ class NetworkStackNotifierTest { mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) mLooper.processAllMessages() verifyConnectedNotification() verify(mResources).getString(R.string.connected) verifyWifiSettingsIntent(mIntentCaptor.value) verifyCanceledNotificationAfterNetworkLost() // There is no notification when SSID is not set. verify(mNm, never()).notify(any(), anyInt(), any()) } @Test fun testConnectedNotification_WithSsid() { // NetworkCapabilities#getSSID is not available for API <= Q assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES) .setSSID(TEST_SSID) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(EMPTY_CAPABILITIES) mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) Loading @@ -221,7 +216,7 @@ class NetworkStackNotifierTest { mLooper.processAllMessages() verifyConnectedNotification() verify(mResources).getString(R.string.connected_to_ssid_param1, TEST_SSID) verify(mResources).getString(R.string.connected) verifyWifiSettingsIntent(mIntentCaptor.value) verifyCanceledNotificationAfterNetworkLost() } Loading @@ -233,7 +228,8 @@ class NetworkStackNotifierTest { mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) onLinkPropertiesChanged(TEST_CAPPORT_LP) onDefaultNetworkAvailable(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) mLooper.processAllMessages() Loading @@ -251,7 +247,8 @@ class NetworkStackNotifierTest { mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) onLinkPropertiesChanged(TEST_CAPPORT_LP) onDefaultNetworkAvailable(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) mLooper.processAllMessages() verifyConnectedNotification() Loading @@ -266,7 +263,8 @@ class NetworkStackNotifierTest { assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) onLinkPropertiesChanged(TEST_CAPPORT_LP) onDefaultNetworkAvailable(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) mLooper.processAllMessages() verify(mNm).notify(eq(TEST_NETWORK_TAG), mNoteIdCaptor.capture(), mNoteCaptor.capture()) Loading Loading
common/networkstackclient/src/android/net/networkstack/ModuleNetworkStackClient.java +8 −11 Original line number Diff line number Diff line Loading @@ -16,12 +16,12 @@ package android.net.networkstack; import static android.content.Context.NETWORK_STACK_SERVICE; import static android.os.Build.VERSION.SDK_INT; import android.annotation.NonNull; import android.content.Context; import android.net.INetworkStackConnector; import android.net.NetworkStack; import android.os.Build; import android.os.IBinder; import android.util.Log; Loading @@ -47,14 +47,14 @@ public class ModuleNetworkStackClient extends NetworkStackClientBase { // TODO(b/149676685): change this check to "< R" once R is defined if (SDK_INT < Build.VERSION_CODES.Q || (SDK_INT == Build.VERSION_CODES.Q && "REL".equals(Build.VERSION.CODENAME))) { // NETWORK_STACK_SERVICE is not available through getSystemService before R // The NetworkStack connector is not available through NetworkStack before R throw new UnsupportedOperationException( "ModuleNetworkStackClient is not supported on API " + SDK_INT); } if (sInstance == null) { sInstance = new ModuleNetworkStackClient(); sInstance.startPolling(packageContext); sInstance.startPolling(); } return sInstance; } Loading @@ -64,10 +64,10 @@ public class ModuleNetworkStackClient extends NetworkStackClientBase { sInstance = null; } private void startPolling(Context context) { private void startPolling() { // If the service is already registered (as it will be most of the time), do not poll and // fulfill requests immediately. final IBinder nss = (IBinder) context.getSystemService(NETWORK_STACK_SERVICE); final IBinder nss = NetworkStack.getService(); if (nss != null) { // Calling onNetworkStackConnected here means that pending oneway Binder calls to the // NetworkStack get sent from the current thread and not a worker thread; this is fine Loading @@ -75,21 +75,18 @@ public class ModuleNetworkStackClient extends NetworkStackClientBase { onNetworkStackConnected(INetworkStackConnector.Stub.asInterface(nss)); return; } new Thread(new PollingRunner(context)).start(); new Thread(new PollingRunner()).start(); } private class PollingRunner implements Runnable { private final Context mContext; private PollingRunner(Context context) { mContext = context; } private PollingRunner() {} @Override public void run() { // Block until the NetworkStack connector is registered in ServiceManager. IBinder nss; while ((nss = (IBinder) mContext.getSystemService(NETWORK_STACK_SERVICE)) == null) { while ((nss = NetworkStack.getService()) == null) { try { Thread.sleep(200); } catch (InterruptedException e) { Loading
res/values/strings.xml +4 −11 Original line number Diff line number Diff line Loading @@ -31,22 +31,15 @@ information page, so that the user can access that page. [CHAR LIMIT=300] --> <string name="notification_channel_description_network_venue_info">Notifications shown to indicate the network has a venue information page</string> <!-- Notifications are shown after the user logs in to a captive portal network, to indicate that the network should now have internet connectivity. This is the title of the notification, indicating that the device is connected to the network with the SSID given as parameter. [CHAR LIMIT=50] --> <string name="connected_to_ssid_param1">Connected to %1$s</string> <!-- A notification is shown after the user logs in to a captive portal network, to indicate that the network should now have internet connectivity. This is the title of the notification, indicating that the device is connected to the network without SSID information. [CHAR LIMIT=50] --> that the network should now have internet connectivity. This is the description of the notification, indicating that the device is connected to the network. [CHAR LIMIT=50] --> <string name="connected">Connected</string> <!-- Notifications are shown when a user connects to a network that advertises a venue information page, so that the user can access that page. This is the message of information page, so that the user can access that page. This is the description of the notification. [CHAR LIMIT=50] --> <string name="tap_for_info">Tap for venue information</string> <string name="tap_for_info">Connected / Tap to view website</string> <!-- The label of application. It's also a sender name of notification. [CHAR LIMIT=50]--> <string name="application_label">Connectivity Manager</string> Loading
src/com/android/networkstack/NetworkStackNotifier.java +14 −16 Original line number Diff line number Diff line Loading @@ -181,6 +181,9 @@ public class NetworkStackNotifier { final TrackedNetworkStatus networkStatus = mNetworkStatus.get(network); // The required network attributes callbacks were not fired yet for this network if (networkStatus == null) return; // Don't show the notification when SSID is unknown to prevent sending something vague to // the user. final boolean hasSsid = !TextUtils.isEmpty(getSsid(networkStatus)); final CaptivePortalDataShim capportData = getCaptivePortalData(networkStatus); final boolean showVenueInfo = capportData != null && capportData.getVenueInfoUrl() != null Loading @@ -191,9 +194,11 @@ public class NetworkStackNotifier { && isVenueInfoNotificationEnabled() // Most browsers do not yet support opening a page on a non-default network, so the // venue info link should not be shown if the network is not the default one. && network.equals(mDefaultNetwork); && network.equals(mDefaultNetwork) && hasSsid; final boolean showValidated = networkStatus.mValidatedNotificationPending && networkStatus.isValidated(); networkStatus.mValidatedNotificationPending && networkStatus.isValidated() && hasSsid; final String notificationTag = getNotificationTag(network); final Resources res = mContext.getResources(); Loading @@ -216,7 +221,7 @@ public class NetworkStackNotifier { // channel even if the notification contains venue info: the "venue info" notification // then doubles as a "connected" notification. final String channel = showValidated ? CHANNEL_CONNECTED : CHANNEL_VENUE_INFO; builder = getNotificationBuilder(channel, networkStatus, res) builder = getNotificationBuilder(channel, networkStatus, res, getSsid(networkStatus)) .setContentText(res.getString(R.string.tap_for_info)) .setContentIntent(mDependencies.getActivityPendingIntent( getContextAsUser(mContext, UserHandle.CURRENT), Loading @@ -226,8 +231,10 @@ public class NetworkStackNotifier { } else if (showValidated) { if (networkStatus.mShownNotification == NOTE_CONNECTED) return; builder = getNotificationBuilder(CHANNEL_CONNECTED, networkStatus, res) builder = getNotificationBuilder(CHANNEL_CONNECTED, networkStatus, res, getSsid(networkStatus)) .setTimeoutAfter(CONNECTED_NOTIFICATION_TIMEOUT_MS) .setContentText(res.getString(R.string.connected)) .setContentIntent(mDependencies.getActivityPendingIntent( getContextAsUser(mContext, UserHandle.CURRENT), new Intent(Settings.ACTION_WIFI_SETTINGS), Loading Loading @@ -256,9 +263,10 @@ public class NetworkStackNotifier { } private Notification.Builder getNotificationBuilder(@NonNull String channelId, @NonNull TrackedNetworkStatus networkStatus, @NonNull Resources res) { @NonNull TrackedNetworkStatus networkStatus, @NonNull Resources res, @NonNull String ssid) { return new Notification.Builder(mContext, channelId) .setContentTitle(getConnectedNotificationTitle(res, networkStatus)) .setContentTitle(ssid) .setSmallIcon(R.drawable.icon_wifi); } Loading @@ -279,16 +287,6 @@ public class NetworkStackNotifier { return mNotificationManager.getNotificationChannel(CHANNEL_VENUE_INFO) != null; } private String getConnectedNotificationTitle(@NonNull Resources res, @NonNull TrackedNetworkStatus status) { final String ssid = getSsid(status); if (TextUtils.isEmpty(ssid)) { return res.getString(R.string.connected); } return res.getString(R.string.connected_to_ssid_param1, ssid); } private static String getNotificationTag(@NonNull Network network) { return Long.toString(network.getNetworkHandle()); } Loading
tests/unit/src/android/net/networkstack/ModuleNetworkStackClientTest.kt +13 −6 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.net.IIpMemoryStoreCallbacks import android.net.INetworkMonitorCallbacks import android.net.INetworkStackConnector import android.net.Network import android.net.NetworkStack import android.net.dhcp.DhcpServingParamsParcel import android.net.dhcp.IDhcpServerCallbacks import android.net.ip.IIpClientCallbacks Loading @@ -28,6 +29,8 @@ import android.os.Build import android.os.IBinder import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.networkstack.apishim.ShimUtils import org.junit.After import org.junit.Assume.assumeTrue Loading @@ -36,11 +39,11 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.Mock import org.mockito.Mockito.doReturn import org.mockito.Mockito.never import org.mockito.Mockito.timeout import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.MockitoSession @RunWith(AndroidJUnit4::class) @SmallTest Loading @@ -49,6 +52,8 @@ class ModuleNetworkStackClientTest { private val TEST_NETWORK = Network(43) private val TEST_TIMEOUT_MS = 500L private var mSession: MockitoSession? = null @Mock private lateinit var mContext: Context @Mock Loading @@ -68,6 +73,7 @@ class ModuleNetworkStackClientTest { fun setUp() { // ModuleNetworkStackClient is only available after Q assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) mSession = mockitoSession().spyStatic(NetworkStack::class.java).startMocking() MockitoAnnotations.initMocks(this) doReturn(mConnector).`when`(mConnectorBinder).queryLocalInterface( INetworkStackConnector::class.qualifiedName!!) Loading @@ -75,12 +81,13 @@ class ModuleNetworkStackClientTest { @After fun tearDown() { mSession?.finishMocking() ModuleNetworkStackClient.resetInstanceForTest() } @Test fun testIpClientServiceAvailableImmediately() { doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } ModuleNetworkStackClient.getInstance(mContext).makeIpClient(TEST_IFNAME, mIpClientCb) verify(mConnector).makeIpClient(TEST_IFNAME, mIpClientCb) } Loading @@ -91,14 +98,14 @@ class ModuleNetworkStackClientTest { Thread.sleep(TEST_TIMEOUT_MS) verify(mConnector, never()).makeIpClient(any(), any()) doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } // Use a longer timeout as polling can cause larger delays verify(mConnector, timeout(TEST_TIMEOUT_MS * 4)).makeIpClient(TEST_IFNAME, mIpClientCb) } @Test fun testDhcpServerAvailableImmediately() { doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } val testParams = DhcpServingParamsParcel() ModuleNetworkStackClient.getInstance(mContext).makeDhcpServer(TEST_IFNAME, testParams, mDhcpServerCb) Loading @@ -107,7 +114,7 @@ class ModuleNetworkStackClientTest { @Test fun testNetworkMonitorAvailableImmediately() { doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } val testName = "NetworkMonitorName" ModuleNetworkStackClient.getInstance(mContext).makeNetworkMonitor(TEST_NETWORK, testName, mNetworkMonitorCb) Loading @@ -116,7 +123,7 @@ class ModuleNetworkStackClientTest { @Test fun testIpMemoryStoreAvailableImmediately() { doReturn(mConnectorBinder).`when`(mContext).getSystemService(Context.NETWORK_STACK_SERVICE) doReturn(mConnectorBinder).`when` { NetworkStack.getService() } ModuleNetworkStackClient.getInstance(mContext).fetchIpMemoryStore(mIpMemoryStoreCb) verify(mConnector).fetchIpMemoryStore(mIpMemoryStoreCb) } Loading
tests/unit/src/com/android/networkstack/NetworkStackNotifierTest.kt +14 −16 Original line number Diff line number Diff line Loading @@ -106,8 +106,8 @@ class NetworkStackNotifierTest { .addTransportType(TRANSPORT_WIFI) .addCapability(NET_CAPABILITY_VALIDATED) private val TEST_CONNECTED_NO_SSID_TITLE = "Connected without SSID" private val TEST_CONNECTED_SSID_TITLE = "Connected to TestSsid" private val TEST_CONNECTED_DESCRIPTION = "Connected" private val TEST_VENUE_DESCRIPTION = "Connected / Tap to view website" private val TEST_VENUE_INFO_URL = "https://testvenue.example.com/info" private val EMPTY_CAPPORT_LP = LinkProperties() Loading @@ -123,9 +123,8 @@ class NetworkStackNotifierTest { MockitoAnnotations.initMocks(this) mLooper = TestableLooper.get(this) doReturn(mResources).`when`(mContext).resources doReturn(TEST_CONNECTED_NO_SSID_TITLE).`when`(mResources).getString(R.string.connected) doReturn(TEST_CONNECTED_SSID_TITLE).`when`(mResources).getString( R.string.connected_to_ssid_param1, TEST_SSID) doReturn(TEST_CONNECTED_DESCRIPTION).`when`(mResources).getString(R.string.connected) doReturn(TEST_VENUE_DESCRIPTION).`when`(mResources).getString(R.string.tap_for_info) // applicationInfo is used by Notification.Builder val realContext = InstrumentationRegistry.getInstrumentation().context Loading Loading @@ -201,19 +200,15 @@ class NetworkStackNotifierTest { mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) mLooper.processAllMessages() verifyConnectedNotification() verify(mResources).getString(R.string.connected) verifyWifiSettingsIntent(mIntentCaptor.value) verifyCanceledNotificationAfterNetworkLost() // There is no notification when SSID is not set. verify(mNm, never()).notify(any(), anyInt(), any()) } @Test fun testConnectedNotification_WithSsid() { // NetworkCapabilities#getSSID is not available for API <= Q assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES) .setSSID(TEST_SSID) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(EMPTY_CAPABILITIES) mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) Loading @@ -221,7 +216,7 @@ class NetworkStackNotifierTest { mLooper.processAllMessages() verifyConnectedNotification() verify(mResources).getString(R.string.connected_to_ssid_param1, TEST_SSID) verify(mResources).getString(R.string.connected) verifyWifiSettingsIntent(mIntentCaptor.value) verifyCanceledNotificationAfterNetworkLost() } Loading @@ -233,7 +228,8 @@ class NetworkStackNotifierTest { mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) onLinkPropertiesChanged(TEST_CAPPORT_LP) onDefaultNetworkAvailable(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) mLooper.processAllMessages() Loading @@ -251,7 +247,8 @@ class NetworkStackNotifierTest { mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) onLinkPropertiesChanged(TEST_CAPPORT_LP) onDefaultNetworkAvailable(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) mLooper.processAllMessages() verifyConnectedNotification() Loading @@ -266,7 +263,8 @@ class NetworkStackNotifierTest { assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) onLinkPropertiesChanged(TEST_CAPPORT_LP) onDefaultNetworkAvailable(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) mLooper.processAllMessages() verify(mNm).notify(eq(TEST_NETWORK_TAG), mNoteIdCaptor.capture(), mNoteCaptor.capture()) Loading