mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 13:08:46 +00:00
Restart websocket immediately upon network change.
This commit is contained in:
@@ -3,11 +3,8 @@ package org.thoughtcrime.securesms.messages
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.app.Service
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.IBinder
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.core.app.NotificationCompat
|
||||
@@ -87,10 +84,19 @@ class IncomingMessageObserver(private val context: Application) {
|
||||
|
||||
private val decryptionDrainedListeners: MutableList<Runnable> = CopyOnWriteArrayList()
|
||||
private val keepAliveTokens: MutableMap<String, Long> = mutableMapOf()
|
||||
private val connectionReceiver: BroadcastReceiver
|
||||
|
||||
private val lock: ReentrantLock = ReentrantLock()
|
||||
private val connectionNecessarySemaphore = Semaphore(0)
|
||||
private val networkConnectionListener = NetworkConnectionListener(context) { isNetworkAvailable ->
|
||||
lock.withLock {
|
||||
if (isNetworkAvailable()) {
|
||||
Log.w(TAG, "Lost network connection. Shutting down our websocket connections and resetting the drained state.")
|
||||
decryptionDrained = false
|
||||
disconnect()
|
||||
}
|
||||
connectionNecessarySemaphore.release()
|
||||
}
|
||||
}
|
||||
|
||||
private val messageContentProcessor = MessageContentProcessorV2(context)
|
||||
|
||||
@@ -136,20 +142,7 @@ class IncomingMessageObserver(private val context: Application) {
|
||||
}
|
||||
})
|
||||
|
||||
connectionReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
lock.withLock {
|
||||
if (!NetworkConstraint.isMet(context)) {
|
||||
Log.w(TAG, "Lost network connection. Shutting down our websocket connections and resetting the drained state.")
|
||||
decryptionDrained = false
|
||||
disconnect()
|
||||
}
|
||||
connectionNecessarySemaphore.release()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.registerReceiver(connectionReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
|
||||
networkConnectionListener.register()
|
||||
}
|
||||
|
||||
fun notifyRegistrationChanged() {
|
||||
@@ -250,8 +243,7 @@ class IncomingMessageObserver(private val context: Application) {
|
||||
fun terminateAsync() {
|
||||
Log.w(TAG, "Termination Enqueued! ${this.hashCode()}", Throwable())
|
||||
INSTANCE_COUNT.decrementAndGet()
|
||||
context.unregisterReceiver(connectionReceiver)
|
||||
|
||||
networkConnectionListener.unregister()
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
Log.w(TAG, "Beginning termination. ${this.hashCode()}")
|
||||
terminated = true
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.messages
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.os.Build
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||
|
||||
/**
|
||||
* Backcompat listener for determining when the network connection is lost.
|
||||
* On API 28+, [onNetworkLost] is invoked when the system notifies the app that the network is lost.
|
||||
* On earlier versions, [onNetworkLost] is invoked on any network change (gained, lost, losing, etc)
|
||||
* Therefore, [onNetworkLost] is a higher-order function, which takes a function to determine conditionally if it should run.
|
||||
* API 28+ only runs on lost networks, so it provides a conditional that's always true because that is guaranteed by the call site.
|
||||
* Earlier versions use [NetworkConstraint.isMet] to query the current network state upon receiving the broadcast.
|
||||
*/
|
||||
class NetworkConnectionListener(private val context: Context, private val onNetworkLost: (() -> Boolean) -> Unit) {
|
||||
companion object {
|
||||
private val TAG = Log.tag(NetworkConnectionListener::class.java)
|
||||
}
|
||||
|
||||
private val connectivityManager = ServiceUtil.getConnectivityManager(context)
|
||||
|
||||
private val networkChangedCallback: ConnectivityManager.NetworkCallback = object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onUnavailable() {
|
||||
super.onUnavailable()
|
||||
Log.d(TAG, "ConnectivityManager.NetworkCallback onUnavailable()")
|
||||
onNetworkLost { true }
|
||||
}
|
||||
|
||||
override fun onAvailable(network: Network) {
|
||||
super.onAvailable(network)
|
||||
Log.d(TAG, "ConnectivityManager.NetworkCallback onAvailable()")
|
||||
onNetworkLost { false }
|
||||
}
|
||||
|
||||
override fun onLost(network: Network) {
|
||||
super.onLost(network)
|
||||
Log.d(TAG, "ConnectivityManager.NetworkCallback onLost()")
|
||||
onNetworkLost { true }
|
||||
}
|
||||
}
|
||||
|
||||
private val connectionReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Log.d(TAG, "BroadcastReceiver onReceive().")
|
||||
onNetworkLost { !NetworkConstraint.isMet(context) }
|
||||
}
|
||||
}
|
||||
|
||||
fun register() {
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
connectivityManager.registerDefaultNetworkCallback(networkChangedCallback)
|
||||
} else {
|
||||
context.registerReceiver(connectionReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
|
||||
}
|
||||
}
|
||||
|
||||
fun unregister() {
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
connectivityManager.unregisterNetworkCallback(networkChangedCallback)
|
||||
} else {
|
||||
context.unregisterReceiver(connectionReceiver)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,6 @@ import android.app.Application;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.util.Preconditions;
|
||||
|
||||
Reference in New Issue
Block a user