mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Use reflection to get local Bluetooth address.
This is expected to work on Android 8 but not 8.1+.
This commit is contained in:
@@ -6,15 +6,25 @@ import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
|
||||
import org.briarproject.bramble.api.Pair;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
|
||||
|
||||
@NotNullByDefault
|
||||
public class AndroidUtils {
|
||||
|
||||
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
|
||||
@@ -22,11 +32,10 @@ public class AndroidUtils {
|
||||
|
||||
private static final String STORED_REPORTS = "dev-reports";
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Collection<String> getSupportedArchitectures() {
|
||||
List<String> abis = new ArrayList<>();
|
||||
if (SDK_INT >= 21) {
|
||||
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
|
||||
abis.addAll(asList(Build.SUPPORTED_ABIS));
|
||||
} else {
|
||||
abis.add(Build.CPU_ABI);
|
||||
if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
|
||||
@@ -36,24 +45,62 @@ public class AndroidUtils {
|
||||
|
||||
public static String getBluetoothAddress(Context ctx,
|
||||
BluetoothAdapter adapter) {
|
||||
return getBluetoothAddressAndMethod(ctx, adapter).getFirst();
|
||||
}
|
||||
|
||||
public static Pair<String, String> getBluetoothAddressAndMethod(Context ctx,
|
||||
BluetoothAdapter adapter) {
|
||||
// Return the adapter's address if it's valid and not fake
|
||||
@SuppressLint("HardwareIds")
|
||||
String address = adapter.getAddress();
|
||||
if (isValidBluetoothAddress(address)) return address;
|
||||
if (isValidBluetoothAddress(address)) {
|
||||
return new Pair<>(address, "adapter");
|
||||
}
|
||||
// Return the address from settings if it's valid and not fake
|
||||
address = Settings.Secure.getString(ctx.getContentResolver(),
|
||||
"bluetooth_address");
|
||||
if (isValidBluetoothAddress(address)) return address;
|
||||
if (isValidBluetoothAddress(address)) {
|
||||
return new Pair<>(address, "settings");
|
||||
}
|
||||
// Try to get the address via reflection
|
||||
address = getBluetoothAddressByReflection(adapter);
|
||||
if (isValidBluetoothAddress(address)) {
|
||||
return new Pair<>(requireNonNull(address), "reflection");
|
||||
}
|
||||
// Let the caller know we can't find the address
|
||||
return "";
|
||||
return new Pair<>("", "");
|
||||
}
|
||||
|
||||
private static boolean isValidBluetoothAddress(String address) {
|
||||
private static boolean isValidBluetoothAddress(@Nullable String address) {
|
||||
return !StringUtils.isNullOrEmpty(address)
|
||||
&& BluetoothAdapter.checkBluetoothAddress(address)
|
||||
&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getBluetoothAddressByReflection(
|
||||
BluetoothAdapter adapter) {
|
||||
try {
|
||||
Field mServiceField =
|
||||
adapter.getClass().getDeclaredField("mService");
|
||||
mServiceField.setAccessible(true);
|
||||
Object mService = mServiceField.get(adapter);
|
||||
// mService may be null when Bluetooth is disabled
|
||||
if (mService == null) throw new NoSuchFieldException();
|
||||
Method getAddressMethod =
|
||||
mService.getClass().getMethod("getAddress");
|
||||
return (String) getAddressMethod.invoke(mService);
|
||||
} catch (NoSuchFieldException e) {
|
||||
return null;
|
||||
} catch (IllegalAccessException e) {
|
||||
return null;
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
} catch (InvocationTargetException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static File getReportDir(Context ctx) {
|
||||
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@@ -7,15 +7,13 @@ import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
|
||||
import org.acra.builder.ReportBuilder;
|
||||
import org.acra.builder.ReportPrimer;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.bramble.api.Pair;
|
||||
import org.briarproject.briar.BuildConfig;
|
||||
import org.briarproject.briar.android.BriarApplication;
|
||||
import org.briarproject.briar.android.logging.BriefLogFormatter;
|
||||
@@ -23,7 +21,6 @@ import org.briarproject.briar.android.logging.BriefLogFormatter;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -43,8 +40,12 @@ import static android.content.Context.WIFI_SERVICE;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static org.briarproject.bramble.util.AndroidUtils.getBluetoothAddressAndMethod;
|
||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubInetAddress;
|
||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||
|
||||
public class BriarReportPrimer implements ReportPrimer {
|
||||
|
||||
@@ -195,63 +196,53 @@ public class BriarReportPrimer implements ReportPrimer {
|
||||
|
||||
// Is Bluetooth available?
|
||||
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
|
||||
boolean btAvailable = bt != null;
|
||||
// Is Bluetooth enabled?
|
||||
boolean btEnabled = bt != null && bt.isEnabled() &&
|
||||
!StringUtils.isNullOrEmpty(bt.getAddress());
|
||||
// Is Bluetooth connectable?
|
||||
boolean btConnectable = bt != null &&
|
||||
(bt.getScanMode() == SCAN_MODE_CONNECTABLE ||
|
||||
bt.getScanMode() ==
|
||||
SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
// Is Bluetooth discoverable?
|
||||
boolean btDiscoverable = bt != null &&
|
||||
bt.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||
// Is Bluetooth LE scanning and advertising supported?
|
||||
boolean btLeApi = false, btLeScan = false, btLeAdvertise = false;
|
||||
if (bt != null && Build.VERSION.SDK_INT >= 21) {
|
||||
btLeApi = true;
|
||||
btLeScan = bt.getBluetoothLeScanner() != null;
|
||||
btLeAdvertise = bt.getBluetoothLeAdvertiser() != null;
|
||||
}
|
||||
if (bt == null) {
|
||||
customData.put("Bluetooth status", "Not available");
|
||||
} else {
|
||||
// Is Bluetooth enabled?
|
||||
boolean btEnabled = bt.isEnabled()
|
||||
&& !isNullOrEmpty(bt.getAddress());
|
||||
// Is Bluetooth connectable?
|
||||
int scanMode = bt.getScanMode();
|
||||
boolean btConnectable = scanMode == SCAN_MODE_CONNECTABLE ||
|
||||
scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||
// Is Bluetooth discoverable?
|
||||
boolean btDiscoverable =
|
||||
scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||
|
||||
String btStatus;
|
||||
if (btAvailable) btStatus = "Available, ";
|
||||
else btStatus = "Not available, ";
|
||||
if (btEnabled) btStatus += "enabled, ";
|
||||
else btStatus += "not enabled, ";
|
||||
if (btConnectable) btStatus += "connectable, ";
|
||||
else btStatus += "not connectable, ";
|
||||
if (btDiscoverable) btStatus += "discoverable";
|
||||
else btStatus += "not discoverable";
|
||||
customData.put("Bluetooth status", btStatus);
|
||||
if (btLeApi) {
|
||||
String btLeStatus;
|
||||
if (btLeScan) btLeStatus = "Scanning, ";
|
||||
else btLeStatus = "No scanning, ";
|
||||
if (btLeAdvertise) btLeStatus += "advertising";
|
||||
else btLeStatus += "no advertising";
|
||||
customData.put("Bluetooth LE status", btLeStatus);
|
||||
}
|
||||
String btStatus;
|
||||
if (btEnabled) btStatus = "Available, enabled, ";
|
||||
else btStatus = "Available, not enabled, ";
|
||||
if (btConnectable) btStatus += "connectable, ";
|
||||
else btStatus += "not connectable, ";
|
||||
if (btDiscoverable) btStatus += "discoverable";
|
||||
else btStatus += "not discoverable";
|
||||
customData.put("Bluetooth status", btStatus);
|
||||
|
||||
if (bt != null) {
|
||||
customData.put("Bluetooth address",
|
||||
scrubMacAddress(bt.getAddress()));
|
||||
if (SDK_INT >= 21) {
|
||||
// Is Bluetooth LE scanning and advertising supported?
|
||||
boolean btLeScan = bt.getBluetoothLeScanner() != null;
|
||||
boolean btLeAdvertise =
|
||||
bt.getBluetoothLeAdvertiser() != null;
|
||||
String btLeStatus;
|
||||
if (btLeScan) btLeStatus = "Scanning, ";
|
||||
else btLeStatus = "No scanning, ";
|
||||
if (btLeAdvertise) btLeStatus += "advertising";
|
||||
else btLeStatus += "no advertising";
|
||||
customData.put("Bluetooth LE status", btLeStatus);
|
||||
}
|
||||
|
||||
Pair<String, String> p = getBluetoothAddressAndMethod(ctx, bt);
|
||||
String address = p.getFirst();
|
||||
String method = p.getSecond();
|
||||
customData.put("Bluetooth address", scrubMacAddress(address));
|
||||
customData.put("Bluetooth address method", method);
|
||||
}
|
||||
String btSettingsAddr;
|
||||
try {
|
||||
btSettingsAddr = Settings.Secure.getString(
|
||||
ctx.getContentResolver(), "bluetooth_address");
|
||||
} catch (SecurityException e) {
|
||||
btSettingsAddr = "Could not get address from settings";
|
||||
}
|
||||
customData.put("Bluetooth address from settings",
|
||||
scrubMacAddress(btSettingsAddr));
|
||||
|
||||
// Git commit ID
|
||||
customData.put("Commit ID", BuildConfig.GitHash);
|
||||
|
||||
return Collections.unmodifiableMap(customData);
|
||||
return unmodifiableMap(customData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user