comparison sat/plugins/plugin_misc_android.py @ 3125:c3ce8c997fdf

plugin android: reconnect profiles with autoconnect if network is activated: if network is activated, we check that all profiles with autoconnect are indeed connected, and reconnect them if necesssary.
author Goffi <goffi@goffi.org>
date Sun, 26 Jan 2020 18:08:09 +0100
parents b86060901278
children 9d0df638c8b4
comparison
equal deleted inserted replaced
3124:b86060901278 3125:c3ce8c997fdf
193 self.notif_player.prepare() 193 self.notif_player.prepare()
194 194
195 # Connectivity handling 195 # Connectivity handling
196 self.cm = activity.getSystemService(Context.CONNECTIVITY_SERVICE) 196 self.cm = activity.getSystemService(Context.CONNECTIVITY_SERVICE)
197 self._net_type = None 197 self._net_type = None
198 self._checkConnectivity() 198 d = defer.ensureDeferred(self._checkConnectivity())
199 d.addErrback(host.logErrback)
200
199 # XXX: we need to keep a reference to BroadcastReceiver to avoid 201 # XXX: we need to keep a reference to BroadcastReceiver to avoid
200 # "XXX has no attribute 'invoke'" error (looks like the same issue as 202 # "XXX has no attribute 'invoke'" error (looks like the same issue as
201 # https://github.com/kivy/pyjnius/issues/59) 203 # https://github.com/kivy/pyjnius/issues/59)
202 self.br = BroadcastReceiver( 204 self.br = BroadcastReceiver(
203 callback=lambda *args, **kwargs: reactor.callLater(0, 205 callback=lambda *args, **kwargs: reactor.callLater(0,
289 # Profile autoconnection 291 # Profile autoconnection
290 292
291 def _profileAutoconnectGet(self): 293 def _profileAutoconnectGet(self):
292 return defer.ensureDeferred(self.profileAutoconnectGet()) 294 return defer.ensureDeferred(self.profileAutoconnectGet())
293 295
294 async def profileAutoconnectGet(self): 296 async def _getProfilesAutoconnect(self):
295 """Return profile to connect automatically by frontend, if any"""
296 autoconnect_dict = await self.host.memory.storage.getIndParamValues( 297 autoconnect_dict = await self.host.memory.storage.getIndParamValues(
297 category='Connection', name='autoconnect_backend', 298 category='Connection', name='autoconnect_backend',
298 ) 299 )
299 profiles_autoconnect = [p for p, v in autoconnect_dict.items() if C.bool(v)] 300 return [p for p, v in autoconnect_dict.items() if C.bool(v)]
301
302 async def profileAutoconnectGet(self):
303 """Return profile to connect automatically by frontend, if any"""
304 profiles_autoconnect = await self._getProfilesAutoconnect()
300 if not profiles_autoconnect: 305 if not profiles_autoconnect:
301 return None 306 return None
302 if len(profiles_autoconnect) > 1: 307 if len(profiles_autoconnect) > 1:
303 log.warning( 308 log.warning(
304 f"More that one profiles with backend autoconnection set found, picking " 309 f"More that one profiles with backend autoconnection set found, picking "
326 for client in self.host.getClients(C.PROF_KEY_ALL): 331 for client in self.host.getClients(C.PROF_KEY_ALL):
327 self._csi.setActive(client) 332 self._csi.setActive(client)
328 333
329 # Connectivity 334 # Connectivity
330 335
331 def _handleNetworkChange(self, previous, new): 336 async def _handleNetworkChange(self, net_type):
332 """Notify the clients about network changes. 337 """Notify the clients about network changes.
333 338
334 This way the client can disconnect/reconnect transport, or change delays 339 This way the client can disconnect/reconnect transport, or change delays
335 """ 340 """
336 if new == NET_TYPE_NONE: 341 log.debug(f"handling network change ({net_type})")
342 if net_type == NET_TYPE_NONE:
337 for client in self.host.getClients(C.PROF_KEY_ALL): 343 for client in self.host.getClients(C.PROF_KEY_ALL):
338 client.networkDisabled() 344 client.networkDisabled()
339 elif previous == NET_TYPE_NONE: 345 else:
346 # client may be there but disabled (e.g. with stream management)
340 for client in self.host.getClients(C.PROF_KEY_ALL): 347 for client in self.host.getClients(C.PROF_KEY_ALL):
348 log.debug(f"enabling network for {client.profile}")
341 client.networkEnabled() 349 client.networkEnabled()
342 350
343 def _checkConnectivity(self): 351 # profiles may have been disconnected and then purged, we try
352 # to reconnect them in case
353 profiles_autoconnect = await self._getProfilesAutoconnect()
354 for profile in profiles_autoconnect:
355 if not self.host.isConnected(profile):
356 log.info(f"{profile} is not connected, reconnecting it")
357 try:
358 await self.host.connect(profile)
359 except Exception as e:
360 log.error(f"Can't connect profile {profile}: {e}")
361
362 async def _checkConnectivity(self):
344 active_network = self.cm.getActiveNetworkInfo() 363 active_network = self.cm.getActiveNetworkInfo()
345 if active_network is None: 364 if active_network is None:
346 net_type = NET_TYPE_NONE 365 net_type = NET_TYPE_NONE
347 else: 366 else:
348 net_type_android = active_network.getType() 367 net_type_android = active_network.getType()
350 net_type = NET_TYPE_WIFI 369 net_type = NET_TYPE_WIFI
351 elif net_type_android == ConnectivityManager.TYPE_MOBILE: 370 elif net_type_android == ConnectivityManager.TYPE_MOBILE:
352 net_type = NET_TYPE_MOBILE 371 net_type = NET_TYPE_MOBILE
353 else: 372 else:
354 net_type = NET_TYPE_OTHER 373 net_type = NET_TYPE_OTHER
374
355 if net_type != self._net_type: 375 if net_type != self._net_type:
356 log.info("connectivity has changed") 376 log.info("connectivity has changed")
357 previous = self._net_type
358 self._net_type = net_type 377 self._net_type = net_type
359 if net_type == NET_TYPE_NONE: 378 if net_type == NET_TYPE_NONE:
360 log.info("no network active") 379 log.info("no network active")
361 elif net_type == NET_TYPE_WIFI: 380 elif net_type == NET_TYPE_WIFI:
362 log.info("WIFI activated") 381 log.info("WIFI activated")
363 elif net_type == NET_TYPE_MOBILE: 382 elif net_type == NET_TYPE_MOBILE:
364 log.info("mobile data activated") 383 log.info("mobile data activated")
365 else: 384 else:
366 log.info("network activated (type={net_type_android})" 385 log.info("network activated (type={net_type_android})"
367 .format(net_type_android=net_type_android)) 386 .format(net_type_android=net_type_android))
368 self._handleNetworkChange(previous, net_type)
369 else: 387 else:
370 log.debug("_checkConnectivity called without network change ({net_type})" 388 log.debug("_checkConnectivity called without network change ({net_type})"
371 .format(net_type = net_type)) 389 .format(net_type = net_type))
372 390
391 # we always call _handleNetworkChange even if there is not connectivity change
392 # to be sure to reconnect when necessary
393 await self._handleNetworkChange(net_type)
394
373 395
374 def onConnectivityChange(self): 396 def onConnectivityChange(self):
375 log.debug("onConnectivityChange called") 397 log.debug("onConnectivityChange called")
376 self._checkConnectivity() 398 d = defer.ensureDeferred(self._checkConnectivity())
399 d.addErrback(self.host.logErrback)