network_change_notifier_delegate_android.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/android/network_change_notifier_delegate_android.h"
  5. #include "base/android/build_info.h"
  6. #include "base/android/jni_array.h"
  7. #include "base/check.h"
  8. #include "base/notreached.h"
  9. #include "net/android/network_change_notifier_android.h"
  10. #include "net/net_jni_headers/NetworkActiveNotifier_jni.h"
  11. #include "net/net_jni_headers/NetworkChangeNotifier_jni.h"
  12. using base::android::JavaParamRef;
  13. using base::android::JavaRef;
  14. using base::android::ScopedJavaLocalRef;
  15. namespace net {
  16. namespace {
  17. // Converts a Java side connection type (integer) to
  18. // the native side NetworkChangeNotifier::ConnectionType.
  19. NetworkChangeNotifier::ConnectionType ConvertConnectionType(
  20. jint connection_type) {
  21. switch (connection_type) {
  22. case NetworkChangeNotifier::CONNECTION_UNKNOWN:
  23. case NetworkChangeNotifier::CONNECTION_ETHERNET:
  24. case NetworkChangeNotifier::CONNECTION_WIFI:
  25. case NetworkChangeNotifier::CONNECTION_2G:
  26. case NetworkChangeNotifier::CONNECTION_3G:
  27. case NetworkChangeNotifier::CONNECTION_4G:
  28. case NetworkChangeNotifier::CONNECTION_5G:
  29. case NetworkChangeNotifier::CONNECTION_NONE:
  30. case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
  31. break;
  32. default:
  33. NOTREACHED() << "Unknown connection type received: " << connection_type;
  34. return NetworkChangeNotifier::CONNECTION_UNKNOWN;
  35. }
  36. return static_cast<NetworkChangeNotifier::ConnectionType>(connection_type);
  37. }
  38. // Converts a Java side connection cost (integer) to
  39. // the native side NetworkChangeNotifier::ConnectionCost.
  40. NetworkChangeNotifier::ConnectionCost ConvertConnectionCost(
  41. jint connection_cost) {
  42. switch (connection_cost) {
  43. case NetworkChangeNotifier::CONNECTION_COST_UNKNOWN:
  44. case NetworkChangeNotifier::CONNECTION_COST_UNMETERED:
  45. case NetworkChangeNotifier::CONNECTION_COST_METERED:
  46. break;
  47. default:
  48. NOTREACHED() << "Unknown connection cost received: " << connection_cost;
  49. return NetworkChangeNotifier::CONNECTION_COST_UNKNOWN;
  50. }
  51. return static_cast<NetworkChangeNotifier::ConnectionCost>(connection_cost);
  52. }
  53. // Converts a Java side connection type (integer) to
  54. // the native side NetworkChangeNotifier::ConnectionType.
  55. NetworkChangeNotifier::ConnectionSubtype ConvertConnectionSubtype(
  56. jint subtype) {
  57. DCHECK(subtype >= 0 && subtype <= NetworkChangeNotifier::SUBTYPE_LAST);
  58. return static_cast<NetworkChangeNotifier::ConnectionSubtype>(subtype);
  59. }
  60. } // namespace
  61. // static
  62. void NetworkChangeNotifierDelegateAndroid::JavaLongArrayToNetworkMap(
  63. JNIEnv* env,
  64. const JavaRef<jlongArray>& long_array,
  65. NetworkMap* network_map) {
  66. std::vector<int64_t> int64_list;
  67. base::android::JavaLongArrayToInt64Vector(env, long_array, &int64_list);
  68. network_map->clear();
  69. for (auto i = int64_list.begin(); i != int64_list.end(); ++i) {
  70. handles::NetworkHandle network_handle = *i;
  71. CHECK(++i != int64_list.end());
  72. (*network_map)[network_handle] = static_cast<ConnectionType>(*i);
  73. }
  74. }
  75. NetworkChangeNotifierDelegateAndroid::NetworkChangeNotifierDelegateAndroid()
  76. : java_network_change_notifier_(Java_NetworkChangeNotifier_init(
  77. base::android::AttachCurrentThread())),
  78. register_network_callback_failed_(
  79. Java_NetworkChangeNotifier_registerNetworkCallbackFailed(
  80. base::android::AttachCurrentThread(),
  81. java_network_change_notifier_)),
  82. // TODO(crbug.com/1042122): Remove once Cronet drops Kitkat support.
  83. is_default_network_active_api_supported_(
  84. base::android::BuildInfo::GetInstance()->sdk_int() >=
  85. base::android::SDK_VERSION_LOLLIPOP) {
  86. JNIEnv* env = base::android::AttachCurrentThread();
  87. Java_NetworkChangeNotifier_addNativeObserver(
  88. env, java_network_change_notifier_, reinterpret_cast<intptr_t>(this));
  89. SetCurrentConnectionType(
  90. ConvertConnectionType(Java_NetworkChangeNotifier_getCurrentConnectionType(
  91. env, java_network_change_notifier_)));
  92. SetCurrentConnectionCost(
  93. ConvertConnectionCost(Java_NetworkChangeNotifier_getCurrentConnectionCost(
  94. env, java_network_change_notifier_)));
  95. SetCurrentMaxBandwidth(
  96. NetworkChangeNotifierAndroid::GetMaxBandwidthMbpsForConnectionSubtype(
  97. GetCurrentConnectionSubtype()));
  98. SetCurrentDefaultNetwork(Java_NetworkChangeNotifier_getCurrentDefaultNetId(
  99. env, java_network_change_notifier_));
  100. NetworkMap network_map;
  101. ScopedJavaLocalRef<jlongArray> networks_and_types =
  102. Java_NetworkChangeNotifier_getCurrentNetworksAndTypes(
  103. env, java_network_change_notifier_);
  104. JavaLongArrayToNetworkMap(env, networks_and_types, &network_map);
  105. SetCurrentNetworksAndTypes(network_map);
  106. if (is_default_network_active_api_supported_)
  107. java_network_active_notifier_ = Java_NetworkActiveNotifier_build(
  108. base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this));
  109. }
  110. NetworkChangeNotifierDelegateAndroid::~NetworkChangeNotifierDelegateAndroid() {
  111. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  112. DCHECK_EQ(default_network_active_observers_, 0);
  113. {
  114. base::AutoLock auto_lock(observer_lock_);
  115. DCHECK(!observer_);
  116. }
  117. JNIEnv* env = base::android::AttachCurrentThread();
  118. Java_NetworkChangeNotifier_removeNativeObserver(
  119. env, java_network_change_notifier_, reinterpret_cast<intptr_t>(this));
  120. }
  121. NetworkChangeNotifier::ConnectionType
  122. NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionType() const {
  123. base::AutoLock auto_lock(connection_lock_);
  124. return connection_type_;
  125. }
  126. NetworkChangeNotifier::ConnectionCost
  127. NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionCost() {
  128. base::AutoLock auto_lock(connection_lock_);
  129. return connection_cost_;
  130. }
  131. NetworkChangeNotifier::ConnectionSubtype
  132. NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionSubtype() const {
  133. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  134. return ConvertConnectionSubtype(
  135. Java_NetworkChangeNotifier_getCurrentConnectionSubtype(
  136. base::android::AttachCurrentThread(), java_network_change_notifier_));
  137. }
  138. void NetworkChangeNotifierDelegateAndroid::
  139. GetCurrentMaxBandwidthAndConnectionType(
  140. double* max_bandwidth_mbps,
  141. ConnectionType* connection_type) const {
  142. base::AutoLock auto_lock(connection_lock_);
  143. *connection_type = connection_type_;
  144. *max_bandwidth_mbps = connection_max_bandwidth_;
  145. }
  146. NetworkChangeNotifier::ConnectionType
  147. NetworkChangeNotifierDelegateAndroid::GetNetworkConnectionType(
  148. handles::NetworkHandle network) const {
  149. base::AutoLock auto_lock(connection_lock_);
  150. auto network_entry = network_map_.find(network);
  151. if (network_entry == network_map_.end())
  152. return ConnectionType::CONNECTION_UNKNOWN;
  153. return network_entry->second;
  154. }
  155. handles::NetworkHandle
  156. NetworkChangeNotifierDelegateAndroid::GetCurrentDefaultNetwork() const {
  157. base::AutoLock auto_lock(connection_lock_);
  158. return default_network_;
  159. }
  160. void NetworkChangeNotifierDelegateAndroid::GetCurrentlyConnectedNetworks(
  161. NetworkList* network_list) const {
  162. network_list->clear();
  163. base::AutoLock auto_lock(connection_lock_);
  164. for (auto i : network_map_)
  165. network_list->push_back(i.first);
  166. }
  167. bool NetworkChangeNotifierDelegateAndroid::IsDefaultNetworkActive() {
  168. // If the API is not available always return true to avoid indefinitely
  169. // batching.
  170. if (!is_default_network_active_api_supported_)
  171. return true;
  172. JNIEnv* env = base::android::AttachCurrentThread();
  173. return Java_NetworkActiveNotifier_isDefaultNetworkActive(
  174. env, java_network_active_notifier_);
  175. }
  176. void NetworkChangeNotifierDelegateAndroid::NotifyConnectionCostChanged(
  177. JNIEnv* env,
  178. const JavaParamRef<jobject>& obj,
  179. jint new_connection_cost) {
  180. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  181. const ConnectionCost actual_connection_cost =
  182. ConvertConnectionCost(new_connection_cost);
  183. SetCurrentConnectionCost(actual_connection_cost);
  184. base::AutoLock auto_lock(observer_lock_);
  185. if (observer_)
  186. observer_->OnConnectionCostChanged();
  187. }
  188. void NetworkChangeNotifierDelegateAndroid::NotifyConnectionTypeChanged(
  189. JNIEnv* env,
  190. const JavaParamRef<jobject>& obj,
  191. jint new_connection_type,
  192. jlong default_netid) {
  193. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  194. const ConnectionType actual_connection_type = ConvertConnectionType(
  195. new_connection_type);
  196. SetCurrentConnectionType(actual_connection_type);
  197. handles::NetworkHandle default_network = default_netid;
  198. if (default_network != GetCurrentDefaultNetwork()) {
  199. SetCurrentDefaultNetwork(default_network);
  200. bool default_exists;
  201. {
  202. base::AutoLock auto_lock(connection_lock_);
  203. // |default_network| may be an invalid value (i.e. -1) in cases where
  204. // the device is disconnected or when run on Android versions prior to L,
  205. // in which case |default_exists| will correctly be false and no
  206. // OnNetworkMadeDefault notification will be sent.
  207. default_exists = network_map_.find(default_network) != network_map_.end();
  208. }
  209. // Android Lollipop had race conditions where CONNECTIVITY_ACTION intents
  210. // were sent out before the network was actually made the default.
  211. // Delay sending the OnNetworkMadeDefault notification until we are
  212. // actually notified that the network connected in NotifyOfNetworkConnect.
  213. if (default_exists) {
  214. base::AutoLock auto_lock(observer_lock_);
  215. if (observer_)
  216. observer_->OnNetworkMadeDefault(default_network);
  217. }
  218. }
  219. base::AutoLock auto_lock(observer_lock_);
  220. if (observer_)
  221. observer_->OnConnectionTypeChanged();
  222. }
  223. jint NetworkChangeNotifierDelegateAndroid::GetConnectionType(JNIEnv*,
  224. jobject) const {
  225. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  226. return GetCurrentConnectionType();
  227. }
  228. jint NetworkChangeNotifierDelegateAndroid::GetConnectionCost(JNIEnv*, jobject) {
  229. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  230. return GetCurrentConnectionCost();
  231. }
  232. void NetworkChangeNotifierDelegateAndroid::NotifyMaxBandwidthChanged(
  233. JNIEnv* env,
  234. const JavaParamRef<jobject>& obj,
  235. jint subtype) {
  236. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  237. double new_max_bandwidth =
  238. NetworkChangeNotifierAndroid::GetMaxBandwidthMbpsForConnectionSubtype(
  239. ConvertConnectionSubtype(subtype));
  240. SetCurrentMaxBandwidth(new_max_bandwidth);
  241. const ConnectionType connection_type = GetCurrentConnectionType();
  242. base::AutoLock auto_lock(observer_lock_);
  243. if (observer_) {
  244. observer_->OnMaxBandwidthChanged(new_max_bandwidth, connection_type);
  245. }
  246. }
  247. void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkConnect(
  248. JNIEnv* env,
  249. const JavaParamRef<jobject>& obj,
  250. jlong net_id,
  251. jint connection_type) {
  252. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  253. handles::NetworkHandle network = net_id;
  254. bool already_exists;
  255. bool is_default_network;
  256. {
  257. base::AutoLock auto_lock(connection_lock_);
  258. already_exists = network_map_.find(network) != network_map_.end();
  259. network_map_[network] = static_cast<ConnectionType>(connection_type);
  260. is_default_network = (network == default_network_);
  261. }
  262. // Android Lollipop would send many duplicate notifications.
  263. // This was later fixed in Android Marshmallow.
  264. // Deduplicate them here by avoiding sending duplicate notifications.
  265. if (!already_exists) {
  266. base::AutoLock auto_lock(observer_lock_);
  267. if (observer_) {
  268. observer_->OnNetworkConnected(network);
  269. if (is_default_network)
  270. observer_->OnNetworkMadeDefault(network);
  271. }
  272. }
  273. }
  274. void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkSoonToDisconnect(
  275. JNIEnv* env,
  276. const JavaParamRef<jobject>& obj,
  277. jlong net_id) {
  278. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  279. handles::NetworkHandle network = net_id;
  280. {
  281. base::AutoLock auto_lock(connection_lock_);
  282. if (network_map_.find(network) == network_map_.end())
  283. return;
  284. }
  285. base::AutoLock auto_lock(observer_lock_);
  286. if (observer_)
  287. observer_->OnNetworkSoonToDisconnect(network);
  288. }
  289. void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkDisconnect(
  290. JNIEnv* env,
  291. const JavaParamRef<jobject>& obj,
  292. jlong net_id) {
  293. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  294. handles::NetworkHandle network = net_id;
  295. {
  296. base::AutoLock auto_lock(connection_lock_);
  297. if (network == default_network_)
  298. default_network_ = handles::kInvalidNetworkHandle;
  299. if (network_map_.erase(network) == 0)
  300. return;
  301. }
  302. base::AutoLock auto_lock(observer_lock_);
  303. if (observer_)
  304. observer_->OnNetworkDisconnected(network);
  305. }
  306. void NetworkChangeNotifierDelegateAndroid::NotifyPurgeActiveNetworkList(
  307. JNIEnv* env,
  308. const JavaParamRef<jobject>& obj,
  309. const JavaParamRef<jlongArray>& active_networks) {
  310. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  311. NetworkList active_network_list;
  312. base::android::JavaLongArrayToInt64Vector(env, active_networks,
  313. &active_network_list);
  314. NetworkList disconnected_networks;
  315. {
  316. base::AutoLock auto_lock(connection_lock_);
  317. for (auto i : network_map_) {
  318. bool found = false;
  319. for (auto j : active_network_list) {
  320. if (j == i.first) {
  321. found = true;
  322. break;
  323. }
  324. }
  325. if (!found) {
  326. disconnected_networks.push_back(i.first);
  327. }
  328. }
  329. }
  330. for (auto disconnected_network : disconnected_networks)
  331. NotifyOfNetworkDisconnect(env, obj, disconnected_network);
  332. }
  333. void NetworkChangeNotifierDelegateAndroid::NotifyOfDefaultNetworkActive(
  334. JNIEnv* env) {
  335. base::AutoLock auto_lock(observer_lock_);
  336. if (observer_)
  337. observer_->OnDefaultNetworkActive();
  338. }
  339. void NetworkChangeNotifierDelegateAndroid::RegisterObserver(
  340. Observer* observer) {
  341. base::AutoLock auto_lock(observer_lock_);
  342. DCHECK(!observer_);
  343. observer_ = observer;
  344. }
  345. void NetworkChangeNotifierDelegateAndroid::UnregisterObserver(
  346. Observer* observer) {
  347. base::AutoLock auto_lock(observer_lock_);
  348. DCHECK_EQ(observer_, observer);
  349. observer_ = nullptr;
  350. }
  351. void NetworkChangeNotifierDelegateAndroid::DefaultNetworkActiveObserverAdded() {
  352. if (!is_default_network_active_api_supported_)
  353. return;
  354. if (default_network_active_observers_.fetch_add(1) == 0)
  355. EnableDefaultNetworkActiveNotifications();
  356. }
  357. void NetworkChangeNotifierDelegateAndroid::
  358. DefaultNetworkActiveObserverRemoved() {
  359. if (!is_default_network_active_api_supported_)
  360. return;
  361. if (default_network_active_observers_.fetch_sub(1) == 1)
  362. DisableDefaultNetworkActiveNotifications();
  363. }
  364. void NetworkChangeNotifierDelegateAndroid::
  365. EnableDefaultNetworkActiveNotifications() {
  366. if (!is_default_network_active_api_supported_)
  367. return;
  368. JNIEnv* env = base::android::AttachCurrentThread();
  369. Java_NetworkActiveNotifier_enableNotifications(env,
  370. java_network_active_notifier_);
  371. }
  372. void NetworkChangeNotifierDelegateAndroid::
  373. DisableDefaultNetworkActiveNotifications() {
  374. if (!is_default_network_active_api_supported_)
  375. return;
  376. JNIEnv* env = base::android::AttachCurrentThread();
  377. Java_NetworkActiveNotifier_disableNotifications(
  378. env, java_network_active_notifier_);
  379. }
  380. void NetworkChangeNotifierDelegateAndroid::SetCurrentConnectionType(
  381. ConnectionType new_connection_type) {
  382. base::AutoLock auto_lock(connection_lock_);
  383. connection_type_ = new_connection_type;
  384. }
  385. void NetworkChangeNotifierDelegateAndroid::SetCurrentConnectionCost(
  386. ConnectionCost new_connection_cost) {
  387. base::AutoLock auto_lock(connection_lock_);
  388. connection_cost_ = new_connection_cost;
  389. }
  390. void NetworkChangeNotifierDelegateAndroid::SetCurrentMaxBandwidth(
  391. double max_bandwidth) {
  392. base::AutoLock auto_lock(connection_lock_);
  393. connection_max_bandwidth_ = max_bandwidth;
  394. }
  395. void NetworkChangeNotifierDelegateAndroid::SetCurrentDefaultNetwork(
  396. handles::NetworkHandle default_network) {
  397. base::AutoLock auto_lock(connection_lock_);
  398. default_network_ = default_network;
  399. }
  400. void NetworkChangeNotifierDelegateAndroid::SetCurrentNetworksAndTypes(
  401. NetworkMap network_map) {
  402. base::AutoLock auto_lock(connection_lock_);
  403. network_map_ = network_map;
  404. }
  405. void NetworkChangeNotifierDelegateAndroid::SetOnline() {
  406. JNIEnv* env = base::android::AttachCurrentThread();
  407. Java_NetworkChangeNotifier_forceConnectivityState(env, true);
  408. }
  409. void NetworkChangeNotifierDelegateAndroid::SetOffline() {
  410. JNIEnv* env = base::android::AttachCurrentThread();
  411. Java_NetworkChangeNotifier_forceConnectivityState(env, false);
  412. }
  413. void NetworkChangeNotifierDelegateAndroid::FakeNetworkConnected(
  414. handles::NetworkHandle network,
  415. ConnectionType type) {
  416. JNIEnv* env = base::android::AttachCurrentThread();
  417. Java_NetworkChangeNotifier_fakeNetworkConnected(env, network, type);
  418. }
  419. void NetworkChangeNotifierDelegateAndroid::FakeNetworkSoonToBeDisconnected(
  420. handles::NetworkHandle network) {
  421. JNIEnv* env = base::android::AttachCurrentThread();
  422. Java_NetworkChangeNotifier_fakeNetworkSoonToBeDisconnected(env, network);
  423. }
  424. void NetworkChangeNotifierDelegateAndroid::FakeNetworkDisconnected(
  425. handles::NetworkHandle network) {
  426. JNIEnv* env = base::android::AttachCurrentThread();
  427. Java_NetworkChangeNotifier_fakeNetworkDisconnected(env, network);
  428. }
  429. void NetworkChangeNotifierDelegateAndroid::FakePurgeActiveNetworkList(
  430. NetworkChangeNotifier::NetworkList networks) {
  431. JNIEnv* env = base::android::AttachCurrentThread();
  432. Java_NetworkChangeNotifier_fakePurgeActiveNetworkList(
  433. env, base::android::ToJavaLongArray(env, networks));
  434. }
  435. void NetworkChangeNotifierDelegateAndroid::FakeDefaultNetwork(
  436. handles::NetworkHandle network,
  437. ConnectionType type) {
  438. JNIEnv* env = base::android::AttachCurrentThread();
  439. Java_NetworkChangeNotifier_fakeDefaultNetwork(env, network, type);
  440. }
  441. void NetworkChangeNotifierDelegateAndroid::FakeConnectionCostChanged(
  442. ConnectionCost cost) {
  443. JNIEnv* env = base::android::AttachCurrentThread();
  444. Java_NetworkChangeNotifier_fakeConnectionCostChanged(env, cost);
  445. }
  446. void NetworkChangeNotifierDelegateAndroid::FakeConnectionSubtypeChanged(
  447. ConnectionSubtype subtype) {
  448. JNIEnv* env = base::android::AttachCurrentThread();
  449. Java_NetworkChangeNotifier_fakeConnectionSubtypeChanged(env, subtype);
  450. }
  451. void NetworkChangeNotifierDelegateAndroid::FakeDefaultNetworkActive() {
  452. if (!is_default_network_active_api_supported_)
  453. return;
  454. JNIEnv* env = base::android::AttachCurrentThread();
  455. Java_NetworkActiveNotifier_fakeDefaultNetworkActive(
  456. env, java_network_active_notifier_);
  457. }
  458. void NetworkChangeNotifierDelegateAndroid::
  459. EnableNetworkChangeNotifierAutoDetectForTest() {
  460. JNIEnv* env = base::android::AttachCurrentThread();
  461. Java_NetworkChangeNotifier_setAutoDetectConnectivityState(env, true);
  462. }
  463. } // namespace net