From e67c55d2d39fea60ee06ca14ca7b61ba638b7f2a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 8 Jan 2020 05:06:23 +0100 Subject: implement bluetooth tethering detection, refactor TetheringObservable --- .../java/se/leap/bitmaskclient/BitmaskApp.java | 4 +- .../bitmaskclient/fragments/TetheringDialog.java | 38 +++++++-- .../tethering/TetheringBroadcastReceiver.java | 13 ++- .../tethering/TetheringObservable.java | 50 ++++++++++++ .../bitmaskclient/tethering/TetheringObserver.java | 92 --------------------- .../tethering/TetheringStateManager.java | 93 ++++++++++++++++++++++ 6 files changed, 186 insertions(+), 104 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObserver.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java diff --git a/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java b/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java index 83691802..48910fb5 100644 --- a/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java +++ b/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java @@ -8,7 +8,7 @@ import android.support.v7.app.AppCompatDelegate; import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.RefWatcher; -import se.leap.bitmaskclient.tethering.TetheringObserver; +import se.leap.bitmaskclient.tethering.TetheringStateManager; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; @@ -40,7 +40,7 @@ public class BitmaskApp extends MultiDexApplication { providerObservable.updateProvider(getSavedProviderFromSharedPreferences(preferences)); EipSetupObserver.init(this, preferences); AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); - TetheringObserver.init(this); + TetheringStateManager.getInstance().init(this); } /** 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 65287afe..1d125245 100644 --- a/app/src/main/java/se/leap/bitmaskclient/fragments/TetheringDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/fragments/TetheringDialog.java @@ -15,15 +15,19 @@ import android.text.Spannable; import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import java.util.Observable; +import java.util.Observer; + import butterknife.ButterKnife; import butterknife.InjectView; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.eip.EipCommand; -import se.leap.bitmaskclient.tethering.TetheringObserver; +import se.leap.bitmaskclient.tethering.TetheringObservable; import se.leap.bitmaskclient.utils.PreferenceHelper; import se.leap.bitmaskclient.views.IconCheckboxEntry; @@ -31,7 +35,7 @@ import se.leap.bitmaskclient.views.IconCheckboxEntry; * Created by cyberta on 25.02.18. */ -public class TetheringDialog extends AppCompatDialogFragment { +public class TetheringDialog extends AppCompatDialogFragment implements Observer { public final static String TAG = TetheringDialog.class.getName(); @@ -142,9 +146,17 @@ public class TetheringDialog extends AppCompatDialogFragment { @Override public void onResume() { super.onResume(); - dataset[0].enabled = TetheringObserver.getInstance().isWifiTetheringEnabled(); - dataset[1].enabled = TetheringObserver.getInstance().isUsbTetheringEnabled(); + dataset[0].enabled = TetheringObservable.getInstance().isWifiTetheringEnabled(); + dataset[1].enabled = TetheringObservable.getInstance().isUsbTetheringEnabled(); + dataset[2].enabled = TetheringObservable.getInstance().isBluetoothTetheringEnabled(); adapter.notifyDataSetChanged(); + TetheringObservable.getInstance().addObserver(this); + } + + @Override + public void onPause() { + super.onPause(); + TetheringObservable.getInstance().deleteObserver(this); } public void onItemClick(DialogListAdapter.ViewModel item) { @@ -176,16 +188,28 @@ public class TetheringDialog extends AppCompatDialogFragment { new DialogListAdapter.ViewModel(getContext().getResources().getDrawable(R.drawable.ic_wifi), getContext().getString(R.string.tethering_wifi), PreferenceHelper.getWifiTethering(getContext()), - TetheringObserver.getInstance().isWifiTetheringEnabled()), + TetheringObservable.getInstance().isWifiTetheringEnabled()), new DialogListAdapter.ViewModel(getContext().getResources().getDrawable(R.drawable.ic_usb), getContext().getString(R.string.tethering_usb), PreferenceHelper.getUsbTethering(getContext()), - TetheringObserver.getInstance().isUsbTetheringEnabled()), + TetheringObservable.getInstance().isUsbTetheringEnabled()), new DialogListAdapter.ViewModel(getContext().getResources().getDrawable(R.drawable.ic_bluetooth), getContext().getString(R.string.tethering_bluetooth), PreferenceHelper.getBluetoothTethering(getContext()), - true) + TetheringObservable.getInstance().isUsbTetheringEnabled()) }; } + @Override + public void update(Observable o, Object arg) { + if (o instanceof TetheringObservable) { + TetheringObservable observable = (TetheringObservable) o; + Log.d(TAG, "TetheringObservable is updated"); + dataset[0].enabled = observable.isWifiTetheringEnabled(); + dataset[1].enabled = observable.isUsbTetheringEnabled(); + dataset[2].enabled = observable.isBluetoothTetheringEnabled(); + adapter.notifyDataSetChanged(); + } + } + } diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringBroadcastReceiver.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringBroadcastReceiver.java index c5840171..54c312d7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringBroadcastReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringBroadcastReceiver.java @@ -4,19 +4,26 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.wifi.WifiManager; +import android.util.Log; public class TetheringBroadcastReceiver extends BroadcastReceiver { + private static final String TAG = TetheringBroadcastReceiver.class.getSimpleName(); + @Override public void onReceive(Context context, Intent intent) { if ("android.net.wifi.WIFI_AP_STATE_CHANGED".equals(intent.getAction())) { + Log.d(TAG, "TETHERING WIFI_AP_STATE_CHANGED"); int apState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0); if (WifiHotspotState.WIFI_AP_STATE_ENABLED.ordinal() == apState % 10) { - TetheringObserver.getInstance().setWifiTetheringEnabled(true); + TetheringObservable.setWifiTethering(true); } else { - TetheringObserver.getInstance().setWifiTetheringEnabled(false); + TetheringObservable.setWifiTethering(false); } } else if ("android.net.conn.TETHER_STATE_CHANGED".equals(intent.getAction())) { - TetheringObserver.getInstance().updateUsbTetheringState(); + Log.d(TAG, "TETHERING TETHER_STATE_CHANGED"); + TetheringStateManager.updateUsbTetheringState(); + TetheringStateManager.updateBluetoothTetheringState(); + TetheringStateManager.updateWifiTetheringState(); } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java new file mode 100644 index 00000000..594258bf --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java @@ -0,0 +1,50 @@ +package se.leap.bitmaskclient.tethering; + +import java.util.Observable; + +public class TetheringObservable extends Observable { + private static TetheringObservable instance; + + private boolean isWifiTetheringEnabled; + private boolean isUsbTetheringEnabled; + private boolean isBluetoothTetheringEnabled; + + private TetheringObservable() { } + + public static TetheringObservable getInstance() { + if (instance == null) { + instance = new TetheringObservable(); + } + return instance; + } + + static void setWifiTethering(boolean enabled) { + getInstance().isWifiTetheringEnabled = enabled; + getInstance().setChanged(); + getInstance().notifyObservers(); + } + + static void setUsbTethering(boolean enabled) { + getInstance().isUsbTetheringEnabled = enabled; + getInstance().setChanged(); + getInstance().notifyObservers(); + } + + static void setBluetoothTethering(boolean enabled) { + getInstance().isBluetoothTetheringEnabled = enabled; + getInstance().setChanged(); + getInstance().notifyObservers(); + } + + public boolean isBluetoothTetheringEnabled() { + return isBluetoothTetheringEnabled; + } + + public boolean isUsbTetheringEnabled() { + return isUsbTetheringEnabled; + } + + public boolean isWifiTetheringEnabled() { + return isWifiTetheringEnabled; + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObserver.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObserver.java deleted file mode 100644 index 1d1fa951..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObserver.java +++ /dev/null @@ -1,92 +0,0 @@ -package se.leap.bitmaskclient.tethering; - -import android.content.Context; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.wifi.WifiManager; - -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.Enumeration; - -public class TetheringObserver { - private static TetheringObserver instance; - - private boolean isWifiTetheringEnabled; - private boolean isUsbTetheringEnabled; - private WifiManager wifiManager; - private ConnectivityManager connectivityManager; - private TetheringBroadcastReceiver broadcastReceiver; - - private TetheringObserver() { - } - - public static void init(Context context) { - if (instance == null) { - instance = new TetheringObserver(); - instance.broadcastReceiver = new TetheringBroadcastReceiver(); - IntentFilter intentFilter = new IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED"); - intentFilter.addAction("android.net.conn.TETHER_STATE_CHANGED"); - context.getApplicationContext().registerReceiver(instance.broadcastReceiver, intentFilter); - instance.wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - instance.setWifiTetheringEnabled(instance.isWifiApEnabled()); - instance.connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); - } - } - - private boolean isWifiApEnabled() { - try { - Method method = instance.wifiManager.getClass().getMethod("getWifiApState"); - int tmp = ((Integer) method.invoke(wifiManager)); - return WifiHotspotState.WIFI_AP_STATE_ENABLED.ordinal() == tmp % 10; - } catch (Exception e) { - return false; - } - } - - private boolean getUsbTetheringState() { - try { - - for(Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { - NetworkInterface networkInterface = en.nextElement(); - for(Enumeration enumIpAddr = networkInterface.getInetAddresses(); enumIpAddr.hasMoreElements();){ - InetAddress inetAddress = enumIpAddr.nextElement(); - if(!networkInterface.isLoopback()){ - if(networkInterface.getName().contains("rndis") || networkInterface.getName().contains("usb")){ - return true; - } - } - } - } - } catch(Exception e){ - e.printStackTrace(); - } - - return false; - } - - public static TetheringObserver getInstance() { - if (instance == null) { - throw new RuntimeException("Call init() first!"); - } - - return instance; - } - - void setWifiTetheringEnabled(boolean enabled) { - isWifiTetheringEnabled = enabled; - } - - public boolean isWifiTetheringEnabled() { - return isWifiTetheringEnabled; - } - - void updateUsbTetheringState() { - isUsbTetheringEnabled = getUsbTetheringState(); - } - - public boolean isUsbTetheringEnabled() { - return isUsbTetheringEnabled; - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java new file mode 100644 index 00000000..1e2521b8 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringStateManager.java @@ -0,0 +1,93 @@ +package se.leap.bitmaskclient.tethering; + +import android.content.Context; +import android.content.IntentFilter; +import android.net.wifi.WifiManager; + +import java.lang.reflect.Method; +import java.net.NetworkInterface; +import java.util.Enumeration; + +import se.leap.bitmaskclient.utils.Cmd; + +public class TetheringStateManager { + private static final String TAG = TetheringStateManager.class.getSimpleName(); + private static TetheringStateManager instance; + + private WifiManager wifiManager; + + private TetheringStateManager() { } + + public static TetheringStateManager getInstance() { + if (instance == null) { + instance = new TetheringStateManager(); + } + return instance; + } + + public void init(Context context) { + TetheringBroadcastReceiver broadcastReceiver = new TetheringBroadcastReceiver(); + IntentFilter intentFilter = new IntentFilter("android.net.conn.TETHER_STATE_CHANGED"); + intentFilter.addAction("android.net.wifi.WIFI_AP_STATE_CHANGED"); + context.getApplicationContext().registerReceiver(broadcastReceiver, intentFilter); + instance.wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); + updateWifiTetheringState(); + updateUsbTetheringState(); + updateBluetoothTetheringState(); + } + + private static boolean isWifiApEnabled() { + try { + Method method = instance.wifiManager.getClass().getMethod("getWifiApState"); + int tmp = ((Integer) method.invoke(instance.wifiManager)); + return WifiHotspotState.WIFI_AP_STATE_ENABLED.ordinal() == tmp % 10; + } catch (Exception e) { + return false; + } + } + + + private static boolean getUsbTetheringState() { + try { + for(Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { + NetworkInterface networkInterface = en.nextElement(); + if(!networkInterface.isLoopback()){ + if(networkInterface.getName().contains("rndis") || networkInterface.getName().contains("usb")){ + return true; + } + } + } + } catch(Exception e){ + e.printStackTrace(); + } + + return false; + } + + // Check whether Bluetooth tethering is enabled. + private static boolean isBluetoothTetheringEnabled() { + StringBuilder log = new StringBuilder(); + boolean hasBtPan = false; + try { + hasBtPan = Cmd.runBlockingCmd(new String[] {"ifconfig bt-pan"}, log) == 0; + //Log.d(TAG, "ifconfig result: " + log.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + return hasBtPan; + + } + + static void updateUsbTetheringState() { + TetheringObservable.setUsbTethering(getUsbTetheringState()); + } + + static void updateBluetoothTetheringState() { + TetheringObservable.setBluetoothTethering(isBluetoothTetheringEnabled()); + } + + static void updateWifiTetheringState() { + TetheringObservable.setWifiTethering(isWifiApEnabled()); + } + +} -- cgit v1.2.3