Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Add support for ble scanning to speed up reconnection #1416

Open
wants to merge 1 commit into
base: master
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,13 @@
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
</intent-filter>
</receiver>
<receiver
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the lifecycle of this receiver? Is it running all the time, basically as a singleton? Is that intended? What if there were two devices, waiting for reconnection?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does GB support multiple devices in a waiting for reconnection state already?
As far as I have understood the Android-concept here, the receiver is always active and acting like a singleton. Since the address to match and a uuid are given as extras to the intent when starting a scan, it shouldn't be a problem to have several devices in a waiting for reconnect state.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not yet, I'm just checking for the future. There's even a WIP PR for multi device PR, but we haven't gotten around at making it ready for prime time. :-(

I think I understand the intention now, maybe deserves a javadoc explanation :-)

android:name=".externalevents.BluetoothScanCallbackReceiver"
android:exported="false">
<intent-filter>
<action android:name="nodomain.freeyourgadget.gadgetbridge.blescancallback" />
</intent-filter>
</receiver>
<receiver
android:name=".service.receivers.GBMusicControlReceiver"
android:exported="false">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* Copyright (C) 2019 Andreas Böhler

This file is part of Gadgetbridge.

Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.externalevents;

import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;


import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;

public class BluetoothScanCallbackReceiver extends BroadcastReceiver {

private static final Logger LOG = LoggerFactory.getLogger(BluetoothScanCallbackReceiver.class);
private String mSeenScanCallbackUUID = "";

@TargetApi(Build.VERSION_CODES.O)
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(!action.equals("nodomain.freeyourgadget.gadgetbridge.blescancallback") || !intent.hasExtra("address") || !intent.hasExtra("uuid")) {
return;
}

String wantedAddress = intent.getExtras().getString("address");
String uuid = intent.getExtras().getString("uuid");

int bleCallbackType = intent.getIntExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, -1);
if(bleCallbackType != -1) {
//LOG.debug("Passive background scan callback type: " + bleCallbackType);
ArrayList<ScanResult> scanResults = intent.getParcelableArrayListExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT);
for(ScanResult result: scanResults) {
BluetoothDevice device = result.getDevice();
if(device.getAddress().equals(wantedAddress) && !mSeenScanCallbackUUID.equals(uuid)) {
mSeenScanCallbackUUID = uuid;
LOG.info("ScanCallbackReceiver has found " + device.getAddress() + "(" + device.getName() + ")");
BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner().stopScan(getScanCallbackIntent(GBApplication.getContext(), wantedAddress, uuid));
GBApplication.deviceService().connect(DeviceHelper.getInstance().toSupportedDevice(device));

}
}
}
}

@TargetApi(Build.VERSION_CODES.O)
public static PendingIntent getScanCallbackIntent(Context context, String address, String uuid) {
Intent intent = new Intent(context, BluetoothScanCallbackReceiver.class);
intent.setAction("nodomain.freeyourgadget.gadgetbridge.blescancallback");
intent.putExtra("address", address);
intent.putExtra("uuid", uuid);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@
import java.util.Set;
import java.util.UUID;

import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.Logging;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.CheckInitializedAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;

/**
* Abstract base class for all devices connected through Bluetooth Low Energy (LE) aka
Expand Down Expand Up @@ -74,6 +76,14 @@ public boolean connect() {
if (mQueue == null) {
mQueue = new BtLEQueue(getBluetoothAdapter(), getDevice(), this, this, getContext(), mSupportedServerServices);
mQueue.setAutoReconnect(getAutoReconnect());
GBPrefs prefs = GBApplication.getGBPrefs();
boolean autoReconnectScan = GBPrefs.AUTO_RECONNECT_SCAN_DEFAULT;
if (prefs != null) {
autoReconnectScan = prefs.getAutoReconnectScan();
}
// Override the user preference if required by the device
autoReconnectScan = autoReconnectScan || useBleScannerForReconnect();
mQueue.setBleScannerForReconnect(autoReconnectScan);
}
return mQueue.connect();
}
Expand Down Expand Up @@ -385,4 +395,8 @@ public boolean onDescriptorReadRequest(BluetoothDevice device, int requestId, in
public boolean onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
return false;
}

public boolean useBleScannerForReconnect() {
return false;
}
}