1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.net; 6 7 import android.content.Context; 8 import android.net.ConnectivityManager; 9 10 import org.jni_zero.CalledByNative; 11 import org.jni_zero.JNINamespace; 12 import org.jni_zero.NativeClassQualifiedName; 13 import org.jni_zero.NativeMethods; 14 15 import org.chromium.base.ContextUtils; 16 17 /** 18 * Triggers updates to the underlying network state in Chrome alongside NetworkChangeNotifier. 19 * 20 * Differently from NetworkChangeNotifier, this handles default network active type of 21 * notifications. These are handled separately for two main reasons: 22 * 1. They are more expensive to listen to and currently only used by bidi streams connection status 23 * check. Hence, we only enable them when they are actually required. 24 * 2. The default network active value is not cacheable, what observers are interested in is the 25 * event itself (usually to send out packets which were being batched). For this reason the 26 * architecture of NetworkChangeNotifier doesn't make much sense for this notification type. 27 * 28 * Note: ConnectivityManager.OnNetworkActiveListener has been introduced in Android API level 21, so 29 * loading this class will fail on older Android versions (no sdk checks are needed for this 30 * reason). 31 */ 32 @JNINamespace("net") 33 public class NetworkActiveNotifier implements ConnectivityManager.OnNetworkActiveListener { 34 private final ConnectivityManager mConnectivityManager; 35 // Native-side observer of the default network active events. 36 private final long mNativeNetworkActiveObserver; 37 // Used for testing, keeps track of when platform notification are enabled (or disabled). 38 private boolean mAreNotificationsEnabled; 39 40 /** Used to build a Java object from native code. */ 41 @CalledByNative build(long nativeNetworkActiveNotifier)42 public static NetworkActiveNotifier build(long nativeNetworkActiveNotifier) { 43 return new NetworkActiveNotifier(nativeNetworkActiveNotifier); 44 } 45 46 @CalledByNative enableNotifications()47 public void enableNotifications() { 48 mAreNotificationsEnabled = true; 49 mConnectivityManager.addDefaultNetworkActiveListener(this); 50 } 51 52 @CalledByNative disableNotifications()53 public void disableNotifications() { 54 mAreNotificationsEnabled = false; 55 mConnectivityManager.removeDefaultNetworkActiveListener(this); 56 } 57 58 @CalledByNative isDefaultNetworkActive()59 public boolean isDefaultNetworkActive() { 60 return mConnectivityManager.isDefaultNetworkActive(); 61 } 62 63 @Override onNetworkActive()64 public void onNetworkActive() { 65 NetworkActiveNotifierJni.get().notifyOfDefaultNetworkActive(mNativeNetworkActiveObserver); 66 } 67 68 /** For testing, called by native code to trigger a fake platform notification. */ 69 @CalledByNative fakeDefaultNetworkActive()70 public void fakeDefaultNetworkActive() { 71 if (mAreNotificationsEnabled) { 72 // Platform notifications should only be received when enabled. 73 onNetworkActive(); 74 } 75 } 76 77 @NativeMethods 78 interface Natives { 79 @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid") notifyOfDefaultNetworkActive(long nativePtr)80 void notifyOfDefaultNetworkActive(long nativePtr); 81 } 82 NetworkActiveNotifier(long nativeNetworkActiveNotifier)83 private NetworkActiveNotifier(long nativeNetworkActiveNotifier) { 84 mNativeNetworkActiveObserver = nativeNetworkActiveNotifier; 85 Context ctx = ContextUtils.getApplicationContext(); 86 mConnectivityManager = 87 (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); 88 } 89 } 90