summaryrefslogtreecommitdiffstats
path: root/net/android/network_change_notifier_delegate_android.h
blob: d6312b7b28068d6c57fd507d2baddea5f8be624c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_
#define NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_

#include <string>

#include "base/android/jni_android.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "net/base/network_change_notifier.h"

namespace net {

// Delegate used to thread-safely notify NetworkChangeNotifierAndroid whenever a
// network connection change notification is signaled by the Java side (on the
// JNI thread).
// All the methods exposed below must be called exclusively on the JNI thread
// unless otherwise stated (e.g. AddObserver()/RemoveObserver()).
class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid {
 public:
  typedef NetworkChangeNotifier::ConnectionType ConnectionType;
  typedef NetworkChangeNotifier::NetworkHandle NetworkHandle;
  typedef NetworkChangeNotifier::NetworkList NetworkList;

  // Observer interface implemented by NetworkChangeNotifierAndroid which
  // subscribes to network change notifications fired by the delegate (and
  // initiated by the Java side).
  class Observer : public NetworkChangeNotifier::NetworkObserver {
   public:
    ~Observer() override {}

    // Updates the current connection type.
    virtual void OnConnectionTypeChanged() = 0;

    // Updates the current max bandwidth.
    virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps,
                                       ConnectionType connection_type) = 0;
  };

  NetworkChangeNotifierDelegateAndroid();
  ~NetworkChangeNotifierDelegateAndroid();

  // Called from NetworkChangeNotifier.java on the JNI thread whenever
  // the connection type changes. This updates the current connection type seen
  // by this class and forwards the notification to the observers that
  // subscribed through AddObserver().
  void NotifyConnectionTypeChanged(JNIEnv* env,
                                   jobject obj,
                                   jint new_connection_type,
                                   jint default_netid);
  jint GetConnectionType(JNIEnv* env, jobject obj) const;

  // Called from NetworkChangeNotifier.java on the JNI thread whenever
  // the maximum bandwidth of the connection changes. This updates the current
  // max bandwidth seen by this class and forwards the notification to the
  // observers that subscribed through AddObserver().
  void NotifyMaxBandwidthChanged(JNIEnv* env,
                                 jobject obj,
                                 jdouble new_max_bandwidth);

  // Called from NetworkChangeNotifier.java on the JNI thread to push
  // down notifications of network connectivity events. These functions in
  // turn:
  //   1) Update |network_map_| and |default_network_|.
  //   2) Push notifications to NetworkChangeNotifier which in turn pushes
  //      notifications to its NetworkObservers. Note that these functions
  //      perform valuable transformations on the signals like deduplicating.
  // For descriptions of what individual calls mean, see
  // NetworkChangeNotifierAutoDetect.Observer functions of the same names.
  void NotifyOfNetworkConnect(JNIEnv* env,
                              jobject obj,
                              jint net_id,
                              jint connection_type);
  void NotifyOfNetworkSoonToDisconnect(JNIEnv* env, jobject obj, jint net_id);
  void NotifyOfNetworkDisconnect(JNIEnv* env, jobject obj, jint net_id);
  void NotifyUpdateActiveNetworkList(JNIEnv* env,
                                     jobject obj,
                                     jintArray active_networks);

  // These methods can be called on any thread. Note that the provided observer
  // will be notified on the thread AddObserver() is called on.
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // These methods are simply implementations of NetworkChangeNotifier APIs of
  // the same name. They can be called from any thread.
  ConnectionType GetCurrentConnectionType() const;
  void GetCurrentMaxBandwidthAndConnectionType(
      double* max_bandwidth_mbps,
      ConnectionType* connection_type) const;
  ConnectionType GetNetworkConnectionType(NetworkHandle network) const;
  NetworkHandle GetCurrentDefaultNetwork() const;
  void GetCurrentlyConnectedNetworks(NetworkList* network_list) const;

  // Initializes JNI bindings.
  static bool Register(JNIEnv* env);

 private:
  friend class BaseNetworkChangeNotifierAndroidTest;

  // Map of active connected networks and their connection type.
  typedef std::map<NetworkHandle, ConnectionType> NetworkMap;

  // Converts a Java int[] into a NetworkMap. Expects int[] to contain
  // repeated instances of: NetworkHandle, ConnectionType
  static void JavaIntArrayToNetworkMap(JNIEnv* env,
                                       jintArray int_array,
                                       NetworkMap* network_map);

  // Setters that grab appropriate lock.
  void SetCurrentConnectionType(ConnectionType connection_type);
  void SetCurrentMaxBandwidth(double max_bandwidth);
  void SetCurrentDefaultNetwork(NetworkHandle default_network);
  void SetCurrentNetworksAndTypes(NetworkMap network_map);

  // Methods calling the Java side exposed for testing.
  void SetOnline();
  void SetOffline();
  void FakeNetworkConnected(NetworkHandle network, ConnectionType type);
  void FakeNetworkSoonToBeDisconnected(NetworkHandle network);
  void FakeNetworkDisconnected(NetworkHandle network);
  void FakeUpdateActiveNetworkList(NetworkList networks);
  void FakeDefaultNetwork(NetworkHandle network, ConnectionType type);

  base::ThreadChecker thread_checker_;
  scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_;
  base::android::ScopedJavaGlobalRef<jobject> java_network_change_notifier_;

  mutable base::Lock connection_lock_;  // Protects the state below.
  ConnectionType connection_type_;
  double connection_max_bandwidth_;
  NetworkHandle default_network_;
  NetworkMap network_map_;

  DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierDelegateAndroid);
};

}  // namespace net

#endif  // NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_H_