summaryrefslogtreecommitdiff
path: root/packages/CompanionDeviceManager
diff options
context:
space:
mode:
Diffstat (limited to 'packages/CompanionDeviceManager')
-rw-r--r--packages/CompanionDeviceManager/AndroidManifest.xml2
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java16
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java197
3 files changed, 162 insertions, 53 deletions
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 65cac09a09b3..34bc4ebcd0aa 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -26,6 +26,8 @@
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<application
android:allowClearUserData="true"
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 12bab18c88c9..14b9de59bf5a 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -16,10 +16,9 @@
package com.android.companiondevicemanager;
-import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
import android.app.Activity;
-import android.bluetooth.BluetoothDevice;
import android.companion.CompanionDeviceManager;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -34,6 +33,8 @@ import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.companiondevicemanager.DeviceDiscoveryService.DeviceFilterPair;
+
public class DeviceChooserActivity extends Activity {
private static final boolean DEBUG = false;
@@ -55,11 +56,11 @@ public class DeviceChooserActivity extends Activity {
if (getService().mRequest.isSingleDevice()) {
setContentView(R.layout.device_confirmation);
- final BluetoothDevice selectedDevice = getService().mDevicesFound.get(0);
+ final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0);
setTitle(Html.fromHtml(getString(
R.string.confirmation_title,
getCallingAppName(),
- getDeviceDisplayName(selectedDevice)), 0));
+ selectedDevice.getDisplayName()), 0));
getService().mSelectedDevice = selectedDevice;
} else {
setContentView(R.layout.device_chooser);
@@ -127,10 +128,11 @@ public class DeviceChooserActivity extends Activity {
return DeviceDiscoveryService.sInstance;
}
- protected void onPairTapped(BluetoothDevice selectedDevice) {
- getService().onDeviceSelected(getCallingPackage(), selectedDevice.getAddress());
+ protected void onPairTapped(DeviceFilterPair selectedDevice) {
+ getService().onDeviceSelected(
+ getCallingPackage(), getDeviceMacAddress(selectedDevice.device));
setResult(RESULT_OK,
- new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice));
+ new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice.device));
finish();
}
} \ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index f0f910848943..e1e60bb99374 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -16,8 +16,10 @@
package com.android.companiondevicemanager;
-import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName;
-import static android.companion.BluetoothLEDeviceFilter.nullsafe;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
+
+import static com.android.internal.util.ArrayUtils.isEmpty;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -32,28 +34,38 @@ import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.companion.AssociationRequest;
+import android.companion.BluetoothDeviceFilter;
+import android.companion.BluetoothDeviceFilterUtils;
import android.companion.BluetoothLEDeviceFilter;
import android.companion.CompanionDeviceManager;
+import android.companion.DeviceFilter;
import android.companion.ICompanionDeviceDiscoveryService;
import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.IFindDeviceCallback;
+import android.companion.WifiDeviceFilter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
+import android.net.wifi.WifiManager;
import android.os.IBinder;
+import android.os.Parcelable;
import android.os.RemoteException;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
+
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
+import java.util.Objects;
public class DeviceDiscoveryService extends Service {
@@ -63,12 +75,16 @@ public class DeviceDiscoveryService extends Service {
static DeviceDiscoveryService sInstance;
private BluetoothAdapter mBluetoothAdapter;
- private BluetoothLEDeviceFilter mFilter;
- private ScanFilter mScanFilter;
+ private WifiManager mWifiManager;
private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build();
- AssociationRequest<?> mRequest;
- List<BluetoothDevice> mDevicesFound;
- BluetoothDevice mSelectedDevice;
+ private List<DeviceFilter<?>> mFilters;
+ private List<BluetoothLEDeviceFilter> mBLEFilters;
+ private List<BluetoothDeviceFilter> mBluetoothFilters;
+ private List<WifiDeviceFilter> mWifiFilters;
+ private List<ScanFilter> mBLEScanFilters;
+ AssociationRequest mRequest;
+ List<DeviceFilterPair> mDevicesFound;
+ DeviceFilterPair mSelectedDevice;
DevicesAdapter mDevicesAdapter;
IFindDeviceCallback mFindCallback;
ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
@@ -95,11 +111,13 @@ public class DeviceDiscoveryService extends Service {
private final ScanCallback mBLEScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
- final BluetoothDevice device = result.getDevice();
+ final DeviceFilterPair<ScanResult> deviceFilterPair
+ = DeviceFilterPair.findMatch(result, mBLEFilters);
+ if (deviceFilterPair == null) return;
if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST) {
- onDeviceLost(device);
+ onDeviceLost(deviceFilterPair);
} else {
- onDeviceFound(device);
+ onDeviceFound(deviceFilterPair);
}
}
};
@@ -109,15 +127,35 @@ public class DeviceDiscoveryService extends Service {
private BroadcastReceiver mBluetoothDeviceFoundBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- final BluetoothDevice device = intent.getParcelableExtra(
- BluetoothDevice.EXTRA_DEVICE);
- if (!mFilter.matches(device)) return; // ignore device
-
+ final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ final DeviceFilterPair<BluetoothDevice> deviceFilterPair
+ = DeviceFilterPair.findMatch(device, mBluetoothFilters);
+ if (deviceFilterPair == null) return;
if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
- onDeviceFound(device);
+ onDeviceFound(deviceFilterPair);
} else {
- onDeviceLost(device);
+ onDeviceLost(deviceFilterPair);
+ }
+ }
+ };
+
+ private BroadcastReceiver mWifiDeviceFoundBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+ List<android.net.wifi.ScanResult> scanResults = mWifiManager.getScanResults();
+
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Wifi scan results: " + TextUtils.join("\n", scanResults));
+ }
+
+ for (int i = 0; i < scanResults.size(); i++) {
+ DeviceFilterPair<android.net.wifi.ScanResult> deviceFilterPair =
+ DeviceFilterPair.findMatch(scanResults.get(i), mWifiFilters);
+ if (deviceFilterPair != null) onDeviceFound(deviceFilterPair);
+ }
}
+
}
};
@@ -135,6 +173,7 @@ public class DeviceDiscoveryService extends Service {
mBluetoothAdapter = getSystemService(BluetoothManager.class).getAdapter();
mBLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
+ mWifiManager = getSystemService(WifiManager.class);
mDevicesFound = new ArrayList<>();
mDevicesAdapter = new DevicesAdapter();
@@ -142,23 +181,39 @@ public class DeviceDiscoveryService extends Service {
sInstance = this;
}
- private void startDiscovery(AssociationRequest<?> request) {
- //TODO support other protocols as well
+ private void startDiscovery(AssociationRequest request) {
mRequest = request;
- mFilter = nullsafe((BluetoothLEDeviceFilter) request.getDeviceFilter());
- mScanFilter = mFilter.getScanFilter();
+
+ mFilters = request.getDeviceFilters();
+ mWifiFilters = ArrayUtils.filter(mFilters, WifiDeviceFilter.class);
+ mBluetoothFilters = ArrayUtils.filter(mFilters, BluetoothDeviceFilter.class);
+ mBLEFilters = ArrayUtils.filter(mFilters, BluetoothLEDeviceFilter.class);
+ mBLEScanFilters = ArrayUtils.map(mBLEFilters, BluetoothLEDeviceFilter::getScanFilter);
reset();
- final IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
- intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED);
+ if (shouldScan(mBluetoothFilters)) {
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
+ intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED);
- registerReceiver(mBluetoothDeviceFoundBroadcastReceiver, intentFilter);
- mBluetoothAdapter.startDiscovery();
+ registerReceiver(mBluetoothDeviceFoundBroadcastReceiver, intentFilter);
+ mBluetoothAdapter.startDiscovery();
+ }
- mBLEScanner.startScan(
- Collections.singletonList(mScanFilter), mDefaultScanSettings, mBLEScanCallback);
+ if (shouldScan(mBLEFilters)) {
+ mBLEScanner.startScan(mBLEScanFilters, mDefaultScanSettings, mBLEScanCallback);
+ }
+
+ if (shouldScan(mWifiFilters)) {
+ registerReceiver(mWifiDeviceFoundBroadcastReceiver,
+ new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+ mWifiManager.startScan();
+ }
+ }
+
+ private boolean shouldScan(List<? extends DeviceFilter> mediumSpecificFilters) {
+ return !isEmpty(mediumSpecificFilters) || isEmpty(mFilters);
}
private void reset() {
@@ -178,25 +233,18 @@ public class DeviceDiscoveryService extends Service {
mBluetoothAdapter.cancelDiscovery();
mBLEScanner.stopScan(mBLEScanCallback);
unregisterReceiver(mBluetoothDeviceFoundBroadcastReceiver);
+ unregisterReceiver(mWifiDeviceFoundBroadcastReceiver);
stopSelf();
}
- private void onDeviceFound(BluetoothDevice device) {
+ private void onDeviceFound(@Nullable DeviceFilterPair device) {
if (mDevicesFound.contains(device)) {
return;
}
- if (DEBUG) {
- Log.i(LOG_TAG, "Considering device " + getDeviceDisplayName(device));
- }
+ if (DEBUG) Log.i(LOG_TAG, "Found device " + device.getDisplayName() + " "
+ + getDeviceMacAddress(device.device));
- if (!mFilter.matches(device)) {
- return;
- }
-
- if (DEBUG) {
- Log.i(LOG_TAG, "Found device " + getDeviceDisplayName(device));
- }
if (mDevicesFound.isEmpty()) {
onReadyToShowUI();
}
@@ -217,12 +265,10 @@ public class DeviceDiscoveryService extends Service {
}
}
- private void onDeviceLost(BluetoothDevice device) {
+ private void onDeviceLost(@Nullable DeviceFilterPair device) {
mDevicesFound.remove(device);
mDevicesAdapter.notifyDataSetChanged();
- if (DEBUG) {
- Log.i(LOG_TAG, "Lost device " + getDeviceDisplayName(device));
- }
+ if (DEBUG) Log.i(LOG_TAG, "Lost device " + device.getDisplayName());
}
void onDeviceSelected(String callingPackage, String deviceAddress) {
@@ -236,7 +282,8 @@ public class DeviceDiscoveryService extends Service {
}
}
- class DevicesAdapter extends ArrayAdapter<BluetoothDevice> {
+ class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> {
+ //TODO wifi icon
private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
private Drawable icon(int drawableRes) {
@@ -261,8 +308,8 @@ public class DeviceDiscoveryService extends Service {
return view;
}
- private void bind(TextView textView, BluetoothDevice device) {
- textView.setText(getDeviceDisplayName(device));
+ private void bind(TextView textView, DeviceFilterPair device) {
+ textView.setText(device.getDisplayName());
textView.setBackgroundColor(
device.equals(mSelectedDevice)
? Color.GRAY
@@ -285,4 +332,62 @@ public class DeviceDiscoveryService extends Service {
return textView;
}
}
+
+ /**
+ * A pair of device and a filter that matched this device if any.
+ *
+ * @param <T> device type
+ */
+ static class DeviceFilterPair<T extends Parcelable> {
+ public final T device;
+ @Nullable
+ public final DeviceFilter<T> filter;
+
+ private DeviceFilterPair(T device, @Nullable DeviceFilter<T> filter) {
+ this.device = device;
+ this.filter = filter;
+ }
+
+ /**
+ * {@code (device, null)} if the filters list is empty or null
+ * {@code null} if none of the provided filters match the device
+ * {@code (device, filter)} where filter is among the list of filters and matches the device
+ */
+ @Nullable
+ public static <T extends Parcelable> DeviceFilterPair<T> findMatch(
+ T dev, @Nullable List<? extends DeviceFilter<T>> filters) {
+ if (isEmpty(filters)) return new DeviceFilterPair<>(dev, null);
+ final DeviceFilter<T> matchingFilter = ArrayUtils.find(filters, (f) -> f.matches(dev));
+ return matchingFilter != null ? new DeviceFilterPair<>(dev, matchingFilter) : null;
+ }
+
+ public String getDisplayName() {
+ if (filter == null) {
+ Preconditions.checkNotNull(device);
+ if (device instanceof BluetoothDevice) {
+ return getDeviceDisplayNameInternal((BluetoothDevice) device);
+ } else if (device instanceof android.net.wifi.ScanResult) {
+ return getDeviceDisplayNameInternal((android.net.wifi.ScanResult) device);
+ } else if (device instanceof ScanResult) {
+ return getDeviceDisplayNameInternal(((ScanResult) device).getDevice());
+ } else {
+ throw new IllegalArgumentException("Unknown device type: " + device.getClass());
+ }
+ }
+ return filter.getDeviceDisplayName(device);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DeviceFilterPair<?> that = (DeviceFilterPair<?>) o;
+ return Objects.equals(getDeviceMacAddress(device), getDeviceMacAddress(that.device));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getDeviceMacAddress(device));
+ }
+ }
}