diff --git a/bramble-android/src/main/java/org/briarproject/bramble/battery/AndroidBatteryManager.java b/bramble-android/src/main/java/org/briarproject/bramble/battery/AndroidBatteryManager.java
index 3b8250dad..0bd13b0b2 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/battery/AndroidBatteryManager.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/battery/AndroidBatteryManager.java
@@ -19,9 +19,7 @@ import javax.inject.Inject;
import static android.content.Intent.ACTION_BATTERY_CHANGED;
import static android.content.Intent.ACTION_POWER_CONNECTED;
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
-import static android.os.BatteryManager.BATTERY_STATUS_CHARGING;
-import static android.os.BatteryManager.BATTERY_STATUS_FULL;
-import static android.os.BatteryManager.EXTRA_STATUS;
+import static android.os.BatteryManager.EXTRA_PLUGGED;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
@@ -48,9 +46,8 @@ class AndroidBatteryManager implements BatteryManager, Service {
IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED);
Intent i = appContext.registerReceiver(null, filter);
if (i == null) return false;
- int status = i.getIntExtra(EXTRA_STATUS, -1);
- return status == BATTERY_STATUS_CHARGING ||
- status == BATTERY_STATUS_FULL;
+ int status = i.getIntExtra(EXTRA_PLUGGED, 0);
+ return status != 0;
}
@Override
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
index d3f863c6b..6be7582a1 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
@@ -16,6 +16,7 @@ public interface TorConstants {
String PREF_TOR_NETWORK = "network2";
String PREF_TOR_PORT = "port";
String PREF_TOR_MOBILE = "useMobileData";
+ String PREF_TOR_ONLY_WHEN_CHARGING = "onlyWhenCharging";
int PREF_TOR_NETWORK_AUTOMATIC = 0;
int PREF_TOR_NETWORK_WITHOUT_BRIDGES = 1;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
index 46770b884..d672b4cb4 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
@@ -69,6 +69,7 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
+import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHEN_CHARGING;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V2;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
@@ -648,8 +649,10 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (s.getNamespace().equals(ID.getString())) {
LOG.info("Tor settings updated");
settings = s.getSettings();
- // Works around a bug introduced in Tor 0.3.4.8. Could be
- // replaced with callback.transportDisabled() when fixed.
+ // Works around a bug introduced in Tor 0.3.4.8.
+ // https://trac.torproject.org/projects/tor/ticket/28027
+ // Could be replaced with callback.transportDisabled()
+ // when fixed.
disableNetwork();
updateConnectionStatus(networkManager.getNetworkStatus(),
batteryManager.isCharging());
@@ -685,6 +688,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
int network = settings.getInt(PREF_TOR_NETWORK,
PREF_TOR_NETWORK_AUTOMATIC);
boolean useMobile = settings.getBoolean(PREF_TOR_MOBILE, true);
+ boolean onlyWhenCharging =
+ settings.getBoolean(PREF_TOR_ONLY_WHEN_CHARGING, false);
boolean bridgesWork = circumventionProvider.doBridgesWork(country);
boolean automatic = network == PREF_TOR_NETWORK_AUTOMATIC;
@@ -699,9 +704,12 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (!online) {
LOG.info("Disabling network, device is offline");
enableNetwork(false);
+ } else if (!charging && onlyWhenCharging) {
+ LOG.info("Disabling network, device is on battery");
+ enableNetwork(false);
} else if (network == PREF_TOR_NETWORK_NEVER ||
(!useMobile && !wifi)) {
- LOG.info("Disabling network due to setting");
+ LOG.info("Disabling network, device is using mobile data");
enableNetwork(false);
} else if (automatic && blocked && !bridgesWork) {
LOG.info("Disabling network, country is blocked");
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
index 6f4e053be..1be93ebce 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
@@ -75,6 +75,7 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENA
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
+import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHEN_CHARGING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
@@ -111,6 +112,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
public static final String TOR_NETWORK = "pref_key_tor_network";
public static final String TOR_MOBILE = "pref_key_tor_mobile_data";
+ public static final String TOR_ONLY_WHEN_CHARGING =
+ "pref_key_tor_only_when_charging";
private static final Logger LOG =
Logger.getLogger(SettingsFragment.class.getName());
@@ -120,6 +123,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private ListPreference enableBluetooth;
private ListPreference torNetwork;
private SwitchPreference torMobile;
+ private SwitchPreference torOnlyWhenCharging;
private SwitchPreference screenLock;
private ListPreference screenLockTimeout;
private SwitchPreference notifyPrivateMessages;
@@ -165,6 +169,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
enableBluetooth = (ListPreference) findPreference("pref_key_bluetooth");
torNetwork = (ListPreference) findPreference(TOR_NETWORK);
torMobile = (SwitchPreference) findPreference(TOR_MOBILE);
+ torOnlyWhenCharging =
+ (SwitchPreference) findPreference(TOR_ONLY_WHEN_CHARGING);
screenLock = (SwitchPreference) findPreference(PREF_SCREEN_LOCK);
screenLockTimeout =
(ListPreference) findPreference(PREF_SCREEN_LOCK_TIMEOUT);
@@ -202,6 +208,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
enableBluetooth.setOnPreferenceChangeListener(this);
torNetwork.setOnPreferenceChangeListener(this);
torMobile.setOnPreferenceChangeListener(this);
+ torOnlyWhenCharging.setOnPreferenceChangeListener(this);
screenLock.setOnPreferenceChangeListener(this);
screenLockTimeout.setOnPreferenceChangeListener(this);
@@ -362,6 +369,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
torSettings.getBoolean(PREF_TOR_MOBILE, true);
torMobile.setChecked(torMobileSetting);
+ boolean torChargingSetting =
+ torSettings.getBoolean(PREF_TOR_ONLY_WHEN_CHARGING, false);
+ torOnlyWhenCharging.setChecked(torChargingSetting);
+
displayScreenLockSetting();
if (SDK_INT < 26) {
@@ -423,6 +434,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
enableBluetooth.setEnabled(enabled);
torNetwork.setEnabled(enabled);
torMobile.setEnabled(enabled);
+ torOnlyWhenCharging.setEnabled(enabled);
if (!enabled) screenLock.setEnabled(false);
notifyPrivateMessages.setEnabled(enabled);
notifyGroupMessages.setEnabled(enabled);
@@ -519,6 +531,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
} else if (preference == torMobile) {
boolean torMobileSetting = (Boolean) newValue;
storeTorMobileSetting(torMobileSetting);
+ } else if (preference == torOnlyWhenCharging) {
+ boolean torChargingSetting = (Boolean) newValue;
+ storeTorChargingSetting(torChargingSetting);
} else if (preference == screenLock) {
Settings s = new Settings();
s.putBoolean(PREF_SCREEN_LOCK, (Boolean) newValue);
@@ -585,6 +600,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
mergeSettings(s, TOR_NAMESPACE);
}
+ private void storeTorChargingSetting(boolean torChargingSetting) {
+ Settings s = new Settings();
+ s.putBoolean(PREF_TOR_ONLY_WHEN_CHARGING, torChargingSetting);
+ mergeSettings(s, TOR_NAMESPACE);
+ }
+
private void storeBluetoothSettings(boolean btSetting) {
Settings s = new Settings();
s.putBoolean(PREF_BT_ENABLE, btSetting);
diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml
index 4e4e6c6b2..762a29427 100644
--- a/briar-android/src/main/res/values/strings.xml
+++ b/briar-android/src/main/res/values/strings.xml
@@ -380,6 +380,8 @@
Automatic: %1$s (in %2$s)
Use mobile data
+ Connect via Internet (Tor) only when charging
+ Disables Internet connection when device is running on battery
Security
diff --git a/briar-android/src/main/res/xml/settings.xml b/briar-android/src/main/res/xml/settings.xml
index 1ed3c3630..d45a80f86 100644
--- a/briar-android/src/main/res/xml/settings.xml
+++ b/briar-android/src/main/res/xml/settings.xml
@@ -57,6 +57,15 @@
android:widgetLayout="@layout/preference_switch_compat"
app:iconSpaceReserved="false"/>
+
+