mirror of
https://github.com/M66B/FairEmail.git
synced 2026-01-05 12:24:26 +01:00
Workaround for VPN reporting metered connection
This commit is contained in:
@@ -26,7 +26,6 @@ import android.content.SharedPreferences;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
@@ -1630,8 +1629,8 @@ public class FragmentMessages extends FragmentEx {
|
||||
if (download == 0)
|
||||
download = Long.MAX_VALUE;
|
||||
|
||||
ConnectivityManager cm = getContext().getSystemService(ConnectivityManager.class);
|
||||
boolean metered = (cm == null || cm.isActiveNetworkMetered());
|
||||
Boolean isMetered = Helper.isMetered(getContext());
|
||||
boolean metered = (isMetered == null || isMetered);
|
||||
|
||||
int count = 0;
|
||||
int unseen = 0;
|
||||
|
||||
@@ -30,6 +30,9 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.TypedArray;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -291,6 +294,95 @@ public class Helper {
|
||||
return filename.substring(index + 1);
|
||||
}
|
||||
|
||||
static Boolean isMetered(Context context) {
|
||||
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
||||
|
||||
Network active = cm.getActiveNetwork();
|
||||
if (active == null) {
|
||||
Log.i(Helper.TAG, "isMetered: no active network");
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkInfo ni = cm.getNetworkInfo(active);
|
||||
if (ni == null) {
|
||||
Log.i(Helper.TAG, "isMetered: active no info");
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.i(Helper.TAG, "isMetered: active info=" + ni);
|
||||
|
||||
if (!ni.isConnected()) {
|
||||
Log.i(Helper.TAG, "isMetered: active not connected");
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
|
||||
if (caps == null) {
|
||||
Log.i(Helper.TAG, "isMetered: active no caps");
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.i(Helper.TAG, "isMetered: active caps=" + caps);
|
||||
|
||||
boolean unmetered = caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
||||
if (unmetered) {
|
||||
Log.i(Helper.TAG, "isMetered: active unmetered");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
|
||||
Log.i(Helper.TAG, "isMetered: active metered");
|
||||
return true;
|
||||
}
|
||||
|
||||
// VPN: evaluate underlying networks
|
||||
|
||||
Network[] networks = cm.getAllNetworks();
|
||||
if (networks == null) {
|
||||
Log.i(Helper.TAG, "isMetered: no underlying networks");
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean connected = false;
|
||||
for (Network network : networks) {
|
||||
ni = cm.getNetworkInfo(network);
|
||||
if (ni == null) {
|
||||
Log.i(Helper.TAG, "isMetered: no underlying info");
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.i(Helper.TAG, "isMetered: underlying info=" + ni);
|
||||
|
||||
caps = cm.getNetworkCapabilities(network);
|
||||
if (caps == null) {
|
||||
Log.i(Helper.TAG, "isMetered: no underlying caps");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
|
||||
if (ni.isConnected()) {
|
||||
connected = true;
|
||||
Log.i(Helper.TAG, "isMetered: underlying is connected");
|
||||
|
||||
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
|
||||
Log.i(Helper.TAG, "isMetered: underlying is unmetered");
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
Log.i(Helper.TAG, "isMetered: underlying is disconnected");
|
||||
} else
|
||||
Log.i(Helper.TAG, "isMetered: underlying is VPN");
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
Log.i(Helper.TAG, "isMetered: underlying disconnected");
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.i(Helper.TAG, "isMetered: underlying is metered");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void connect(Context context, IMAPStore istore, EntityAccount account) throws MessagingException {
|
||||
try {
|
||||
istore.connect(account.host, account.port, account.user, account.password);
|
||||
|
||||
@@ -36,7 +36,6 @@ import android.media.RingtoneManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@@ -944,10 +943,13 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
Boolean isMetered = Helper.isMetered(ServiceSynchronize.this);
|
||||
boolean metered = (isMetered == null || isMetered);
|
||||
|
||||
try {
|
||||
db.beginTransaction();
|
||||
downloadMessage(
|
||||
ServiceSynchronize.this,
|
||||
ServiceSynchronize.this, metered,
|
||||
folder, ifolder, (IMAPMessage) imessage, message.id);
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
@@ -1025,9 +1027,14 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
Boolean isMetered = Helper.isMetered(ServiceSynchronize.this);
|
||||
boolean metered = (isMetered == null || isMetered);
|
||||
|
||||
try {
|
||||
db.beginTransaction();
|
||||
downloadMessage(ServiceSynchronize.this, folder, ifolder, (IMAPMessage) e.getMessage(), message.id);
|
||||
downloadMessage(
|
||||
ServiceSynchronize.this, metered,
|
||||
folder, ifolder, (IMAPMessage) e.getMessage(), message.id);
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
@@ -2017,11 +2024,16 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
Message[] isub = Arrays.copyOfRange(imessages, from, i + 1);
|
||||
// Fetch on demand
|
||||
|
||||
Boolean isMetered = Helper.isMetered(ServiceSynchronize.this);
|
||||
boolean metered = (isMetered == null || isMetered);
|
||||
|
||||
for (int j = isub.length - 1; j >= 0 && state.running(); j--)
|
||||
try {
|
||||
db.beginTransaction();
|
||||
if (ids[from + j] != null) {
|
||||
downloadMessage(this, folder, ifolder, (IMAPMessage) isub[j], ids[from + j]);
|
||||
downloadMessage(
|
||||
this, metered,
|
||||
folder, ifolder, (IMAPMessage) isub[j], ids[from + j]);
|
||||
Thread.sleep(20);
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
@@ -2262,7 +2274,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
return message;
|
||||
}
|
||||
|
||||
private static void downloadMessage(Context context, EntityFolder folder, IMAPFolder ifolder, IMAPMessage imessage, long id) throws MessagingException, IOException {
|
||||
private static void downloadMessage(Context context, boolean metered, EntityFolder folder, IMAPFolder ifolder, IMAPMessage imessage, long id) throws MessagingException, IOException {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
long download = prefs.getInt("download", 32768);
|
||||
if (download == 0)
|
||||
@@ -2275,9 +2287,6 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
|
||||
MessageHelper helper = new MessageHelper(imessage);
|
||||
|
||||
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
||||
boolean metered = (cm == null || cm.isActiveNetworkMetered());
|
||||
|
||||
boolean fetch = false;
|
||||
if (!message.content)
|
||||
if (!metered || (message.size != null && message.size < download))
|
||||
@@ -2339,16 +2348,11 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
@Override
|
||||
public void onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) {
|
||||
try {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);
|
||||
boolean metered = prefs.getBoolean("metered", true);
|
||||
boolean unmetered = (capabilities != null &&
|
||||
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
|
||||
|
||||
if (!started && (metered || unmetered))
|
||||
if (!started) {
|
||||
EntityLog.log(ServiceSynchronize.this, "Network " + network + " capabilities " + capabilities);
|
||||
|
||||
if (!started && suitableNetwork())
|
||||
queue_reload(true, "connect " + network);
|
||||
if (suitableNetwork())
|
||||
queue_reload(true, "connect " + network);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
|
||||
}
|
||||
@@ -2382,17 +2386,14 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
}
|
||||
|
||||
private boolean suitableNetwork() {
|
||||
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
|
||||
Network active = cm.getActiveNetwork();
|
||||
NetworkCapabilities caps = (active == null ? null : cm.getNetworkCapabilities(active));
|
||||
NetworkInfo ni = (active == null ? null : cm.getNetworkInfo(active));
|
||||
boolean unmetered = (caps != null && caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);
|
||||
boolean metered = prefs.getBoolean("metered", true);
|
||||
|
||||
boolean suitable = (active != null && (metered || unmetered));
|
||||
EntityLog.log(ServiceSynchronize.this, "suitable=" + suitable + " active=" + ni);
|
||||
Boolean isMetered = Helper.isMetered(ServiceSynchronize.this);
|
||||
|
||||
boolean suitable = (isMetered != null && (metered || !isMetered));
|
||||
EntityLog.log(ServiceSynchronize.this,
|
||||
"suitable=" + suitable + " metered=" + metered + " isMetered=" + isMetered);
|
||||
|
||||
// The connected state is deliberately ignored
|
||||
return suitable;
|
||||
|
||||
Reference in New Issue
Block a user