Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Enable BSSID logging #73

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class MessageContext {
private final long estimatedNextTimestamp;
private final String deviceName;
@Nullable private final String currentSsid;
@Nullable private final String currentBssid;

MessageContext(
long nextAlarmclockTimestamp,
Expand All @@ -26,7 +27,8 @@ public class MessageContext {
long currentTimestamp,
long estimatedNextTimestamp,
String deviceName,
@Nullable String currentSsid) {
@Nullable String currentSsid,
@Nullable String currentBssid) {
this.nextAlarmclockTimestamp = nextAlarmclockTimestamp;
this.batteryStatus = batteryStatus;
this.conditionContents = conditionContents;
Expand All @@ -35,6 +37,7 @@ public class MessageContext {
this.estimatedNextTimestamp = estimatedNextTimestamp;
this.deviceName = deviceName;
this.currentSsid = currentSsid;
this.currentBssid = currentBssid;
}

public long getNextAlarmclockTimestamp() {
Expand Down Expand Up @@ -69,4 +72,9 @@ public String getDeviceName() {
public String getCurrentSsid() {
return currentSsid;
}

@Nullable
public String getCurrentBssid() {
return currentBssid;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public MessageContextProvider(Context applicationContext) {
public MessageContext getContext() {
long currentTimestamp = System.currentTimeMillis();
String currentSsid = networkService.getCurrentSsid();
String currentBssid = networkService.getCurrentBssid();
return new MessageContext(
alarmclockTimestampProvider.getNextAlarmclockTimestamp(),
batteryStatusProvider.getCurrentBatteryStatus(),
Expand All @@ -44,6 +45,7 @@ public MessageContext getContext() {
currentTimestamp,
preferences.getLong(NEXT_SCHEDULE, 0L),
deviceNameProvider.getDeviceName(),
currentSsid);
currentSsid,
currentBssid);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,25 @@ public String getCurrentSsid() {
return wifiEventConsumer.getCurrentSsid();
}

@Nullable
public String getCurrentBssid() {
// since the detection of wifi networks in Android < 12 with a network callback is flaky
// due to the SSID not being present in the event data, we re-check the current wifi
// whenever we need it
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && wifiCallbackApi23 != null) {
wifiCallbackApi23.checkWifiConnection();
}
return wifiEventConsumer.getCurrentBssid();
}

public static Optional<String> getSsid(Optional<WifiInfo> wifiInfo) {
return wifiInfo.map(WifiInfo::getSSID).map(NetworkService::normalizeSsid);
}

public static Optional<String> getBssid(Optional<WifiInfo> wifiInfo) {
return wifiInfo.map(WifiInfo::getBSSID);
}

private static String normalizeSsid(String ssid) {
if (ssid == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
public class WifiCallback extends ConnectivityManager.NetworkCallback {
private static final String TAG = "WifiCallback";
private final Map<Long, Optional<String>> ssidByNetworkHandle = new ConcurrentHashMap<>();
private final Map<Long, Optional<String>> bssidByNetworkHandle = new ConcurrentHashMap<>();
private final WifiEventConsumer consumer;

public WifiCallback(WifiEventConsumer consumer) {
Expand All @@ -32,13 +33,15 @@ public void onCapabilitiesChanged(
@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
long networkHandle = network.getNetworkHandle();
Optional<String> current = NetworkService.getSsid(getWifiInfo(networkCapabilities));
Optional<String> currentB = NetworkService.getBssid(getWifiInfo(networkCapabilities));
Optional<String> previous = ssidByNetworkHandle.putIfAbsent(networkHandle, current);
Optional<String> previousB = bssidByNetworkHandle.putIfAbsent(networkHandle, currentB);
// absent means not a Wi-Fi network, null means (previously) unknown
//noinspection OptionalAssignedToNull
if (previous == null) {
if (current.isPresent()) {
if (previous == null || previousB == null) {
if (current.isPresent() && currentB.isPresent()) {
DatabaseLogger.d(TAG, "Connected to Wifi network " + networkHandle);
consumer.wifiConnected(current.get());
consumer.wifiConnected(current.get(), currentB.get());
} else {
DatabaseLogger.d(TAG, "Connected to non-Wifi network " + networkHandle);
}
Expand All @@ -49,10 +52,11 @@ public void onCapabilitiesChanged(
public void onLost(@NonNull Network network) {
long networkHandle = network.getNetworkHandle();
Optional<String> removed = ssidByNetworkHandle.remove(networkHandle);
if (removed != null) {
if (removed.isPresent()) {
Optional<String> removedB = bssidByNetworkHandle.remove(networkHandle);
if (removed != null && removedB != null) {
if (removed.isPresent() && removedB.isPresent()) {
DatabaseLogger.d(TAG, "Lost Wifi network " + networkHandle);
consumer.wifiDisconnected(removed.get());
consumer.wifiDisconnected(removed.get(), removedB.get());
} else {
DatabaseLogger.d(TAG, "Lost non-Wifi network " + networkHandle);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ public void onLost(@NonNull Network network) {
// on every publishing schedule
void checkWifiConnection() {
Optional<String> ssid = getConnectedSsid();
if (ssid.isPresent()) {
consumer.wifiConnected(ssid.get());
Optional<String> bssid = getConnectedBssid();
if (ssid.isPresent() && bssid.isPresent()) {
consumer.wifiConnected(ssid.get(), bssid.get());
} else {
consumer.wifiDisconnected(null);
consumer.wifiDisconnected(null, null);
}
}

Expand All @@ -52,4 +53,10 @@ private Optional<String> getConnectedSsid() {
Optional.ofNullable(wifiManager.getConnectionInfo())
.filter(w -> w.getSupplicantState() == SupplicantState.COMPLETED));
}

private Optional<String> getConnectedBssid() {
return NetworkService.getBssid(
Optional.ofNullable(wifiManager.getConnectionInfo())
.filter(w -> w.getSupplicantState() == SupplicantState.COMPLETED));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class WifiEventConsumer {
// will be reset so that we do trigger an event after restart even if the current network is the
// same as before the app restart
private static final AtomicReference<String> CURRENT_SSID = new AtomicReference<>();
private static final AtomicReference<String> CURRENT_BSSID = new AtomicReference<>();
private final SharedPreferences preference;
private final Scheduler scheduler;

Expand All @@ -31,14 +32,14 @@ public WifiEventConsumer(Context applicationContext) {
scheduler = new Scheduler(applicationContext);
}

public void wifiDisconnected(@Nullable String ssid) {
if (CURRENT_SSID.getAndSet(null) != null) {
public void wifiDisconnected(@Nullable String ssid, @Nullable String bssid) {
if (CURRENT_SSID.getAndSet(null) != null || CURRENT_BSSID.getAndSet(null) != null) {
if (ssid != null) {
DatabaseLogger.logDetection("Wi-Fi disconnected: " + ssid);
DatabaseLogger.logDetection("Wi-Fi disconnected: " + ssid + " " + bssid);
} else {
DatabaseLogger.logDetection("Wi-Fi disconnected");
}
DatabaseLogger.i(TAG, "Wi-Fi disconnected: " + ssid);
DatabaseLogger.i(TAG, "Wi-Fi disconnected: " + ssid + " " + bssid);
if (preference.getBoolean(SEND_VIA_MOBILE_NETWORK, false)) {
DatabaseLogger.i(TAG, "Triggering scheduler after disconnect");
// since we don't want to continuously send "offline" / "online" ping-pong, let's
Expand All @@ -48,22 +49,27 @@ public void wifiDisconnected(@Nullable String ssid) {
scheduler.runIn(15, TimeUnit.SECONDS);
}
} else {
DatabaseLogger.d(TAG, "Ignoring disconnect for already disconnected network " + ssid);
DatabaseLogger.d(TAG, "Ignoring disconnect for already disconnected network " + ssid + " " + bssid);
}
}

public void wifiConnected(@NonNull String ssid) {
if (!ssid.equals(CURRENT_SSID.getAndSet(ssid))) {
DatabaseLogger.logDetection("Wi-Fi connected: " + ssid);
DatabaseLogger.i(TAG, "Triggering scheduler after connecting to Wi-Fi " + ssid);
public void wifiConnected(@NonNull String ssid, @NonNull String bssid) {
if (!ssid.equals(CURRENT_SSID.getAndSet(ssid)) && !bssid.equals(CURRENT_BSSID.getAndSet(bssid))) {
DatabaseLogger.logDetection("Wi-Fi connected/changed: " + ssid + " " + bssid);
DatabaseLogger.i(TAG, "Triggering scheduler after connecting to Wi-Fi " + ssid + " " + bssid);
scheduler.runNow();
} else {
DatabaseLogger.d(TAG, "Ignoring connect for already connected network " + ssid);
DatabaseLogger.d(TAG, "Ignoring connect for already connected network " + ssid + " " + bssid);
}
}

@Nullable
public String getCurrentSsid() {
return CURRENT_SSID.get();
}

@Nullable
public String getCurrentBssid() {
return CURRENT_BSSID.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ public boolean apply(MessageContext messageContext, Message.MessageBuilder build
return true;
}
},
CONNECTED_WIFI_BSSID {
@Override
public boolean apply(MessageContext messageContext, Message.MessageBuilder builder) {
builder.withEntry(
this,
messageContext.getCurrentBssid() == null
? UNKNOWN
: messageContext.getCurrentBssid());
return true;
}
},
GEO_LOCATION {
@Override
public boolean apply(MessageContext messageContext, Message.MessageBuilder builder) {
Expand Down Expand Up @@ -133,6 +144,7 @@ public static MessageItem[] settingValues() {
CHARGING_STATE,
PLUG_STATE,
CONNECTED_WIFI,
CONNECTED_WIFI_BSSID,
GEO_LOCATION,
CURRENT_TIMESTAMP,
NEXT_SCHEDULED_TIMESTAMP,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,18 @@ public void onReceive(Context context, Intent intent) {
w ->
w.getSupplicantState()
== SupplicantState.COMPLETED));
Optional<String> bssid =
NetworkService.getBssid(
Optional.ofNullable(wifiManager.getConnectionInfo())
.filter(
w ->
w.getSupplicantState()
== SupplicantState.COMPLETED));
WifiEventConsumer consumer = new WifiEventConsumer(applicationContext);
if (ssid.isPresent()) {
consumer.wifiConnected(ssid.get());
consumer.wifiConnected(ssid.get(), bssid.get());
} else {
consumer.wifiDisconnected(null);
consumer.wifiDisconnected(null,null);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-de/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<item><b>chargingState</b>: Ladezustand, mögliche Werte: CHARGING, DISCHARGING, FULL, NOT_CHARGING, N/A</item>
<item><b>plugState</b>: Ladeanschluss, mögliche Werte: AC, USB, WIRELESS, N/A</item>
<item><b>connectedWifi</b>: Die SSID des aktuell verbundenen WLANs. Kann \"N/A\" sein, wenn das Gerät nicht verbunden ist oder die SSID nicht bestimmt werden kann.</item>
<item><b>connectedWifiBssid</b>: Die BSSID des aktuell verbundenen WLANs. Kann \"N/A\" sein, wenn das Gerät nicht verbunden ist oder die BSSID nicht bestimmt werden kann.</item>
<item><b>geoLocation</b>: Der letzte bekannte Standort deines Gerätes, nach RFC 5870 encodiert. Er enthält einen zusätzlichen Parameter \"timestamp\", welcher das Alter des Standorts seit dem 1. 1. 1970 angibt.</item>
<item><b>currentTimestamp</b>: Der Zeitstempel in Sekunden seit dem 1. 1. 1970, zu dem diese Nachricht generiert worden ist.</item>
<item><b>nextScheduledTimestamp</b>: Der Zeitstempel in Sekunden seit dem 1. 1. 1970, für den die nächste Nachricht geplant ist. Oder 0, wenn nicht geplant (z.B. wenn keine Bedingung erfüllt ist)</item>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<item><b>chargingState</b>: Possible values: CHARGING, DISCHARGING, FULL, NOT_CHARGING, N/A</item>
<item><b>plugState</b>: Possible values: AC, USB, WIRELESS, N/A</item>
<item><b>connectedWifi</b>: The SSID of the network you are currently connected to. May be \"N/A\" if your device is not connected or the app is unable to determine the SSID.</item>
<item><b>connectedWifiBssid</b>: The BSSID of the network you are currently connected to. May be \"N/A\" if your device is not connected or the app is unable to determine the BSSID.</item>
<item><b>geoLocation</b>: The last known geo location of your device. It is encoded according to RFC 5870 with custom parameter \"timestamp\" which contains the age of the location in seconds since 1970–01–01.</item>
<item><b>currentTimestamp</b>: The timestamp when this message was generated in seconds since 1970–01–01.</item>
<item><b>nextScheduledTimestamp</b>: The timestamp when the next message is scheduled in seconds since 1970–01–01, or 0 if not scheduled (e.g. if currently no condition matches).</item>
Expand Down