Track inconsistencies between new and old network availability for internal users.

This commit is contained in:
Cody Henthorne
2022-03-21 17:21:42 -04:00
committed by GitHub
parent 86ca1ebda0
commit 007975e7da
4 changed files with 138 additions and 0 deletions

View File

@@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencyProvider;
import org.thoughtcrime.securesms.emoji.EmojiSource;
import org.thoughtcrime.securesms.emoji.JumboEmoji;
import org.thoughtcrime.securesms.gcm.FcmJobService;
import org.thoughtcrime.securesms.jobmanager.impl.NewNetworkConnectivity;
import org.thoughtcrime.securesms.jobs.CheckServiceReachabilityJob;
import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob;
import org.thoughtcrime.securesms.jobs.DownloadLatestEmojiDataJob;
@@ -203,6 +204,7 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
.addPostRender(() -> ApplicationDependencies.getJobManager().add(new FontDownloaderJob()))
.addPostRender(CheckServiceReachabilityJob::enqueueIfNecessary)
.addPostRender(GroupV2UpdateSelfProfileKeyJob::enqueueForGroupsIfNecessary)
.addPostRender(NewNetworkConnectivity::start)
.execute();
Log.d(TAG, "onCreate() took " + (System.currentTimeMillis() - startTime) + " ms");

View File

@@ -47,6 +47,8 @@ public class NetworkConstraint implements Constraint {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
NewNetworkConnectivity.consistencyCheck();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

View File

@@ -0,0 +1,133 @@
package org.thoughtcrime.securesms.jobmanager.impl
import android.app.Application
import android.app.PendingIntent
import android.content.Intent
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkInfo
import android.net.NetworkRequest
import android.os.Build
import android.os.Handler
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogActivity
import org.thoughtcrime.securesms.notifications.NotificationChannels
import org.thoughtcrime.securesms.notifications.NotificationIds
import org.thoughtcrime.securesms.util.FeatureFlags
@Suppress("DEPRECATION")
object NewNetworkConnectivity {
private val TAG: String = Log.tag(NewNetworkConnectivity::class.java)
private val context: Application = ApplicationDependencies.getApplication()
private lateinit var connectivityManager: ConnectivityManager
private var retryCount = 0
private var callback: NetworkCallback? = null
private var handler: Handler? = null
private var hasInternet: Boolean? = null
private var previousHasInternet: Boolean? = null
@JvmStatic
fun start() {
if (FeatureFlags.internalUser() && Build.VERSION.SDK_INT >= 26) {
connectivityManager = ContextCompat.getSystemService(context, ConnectivityManager::class.java)!!
val thread = SignalExecutors.getAndStartHandlerThread("NewNetwork")
handler = Handler(thread.looper)
handler!!.post(this::requestNetwork)
}
}
@RequiresApi(26)
private fun requestNetwork() {
if (retryCount > 5) {
Log.internal().w(TAG, "Unable to request network after $retryCount attempts")
} else {
callback?.let { connectivityManager.unregisterNetworkCallback(it) }
Log.internal().i(TAG, "Requesting network attempt: $retryCount")
val callback = NetworkCallback()
connectivityManager.requestNetwork(NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(), callback, handler!!)
this.callback = callback
}
}
@JvmStatic
fun consistencyCheck() {
if (FeatureFlags.internalUser() && Build.VERSION.SDK_INT >= 26) {
handler?.post {
val oldActiveNetwork: NetworkInfo? = connectivityManager.activeNetworkInfo
val oldIsMet: Boolean = isMet(oldActiveNetwork)
if (hasInternet == null) {
Log.internal().w(TAG, "New has not been initialized yet, defaulting to false")
hasInternet = false
}
when {
oldIsMet == hasInternet && previousHasInternet != hasInternet -> {
Log.internal().i(TAG, "Old and new are consistent: $hasInternet")
previousHasInternet = hasInternet
}
oldIsMet != hasInternet && previousHasInternet != hasInternet -> {
Log.internal().w(TAG, "Network inconsistent old: $oldIsMet new: $hasInternet", Throwable())
Log.internal().w(TAG, "Old active network: $oldActiveNetwork")
previousHasInternet = hasInternet
postInternalErrorNotification()
}
}
} ?: Log.internal().w(TAG, "New handler has not been initialized yet")
}
}
private fun isMet(oldActiveNetwork: NetworkInfo?): Boolean {
return oldActiveNetwork != null && oldActiveNetwork.isConnected
}
private fun postInternalErrorNotification() {
if (!FeatureFlags.internalUser()) return
NotificationManagerCompat.from(context).notify(
NotificationIds.INTERNAL_NET_ERROR,
NotificationCompat.Builder(context, NotificationChannels.FAILURES)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("Network check inconsistency")
.setContentText(context.getString(R.string.MessageDecryptionUtil_tap_to_send_a_debug_log))
.setContentIntent(PendingIntent.getActivity(context, 0, Intent(context, SubmitDebugLogActivity::class.java), 0))
.build()
)
}
@RequiresApi(26)
private class NetworkCallback : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Log.internal().i(TAG, "onAvailable $network ${connectivityManager.getNetworkCapabilities(network)}")
retryCount = 0
hasInternet = true
consistencyCheck()
}
override fun onLost(network: Network) {
Log.internal().i(TAG, "onLost $network")
retryCount = 0
hasInternet = false
consistencyCheck()
}
override fun onUnavailable() {
retryCount++
requestNetwork()
}
}
}

View File

@@ -14,6 +14,7 @@ public final class NotificationIds {
public static final int USER_NOTIFICATION_MIGRATION = 525600;
public static final int DEVICE_TRANSFER = 625420;
public static final int DONOR_BADGE_FAILURE = 630001;
public static final int INTERNAL_NET_ERROR = 404404;
private NotificationIds() { }