summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Constants.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java51
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java15
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/firewall/SetupTetheringTask.java18
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/fragments/TetheringDialog.java28
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java13
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tethering/TetheringState.java7
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java17
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java15
-rw-r--r--app/src/main/res/layout-xlarge/v_switch_list_item.xml2
-rw-r--r--app/src/main/res/layout/f_drawer_main.xml1
-rw-r--r--app/src/main/res/layout/v_switch_list_item.xml2
-rw-r--r--app/src/main/res/values/strings.xml2
15 files changed, 145 insertions, 41 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java b/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java
index eeed29bc..02184f03 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java
@@ -17,6 +17,7 @@ import android.preference.PreferenceManager;
import se.leap.bitmaskclient.R;
import de.blinkt.openvpn.core.VpnStatus.ByteCountListener;
+import se.leap.bitmaskclient.tethering.TetheringObservable;
import java.util.LinkedList;
import java.util.Objects;
@@ -143,8 +144,8 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL
networkStateChange(context);
} else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
boolean screenOffPause = prefs.getBoolean("screenoff", false);
-
- if (screenOffPause) {
+ boolean isTethering = TetheringObservable.getInstance().getTetheringState().isVpnTetheringRunning();
+ if (screenOffPause && !isTethering) {
if (VpnStatus.getLastConnectedVpnProfile() != null && !VpnStatus.getLastConnectedVpnProfile().mPersistTun)
VpnStatus.logError(R.string.screen_nopersistenttun);
diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java
index 60edc941..6ec3076c 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java
@@ -15,7 +15,6 @@ public interface Constants {
String LAST_USED_PROFILE = "last_used_profile";
String EXCLUDED_APPS = "excluded_apps";
String USE_PLUGGABLE_TRANSPORTS = "usePluggableTransports";
- String SU_PERMISSION = "su_permission";
String ALLOW_TETHERING_BLUETOOTH = "tethering_bluetooth";
String ALLOW_TETHERING_WIFI = "tethering_wifi";
String ALLOW_TETHERING_USB = "tethering_usb";
diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
index 104f1edc..715d278d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
@@ -45,10 +45,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import java.util.Observable;
+import java.util.Observer;
import java.util.Set;
import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.Constants;
import se.leap.bitmaskclient.EipFragment;
import se.leap.bitmaskclient.FragmentManagerEnhanced;
import se.leap.bitmaskclient.MainActivity;
@@ -57,12 +58,14 @@ import se.leap.bitmaskclient.ProviderListActivity;
import se.leap.bitmaskclient.ProviderObservable;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.eip.EipCommand;
+import se.leap.bitmaskclient.eip.EipStatus;
import se.leap.bitmaskclient.firewall.FirewallManager;
import se.leap.bitmaskclient.fragments.AboutFragment;
import se.leap.bitmaskclient.fragments.AlwaysOnDialog;
import se.leap.bitmaskclient.fragments.ExcludeAppsFragment;
import se.leap.bitmaskclient.fragments.LogFragment;
import se.leap.bitmaskclient.fragments.TetheringDialog;
+import se.leap.bitmaskclient.tethering.TetheringObservable;
import se.leap.bitmaskclient.utils.PreferenceHelper;
import se.leap.bitmaskclient.views.IconSwitchEntry;
import se.leap.bitmaskclient.views.IconTextEntry;
@@ -76,6 +79,8 @@ import static se.leap.bitmaskclient.Constants.ENABLE_DONATION;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
+import static se.leap.bitmaskclient.Constants.USE_IPv6_FIREWALL;
+import static se.leap.bitmaskclient.Constants.USE_PLUGGABLE_TRANSPORTS;
import static se.leap.bitmaskclient.R.string.about_fragment_title;
import static se.leap.bitmaskclient.R.string.exclude_apps_fragment_title;
import static se.leap.bitmaskclient.R.string.log_fragment_title;
@@ -92,7 +97,7 @@ import static se.leap.bitmaskclient.utils.PreferenceHelper.usePluggableTransport
* See the <a href="https://developer.android.com/design/patterns/navigation-drawer.html#Interaction">
* design guidelines</a> for a complete explanation of the behaviors implemented here.
*/
-public class NavigationDrawerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener {
+public class NavigationDrawerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener, Observer {
/**
* Per the design guidelines, you should show the drawer on launch until the user manually
@@ -126,6 +131,7 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen
private final static String KEY_SHOW_SAVE_BATTERY_ALERT = "KEY_SHOW_SAVE_BATTERY_ALERT";
private volatile boolean showSaveBattery = false;
AlertDialog alertDialog;
+ private FirewallManager firewallManager;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -135,6 +141,8 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen
preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
userLearnedDrawer = preferences.getBoolean(PREF_USER_LEARNED_DRAWER, false);
preferences.registerOnSharedPreferenceChangeListener(this);
+ firewallManager = new FirewallManager(getContext().getApplicationContext(), false);
+
}
@Override
@@ -149,9 +157,18 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen
Bundle savedInstanceState) {
drawerView = inflater.inflate(R.layout.f_drawer_main, container, false);
restoreFromSavedInstance(savedInstanceState);
+ TetheringObservable.getInstance().addObserver(this);
+ EipStatus.getInstance().addObserver(this);
return drawerView;
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ TetheringObservable.getInstance().deleteObserver(this);
+ EipStatus.getInstance().deleteObserver(this);
+ }
+
public boolean isDrawerOpen() {
return drawerLayout != null && drawerLayout.isDrawerOpen(fragmentContainerView);
}
@@ -302,6 +319,7 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen
private void initSaveBatteryEntry() {
saveBattery = drawerView.findViewById(R.id.battery_switch);
+ saveBattery.showSubtitle(false);
saveBattery.setChecked(getSaveBattery(getContext()));
saveBattery.setOnCheckedChangeListener(((buttonView, isChecked) -> {
if (!buttonView.isPressed()) {
@@ -313,6 +331,16 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen
saveBattery(getContext(), false);
}
}));
+ boolean enableEntry = !TetheringObservable.getInstance().getTetheringState().isVpnTetheringRunning();
+ enableSaveBatteryEntry(enableEntry);
+ }
+
+ private void enableSaveBatteryEntry(boolean enabled) {
+ if (saveBattery.isEnabled() == enabled) {
+ return;
+ }
+ saveBattery.setEnabled(enabled);
+ saveBattery.showSubtitle(!enabled);
}
private void initAlwaysOnVpnEntry() {
@@ -374,13 +402,12 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen
firewall = drawerView.findViewById(R.id.enableIPv6Firewall);
boolean show = showExperimentalFeatures(getContext());
firewall.setVisibility(show ? VISIBLE : GONE);
- firewall.setChecked(PreferenceHelper.useIpv6Firewall(this.getContext()));
+ firewall.setChecked(PreferenceHelper.useIpv6Firewall(getContext()));
firewall.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (!buttonView.isPressed()) {
return;
}
PreferenceHelper.setUseIPv6Firewall(getContext(), isChecked);
- FirewallManager firewallManager = new FirewallManager(getContext().getApplicationContext(), false);
if (VpnStatus.isVPNActive()) {
if (isChecked) {
firewallManager.startIPv6Firewall();
@@ -626,8 +653,22 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (key.equals(Constants.USE_PLUGGABLE_TRANSPORTS)) {
+ if (key.equals(USE_PLUGGABLE_TRANSPORTS)) {
initUseBridgesEntry();
+ } else if (key.equals(USE_IPv6_FIREWALL)) {
+ initFirewallEntry();
+ }
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ if (o instanceof TetheringObservable || o instanceof EipStatus) {
+ try {
+ getActivity().runOnUiThread(() ->
+ enableSaveBatteryEntry(!TetheringObservable.getInstance().getTetheringState().isVpnTetheringRunning()));
+ } catch (NullPointerException npe) {
+ // eat me
+ }
}
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java b/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java
index c148497b..ace8a298 100644
--- a/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java
@@ -17,11 +17,15 @@ package se.leap.bitmaskclient.firewall;
*/
import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.widget.Toast;
import java.util.Observable;
import java.util.Observer;
import de.blinkt.openvpn.core.VpnStatus;
+import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.tethering.TetheringObservable;
import se.leap.bitmaskclient.tethering.TetheringState;
import se.leap.bitmaskclient.utils.PreferenceHelper;
@@ -80,9 +84,18 @@ public class FirewallManager implements FirewallCallback, Observer {
@Override
public void onSuRequested(boolean success) {
- PreferenceHelper.setSuPermission(context, success);
if (!success) {
VpnStatus.logError("[FIREWALL] Root permission needed to execute custom firewall rules.");
+ new Handler(Looper.getMainLooper()).post(() -> {
+ Toast.makeText(context.getApplicationContext(), context.getString(R.string.root_permission_error, context.getString(R.string.app_name)), Toast.LENGTH_LONG).show();
+ });
+ TetheringObservable.allowVpnWifiTethering(false);
+ TetheringObservable.allowVpnUsbTethering(false);
+ TetheringObservable.allowVpnBluetoothTethering(false);
+ PreferenceHelper.allowWifiTethering(context, false);
+ PreferenceHelper.allowUsbTethering(context, false);
+ PreferenceHelper.allowBluetoothTethering(context, false);
+ PreferenceHelper.setUseIPv6Firewall(context, false);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/firewall/SetupTetheringTask.java b/app/src/main/java/se/leap/bitmaskclient/firewall/SetupTetheringTask.java
index 7abd01a8..edf79add 100644
--- a/app/src/main/java/se/leap/bitmaskclient/firewall/SetupTetheringTask.java
+++ b/app/src/main/java/se/leap/bitmaskclient/firewall/SetupTetheringTask.java
@@ -130,7 +130,7 @@ public class SetupTetheringTask extends AsyncTask<Void, Boolean, Boolean> {
}
private boolean removeWifiTetheringRules(TetheringState state, StringBuilder log) throws Exception {
- Log.d(TAG, "add Wifi tethering Rules");
+ Log.d(TAG, "remove Wifi tethering Rules");
String[] removeRules = getDeletionRules(state, state.lastSeenWifiAddress, state.lastSeenWifiInterface);
return runBlockingCmd(removeRules, log) == 0;
}
@@ -142,20 +142,24 @@ public class SetupTetheringTask extends AsyncTask<Void, Boolean, Boolean> {
}
private boolean removeUsbTetheringRules(TetheringState state, StringBuilder log) throws Exception {
- Log.d(TAG, "add usb tethering rules");
+ Log.d(TAG, "remove usb tethering rules");
String[] addRules = getDeletionRules(state, state.lastSeenUsbAddress, state.lastSeenUsbInterface);
return runBlockingCmd(addRules, log) == 0;
}
- //TODO: implement the follwing methods -v
- private boolean removeBluetoothTetheringRules(TetheringState state, StringBuilder log) {
- return true;
+ private boolean addBluetoothTetheringRules(TetheringState state, StringBuilder log) throws Exception {
+ Log.d(TAG, "add bluetooth tethering rules");
+ String[] addRules = getAdditionRules(state.bluetoothAddress, state.bluetoothInterface);
+ return runBlockingCmd(addRules, log) == 0;
}
- private boolean addBluetoothTetheringRules(TetheringState state, StringBuilder log) {
- return true;
+ private boolean removeBluetoothTetheringRules(TetheringState state, StringBuilder log) throws Exception {
+ Log.d(TAG, "remove bluetooth tethering rules");
+ String[] addRules = getDeletionRules(state, state.lastSeenBluetoothAddress, state.lastSeenBluetoothInterface);
+ return runBlockingCmd(addRules, log) == 0;
}
+
private String[] getAdditionRules(String addressRange, String interfaceName) {
return new String[] {
"su",
diff --git a/app/src/main/java/se/leap/bitmaskclient/fragments/TetheringDialog.java b/app/src/main/java/se/leap/bitmaskclient/fragments/TetheringDialog.java
index c53d2a6c..900d1885 100644
--- a/app/src/main/java/se/leap/bitmaskclient/fragments/TetheringDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/fragments/TetheringDialog.java
@@ -1,6 +1,8 @@
package se.leap.bitmaskclient.fragments;
import android.app.Dialog;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -150,10 +152,10 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
.setPositiveButton(android.R.string.ok, (dialog, id) -> {
PreferenceHelper.allowWifiTethering(getContext(), dataset[0].checked);
PreferenceHelper.allowUsbTethering(getContext(), dataset[1].checked);
-// PreferenceHelper.allowBluetoothTethering(getContext(), dataset[2].checked);
+ PreferenceHelper.allowBluetoothTethering(getContext(), dataset[2].checked);
TetheringObservable.allowVpnWifiTethering(dataset[0].checked);
TetheringObservable.allowVpnUsbTethering(dataset[1].checked);
-// TetheringObservable.allowVpnBluetoothTethering(dataset[2].checked);
+ TetheringObservable.allowVpnBluetoothTethering(dataset[2].checked);
FirewallManager firewallManager = new FirewallManager(getContext().getApplicationContext(), false);
if (VpnStatus.isVPNActive()) {
if (TetheringObservable.getInstance().getTetheringState().hasAnyDeviceTetheringEnabled() &&
@@ -172,7 +174,7 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
super.onResume();
dataset[0].enabled = TetheringObservable.getInstance().isWifiTetheringEnabled();
dataset[1].enabled = TetheringObservable.getInstance().isUsbTetheringEnabled();
-// dataset[2].enabled = TetheringObservable.getInstance().isBluetoothTetheringEnabled();
+ dataset[2].enabled = TetheringObservable.getInstance().isBluetoothTetheringEnabled();
adapter.notifyDataSetChanged();
TetheringObservable.getInstance().addObserver(this);
}
@@ -199,8 +201,18 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
spannable.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
- Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
- startActivity(intent);
+ try {
+ final Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ final ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.TetherSettings");
+ intent.setComponent(cn);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
+ startActivity(intent);
+ }
+
}
}, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -217,10 +229,10 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
getContext().getString(R.string.tethering_usb),
PreferenceHelper.isUsbTetheringAllowed(getContext()),
TetheringObservable.getInstance().isUsbTetheringEnabled()),
-/* new DialogListAdapter.ViewModel(getContext().getResources().getDrawable(R.drawable.ic_bluetooth),
+ new DialogListAdapter.ViewModel(getContext().getResources().getDrawable(R.drawable.ic_bluetooth),
getContext().getString(R.string.tethering_bluetooth),
PreferenceHelper.isBluetoothTetheringAllowed(getContext()),
- TetheringObservable.getInstance().isUsbTetheringEnabled())*/
+ TetheringObservable.getInstance().isUsbTetheringEnabled())
};
}
@@ -231,7 +243,7 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
Log.d(TAG, "TetheringObservable is updated");
dataset[0].enabled = observable.isWifiTetheringEnabled();
dataset[1].enabled = observable.isUsbTetheringEnabled();
-// dataset[2].enabled = observable.isBluetoothTetheringEnabled();
+ dataset[2].enabled = observable.isBluetoothTetheringEnabled();
adapter.notifyDataSetChanged();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java
index 75d29417..9bca25e9 100644
--- a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java
+++ b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java
@@ -91,9 +91,16 @@ public class TetheringObservable extends Observable {
}
}
- static void setBluetoothTethering(boolean enabled) {
- if (getInstance().tetheringState.isBluetoothTetheringEnabled != enabled) {
- getInstance().tetheringState.isBluetoothTetheringEnabled = enabled;
+ static void setBluetoothTethering(boolean enabled, @NonNull String address, @NonNull String interfaceName) {
+ if (getInstance().tetheringState.isBluetoothTetheringEnabled != enabled ||
+ !getInstance().tetheringState.bluetoothAddress.equals(address) ||
+ !getInstance().tetheringState.bluetoothInterface.equals(interfaceName)) {
+ TetheringState state = getInstance().tetheringState;
+ state.isBluetoothTetheringEnabled = enabled;
+ state.bluetoothAddress = address;
+ state.bluetoothInterface = interfaceName;
+ state.lastSeenBluetoothAddress = address.isEmpty() ? state.lastSeenBluetoothAddress : address;
+ state.lastSeenBluetoothInterface = interfaceName.isEmpty() ? state.lastSeenBluetoothInterface : interfaceName;
getInstance().setChanged();
getInstance().notifyObservers();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringState.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringState.java
index 8ef237c6..21c378ee 100644
--- a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringState.java
+++ b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringState.java
@@ -1,5 +1,8 @@
package se.leap.bitmaskclient.tethering;
+import de.blinkt.openvpn.core.VpnStatus;
+import se.leap.bitmaskclient.eip.EipStatus;
+
public class TetheringState implements Cloneable {
public boolean isWifiTetheringEnabled;
public boolean isUsbTetheringEnabled;
@@ -41,5 +44,9 @@ public class TetheringState implements Cloneable {
return isVpnWifiTetheringAllowed || isVpnUsbTetheringAllowed || isVpnBluetoothTetheringAllowed;
}
+ public boolean isVpnTetheringRunning() {
+ return (tetherWifiVpn() || tetherUsbVpn() || tetherBluetoothVpn()) && (EipStatus.getInstance().isConnecting() || EipStatus.getInstance().isConnected() || EipStatus.getInstance().isBlocking());
+ }
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java
index d3c934f6..0af4c357 100644
--- a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java
@@ -85,7 +85,7 @@ public class TetheringStateManager {
}
static void updateBluetoothTetheringState() {
- //TetheringObservable.setBluetoothTethering(isBluetoothTetheringEnabled());
+ TetheringObservable.setBluetoothTethering(isBluetoothTetheringEnabled(), getBluetoothAddressRange(), getBluetoothInterfaceName());
}
private static String getWifiAddressRange() {
@@ -98,6 +98,11 @@ public class TetheringStateManager {
return getAddressRange(interfaceAddress);
}
+ private static String getBluetoothAddressRange() {
+ String interfaceAddress = getInterfaceAddress(getBluetoothInterface());
+ return getAddressRange(interfaceAddress);
+ }
+
private static String getWlanInterfaceName() {
return getInterfaceName(getWlanInterface());
}
@@ -106,12 +111,20 @@ public class TetheringStateManager {
return getInterfaceName(getUsbInterface());
}
+ private static String getBluetoothInterfaceName() {
+ return getInterfaceName(getBluetoothInterface());
+ }
+
private static NetworkInterface getWlanInterface() {
return getNetworkInterface(new String[]{"wlan", "eth"});
}
private static NetworkInterface getUsbInterface() {
- return getNetworkInterface(new String[]{"rndis", "usb"});
+ return getNetworkInterface(new String[]{"rndis"});
+ }
+
+ private static NetworkInterface getBluetoothInterface() {
+ return getNetworkInterface(new String[]{"bt-pan"});
}
private static boolean isBluetoothTetheringEnabled() {
diff --git a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
index 6f9744bc..238b00a1 100644
--- a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
@@ -29,7 +29,6 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
import static se.leap.bitmaskclient.Constants.SHOW_EXPERIMENTAL;
-import static se.leap.bitmaskclient.Constants.SU_PERMISSION;
import static se.leap.bitmaskclient.Constants.USE_IPv6_FIREWALL;
import static se.leap.bitmaskclient.Constants.USE_PLUGGABLE_TRANSPORTS;
@@ -121,14 +120,6 @@ public class PreferenceHelper {
apply();
}
- public static boolean hasSuPermission(Context context) {
- return getBoolean(context, SU_PERMISSION, false);
- }
-
- public static void setSuPermission(Context context, boolean allowed) {
- putBoolean(context, SU_PERMISSION, allowed);
- }
-
public static boolean getUsePluggableTransports(Context context) {
return getBoolean(context, USE_PLUGGABLE_TRANSPORTS, false);
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java b/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java
index 02347b05..b41f3a50 100644
--- a/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java
+++ b/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java
@@ -7,6 +7,7 @@ import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
+import android.support.v7.widget.AppCompatImageView;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -22,7 +23,7 @@ public class IconSwitchEntry extends LinearLayout {
private TextView textView;
private TextView subtitleView;
- private ImageView iconView;
+ private AppCompatImageView iconView;
private SwitchCompat switchView;
private CompoundButton.OnCheckedChangeListener checkedChangeListener;
@@ -88,6 +89,10 @@ public class IconSwitchEntry extends LinearLayout {
textView.setText(id);
}
+ public void showSubtitle(boolean show) {
+ subtitleView.setVisibility(show ? VISIBLE : GONE);
+ }
+
public void setIcon(@DrawableRes int id) {
iconView.setImageResource(id);
}
@@ -101,4 +106,12 @@ public class IconSwitchEntry extends LinearLayout {
switchView.setChecked(isChecked);
switchView.setOnCheckedChangeListener(checkedChangeListener);
}
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ switchView.setVisibility(enabled ? VISIBLE : GONE);
+ textView.setTextColor(getResources().getColor(enabled ? android.R.color.black : R.color.colorDisabled));
+ iconView.setImageAlpha(enabled ? 255 : 128);
+ }
}
diff --git a/app/src/main/res/layout-xlarge/v_switch_list_item.xml b/app/src/main/res/layout-xlarge/v_switch_list_item.xml
index c393a0f8..8ad83650 100644
--- a/app/src/main/res/layout-xlarge/v_switch_list_item.xml
+++ b/app/src/main/res/layout-xlarge/v_switch_list_item.xml
@@ -5,7 +5,7 @@
android:layout_width="match_parent"
>
- <ImageView
+ <android.support.v7.widget.AppCompatImageView
android:id="@+id/material_icon"
android:layout_width="?android:attr/listPreferredItemHeight"
android:layout_height="?android:attr/listPreferredItemHeight"
diff --git a/app/src/main/res/layout/f_drawer_main.xml b/app/src/main/res/layout/f_drawer_main.xml
index 191d547f..7e6291b7 100644
--- a/app/src/main/res/layout/f_drawer_main.xml
+++ b/app/src/main/res/layout/f_drawer_main.xml
@@ -65,6 +65,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:text="@string/save_battery"
+ app:subtitle="@string/subtitle_save_battery"
app:icon="@drawable/ic_battery_36"
/>
diff --git a/app/src/main/res/layout/v_switch_list_item.xml b/app/src/main/res/layout/v_switch_list_item.xml
index a92e78b1..6a2e4a8d 100644
--- a/app/src/main/res/layout/v_switch_list_item.xml
+++ b/app/src/main/res/layout/v_switch_list_item.xml
@@ -5,7 +5,7 @@
android:layout_width="match_parent"
>
- <ImageView
+ <android.support.v7.widget.AppCompatImageView
android:id="@+id/material_icon"
android:layout_width="?android:attr/listPreferredItemHeightSmall"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b5fc2fa2..abab24df 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -102,6 +102,7 @@
<string name="vpn_certificate_is_invalid">VPN certificate is invalid. Try to download a new one.</string>
<string name="vpn_certificate_user_message">The VPN certificate is invalid. Please log in to download a new one.</string>
<string name="save_battery">Save battery</string>
+ <string name="subtitle_save_battery">Disabled while VPN Hotspot on</string>
<string name="save_battery_message">Background data connections will hibernate when your phone is inactive.</string>
<string name="always_on_vpn">Always-on VPN</string>
<string name="subtitle_always_on_vpn">Open Android System Settings</string>
@@ -139,4 +140,5 @@
<string name="warning_option_try_pt">Try obfuscated connection</string>
<string name="warning_option_try_ovpn">Try standard connection</string>
<string name="vpn_error_establish">Android failed to establish the VPN service.</string>
+ <string name="root_permission_error">%s cannot execute features like VPN Hotspot or IPv6 firewall without root permissions.</string>
</resources>