aboutsummaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorEric Gribkoff <ericgribkoff@google.com>2018-06-30 09:24:47 -0700
committerGitHub <noreply@github.com>2018-06-30 09:24:47 -0700
commit27a1c900a9dd63be89d5bafbad314c071b26a849 (patch)
tree6f0bc96b7cd581685feaa192c9fc0d1e0a86f3d2 /android
parent8c52e138eeb9c040ca6197643db496749d65b580 (diff)
downloadgrpc-grpc-java-27a1c900a9dd63be89d5bafbad314c071b26a849.tar.gz
android: initialize listener with isConnected=false (#4606)
Diffstat (limited to 'android')
-rw-r--r--android/src/main/java/io/grpc/android/AndroidChannelBuilder.java40
-rw-r--r--android/src/test/java/io/grpc/android/AndroidChannelBuilderTest.java10
2 files changed, 23 insertions, 27 deletions
diff --git a/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java b/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java
index 3a824e23f..4223e1577 100644
--- a/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java
+++ b/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java
@@ -187,7 +187,15 @@ public final class AndroidChannelBuilder extends ForwardingChannelBuilder<Androi
if (context != null) {
connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- configureNetworkMonitoring();
+ try {
+ configureNetworkMonitoring();
+ } catch (SecurityException e) {
+ Log.w(
+ LOG_TAG,
+ "Failed to configure network monitoring. Does app have ACCESS_NETWORK_STATE"
+ + " permission?",
+ e);
+ }
} else {
connectivityManager = null;
}
@@ -195,29 +203,10 @@ public final class AndroidChannelBuilder extends ForwardingChannelBuilder<Androi
@GuardedBy("lock")
private void configureNetworkMonitoring() {
- // Eagerly check current network state to verify app has required permissions
- NetworkInfo currentNetwork;
- try {
- currentNetwork = connectivityManager.getActiveNetworkInfo();
- } catch (SecurityException e) {
- Log.w(
- LOG_TAG,
- "Failed to configure network monitoring. Does app have ACCESS_NETWORK_STATE"
- + " permission?",
- e);
- return;
- }
-
// Android N added the registerDefaultNetworkCallback API to listen to changes in the device's
// default network. For earlier Android API levels, use the BroadcastReceiver API.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && connectivityManager != null) {
- // The connection status may change before registration of the listener is complete, but
- // this will at worst result in invoking resetConnectBackoff() instead of enterIdle() (or
- // vice versa) on the first network change.
- boolean isConnected = currentNetwork != null && currentNetwork.isConnected();
-
- final DefaultNetworkCallback defaultNetworkCallback =
- new DefaultNetworkCallback(isConnected);
+ final DefaultNetworkCallback defaultNetworkCallback = new DefaultNetworkCallback();
connectivityManager.registerDefaultNetworkCallback(defaultNetworkCallback);
unregisterRunnable =
new Runnable() {
@@ -313,12 +302,13 @@ public final class AndroidChannelBuilder extends ForwardingChannelBuilder<Androi
/** Respond to changes in the default network. Only used on API levels 24+. */
@TargetApi(Build.VERSION_CODES.N)
private class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback {
+ // Registering a listener may immediate invoke onAvailable/onLost: the API docs do not specify
+ // if the methods are always invoked once, then again on any change, or only on change. When
+ // onAvailable() is invoked immediately without an actual network change, it's preferable to
+ // (spuriously) resetConnectBackoff() rather than enterIdle(), as the former is a no-op if the
+ // channel has already moved to CONNECTING.
private boolean isConnected = false;
- private DefaultNetworkCallback(boolean isConnected) {
- this.isConnected = isConnected;
- }
-
@Override
public void onAvailable(Network network) {
if (isConnected) {
diff --git a/android/src/test/java/io/grpc/android/AndroidChannelBuilderTest.java b/android/src/test/java/io/grpc/android/AndroidChannelBuilderTest.java
index 0477c34a0..db6be27ea 100644
--- a/android/src/test/java/io/grpc/android/AndroidChannelBuilderTest.java
+++ b/android/src/test/java/io/grpc/android/AndroidChannelBuilderTest.java
@@ -256,15 +256,21 @@ public final class AndroidChannelBuilderTest {
@Test
@Config(sdk = 24)
- public void newChannelWithConnection_entersIdleOnConnectionChange_api24() {
+ public void newChannelWithConnection_entersIdleOnSecondConnectionChange_api24() {
shadowConnectivityManager.setActiveNetworkInfo(MOBILE_CONNECTED);
TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext());
+ // The first onAvailable() may just signal that the device was connected when the callback is
+ // registered, rather than indicating a changed network, so we do not enter idle.
shadowConnectivityManager.setActiveNetworkInfo(WIFI_CONNECTED);
- assertThat(delegateChannel.resetCount).isEqualTo(0);
+ assertThat(delegateChannel.resetCount).isEqualTo(1);
+ assertThat(delegateChannel.enterIdleCount).isEqualTo(0);
+
+ shadowConnectivityManager.setActiveNetworkInfo(MOBILE_CONNECTED);
+ assertThat(delegateChannel.resetCount).isEqualTo(1);
assertThat(delegateChannel.enterIdleCount).isEqualTo(1);
androidChannel.shutdown();