[Pair hearing devices] Add pair hearing device functionality
* Add setFilter(List<ScanFilter>) in DeviceListPreferenceFragment to enable BluetoothLeScanner Bug: 237625815 Test: make RunSettingsRoboTests ROBOTEST_FILTER=DeviceListPreferenceFragmentTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=HearingDevicePairingDetailTest Change-Id: I13495cad7260789845fad9a7e77e96b692a5cbd0
This commit is contained in:
@@ -4557,7 +4557,7 @@
|
|||||||
<!-- Title for the pair hearing device page. [CHAR LIMIT=25] -->
|
<!-- Title for the pair hearing device page. [CHAR LIMIT=25] -->
|
||||||
<string name="accessibility_hearing_device_pairing_page_title">Pair hearing device</string>
|
<string name="accessibility_hearing_device_pairing_page_title">Pair hearing device</string>
|
||||||
<!-- Title for the preference category containing the list of the available hearing during and after bluetooth scanning devices. [CHAR LIMIT=30] -->
|
<!-- Title for the preference category containing the list of the available hearing during and after bluetooth scanning devices. [CHAR LIMIT=30] -->
|
||||||
<string name="accessibility_found_hearing_devices">Available devices</string>
|
<string name="accessibility_found_hearing_devices">Available hearing devices</string>
|
||||||
<!-- Title for the preference category containing the all bluetooth devices during and after bluetooth scanning devices. Used when people can not find their hearing device in hearing device pairing list. [CHAR LIMIT=45] -->
|
<!-- Title for the preference category containing the all bluetooth devices during and after bluetooth scanning devices. Used when people can not find their hearing device in hearing device pairing list. [CHAR LIMIT=45] -->
|
||||||
<string name="accessibility_found_all_devices">Don\u2019t see your hearing device?</string>
|
<string name="accessibility_found_all_devices">Don\u2019t see your hearing device?</string>
|
||||||
<!-- Title for listing all bluetooth devices preference in the accessibility page. [CHAR LIMIT=40] -->
|
<!-- Title for listing all bluetooth devices preference in the accessibility page. [CHAR LIMIT=40] -->
|
||||||
|
@@ -29,8 +29,10 @@
|
|||||||
android:title="@string/bluetooth_pairing_pref_title"
|
android:title="@string/bluetooth_pairing_pref_title"
|
||||||
android:icon="@drawable/ic_add_24dp"
|
android:icon="@drawable/ic_add_24dp"
|
||||||
android:summary="@string/connected_device_add_device_summary"
|
android:summary="@string/connected_device_add_device_summary"
|
||||||
|
android:fragment="com.android.settings.accessibility.HearingDevicePairingDetail"
|
||||||
settings:userRestriction="no_config_bluetooth"
|
settings:userRestriction="no_config_bluetooth"
|
||||||
settings:useAdminDisabledSummary="true" />
|
settings:useAdminDisabledSummary="true"
|
||||||
|
settings:controller="com.android.settings.connecteddevice.AddDevicePreferenceController"/>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="previously_connected_hearing_devices"
|
android:key="previously_connected_hearing_devices"
|
||||||
|
42
res/xml/hearing_device_pairing_detail.xml
Normal file
42
res/xml/hearing_device_pairing_detail.xml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2023 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:title="@string/bluetooth_pairing_pref_title">
|
||||||
|
|
||||||
|
<com.android.settings.bluetooth.BluetoothProgressCategory
|
||||||
|
android:key="available_hearing_devices"
|
||||||
|
android:title="@string/accessibility_found_hearing_devices" />
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="device_control_category"
|
||||||
|
android:title="@string/accessibility_found_all_devices">
|
||||||
|
<com.android.settingslib.RestrictedPreference
|
||||||
|
android:key="add_bt_devices"
|
||||||
|
android:title="@string/accessibility_list_all_devices_title"
|
||||||
|
android:fragment="com.android.settings.bluetooth.BluetoothPairingDetail"
|
||||||
|
settings:userRestriction="no_config_bluetooth"
|
||||||
|
settings:useAdminDisabledSummary="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<com.android.settings.accessibility.AccessibilityFooterPreference
|
||||||
|
android:key="hearing_device_footer"
|
||||||
|
android:title="@string/accessibility_hearing_device_footer_summary"
|
||||||
|
android:selectable="false"
|
||||||
|
settings:searchable="false" />
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothUuid;
|
||||||
|
import android.bluetooth.le.ScanFilter;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.bluetooth.BluetoothDevicePairingDetailBase;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HearingDevicePairingDetail is a page to scan hearing devices. This page shows scanning icons and
|
||||||
|
* pairing them.
|
||||||
|
*/
|
||||||
|
public class HearingDevicePairingDetail extends BluetoothDevicePairingDetailBase {
|
||||||
|
|
||||||
|
private static final String TAG = "HearingDevicePairingDetail";
|
||||||
|
@VisibleForTesting
|
||||||
|
static final String KEY_AVAILABLE_HEARING_DEVICES = "available_hearing_devices";
|
||||||
|
|
||||||
|
public HearingDevicePairingDetail() {
|
||||||
|
super();
|
||||||
|
final ScanFilter filter = new ScanFilter.Builder()
|
||||||
|
.setServiceData(BluetoothUuid.HEARING_AID, new byte[]{0}, new byte[]{0})
|
||||||
|
.build();
|
||||||
|
setFilter(Collections.singletonList(filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
mAvailableDevicesCategory.setProgress(mBluetoothAdapter.isEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
|
||||||
|
super.onDeviceBondStateChanged(cachedDevice, bondState);
|
||||||
|
|
||||||
|
mAvailableDevicesCategory.setProgress(bondState == BluetoothDevice.BOND_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMetricsCategory() {
|
||||||
|
// TODO(b/262839191): To be updated settings_enums.proto
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getPreferenceScreenResId() {
|
||||||
|
return R.xml.hearing_device_pairing_detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getLogTag() {
|
||||||
|
return TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDeviceListKey() {
|
||||||
|
return KEY_AVAILABLE_HEARING_DEVICES;
|
||||||
|
}
|
||||||
|
}
|
@@ -18,6 +18,11 @@ package com.android.settings.bluetooth;
|
|||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.le.BluetoothLeScanner;
|
||||||
|
import android.bluetooth.le.ScanCallback;
|
||||||
|
import android.bluetooth.le.ScanFilter;
|
||||||
|
import android.bluetooth.le.ScanResult;
|
||||||
|
import android.bluetooth.le.ScanSettings;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.text.BidiFormatter;
|
import android.text.BidiFormatter;
|
||||||
@@ -33,6 +38,7 @@ import com.android.settings.dashboard.RestrictedDashboardFragment;
|
|||||||
import com.android.settingslib.bluetooth.BluetoothCallback;
|
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||||
import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
|
import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -59,37 +65,51 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
"persist.bluetooth.showdeviceswithoutnames";
|
"persist.bluetooth.showdeviceswithoutnames";
|
||||||
|
|
||||||
private BluetoothDeviceFilter.Filter mFilter;
|
private BluetoothDeviceFilter.Filter mFilter;
|
||||||
|
private List<ScanFilter> mLeScanFilters;
|
||||||
|
private ScanCallback mScanCallback;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean mScanEnabled;
|
protected boolean mScanEnabled;
|
||||||
|
|
||||||
BluetoothDevice mSelectedDevice;
|
protected BluetoothDevice mSelectedDevice;
|
||||||
|
|
||||||
BluetoothAdapter mBluetoothAdapter;
|
protected BluetoothAdapter mBluetoothAdapter;
|
||||||
LocalBluetoothManager mLocalManager;
|
protected LocalBluetoothManager mLocalManager;
|
||||||
|
protected CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
PreferenceGroup mDeviceListGroup;
|
protected PreferenceGroup mDeviceListGroup;
|
||||||
|
|
||||||
final HashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
|
protected final HashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
|
||||||
new HashMap<>();
|
new HashMap<>();
|
||||||
final List<BluetoothDevice> mSelectedList = new ArrayList<>();
|
protected final List<BluetoothDevice> mSelectedList = new ArrayList<>();
|
||||||
|
|
||||||
boolean mShowDevicesWithoutNames;
|
protected boolean mShowDevicesWithoutNames;
|
||||||
|
|
||||||
DeviceListPreferenceFragment(String restrictedKey) {
|
public DeviceListPreferenceFragment(String restrictedKey) {
|
||||||
super(restrictedKey);
|
super(restrictedKey);
|
||||||
mFilter = BluetoothDeviceFilter.ALL_FILTER;
|
mFilter = BluetoothDeviceFilter.ALL_FILTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
final void setFilter(BluetoothDeviceFilter.Filter filter) {
|
protected final void setFilter(BluetoothDeviceFilter.Filter filter) {
|
||||||
mFilter = filter;
|
mFilter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
final void setFilter(int filterType) {
|
protected final void setFilter(int filterType) {
|
||||||
mFilter = BluetoothDeviceFilter.getFilter(filterType);
|
mFilter = BluetoothDeviceFilter.getFilter(filterType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bluetooth device scanning filter with {@link ScanFilter}s. It will change to start
|
||||||
|
* {@link BluetoothLeScanner} which will scan BLE device only.
|
||||||
|
*
|
||||||
|
* @param leScanFilters list of settings to filter scan result
|
||||||
|
*/
|
||||||
|
protected void setFilter(List<ScanFilter> leScanFilters) {
|
||||||
|
mFilter = null;
|
||||||
|
mLeScanFilters = leScanFilters;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -100,6 +120,7 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
mCachedDeviceManager = mLocalManager.getCachedDeviceManager();
|
||||||
mShowDevicesWithoutNames = SystemProperties.getBoolean(
|
mShowDevicesWithoutNames = SystemProperties.getBoolean(
|
||||||
BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
|
BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
|
||||||
|
|
||||||
@@ -109,7 +130,7 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** find and update preference that already existed in preference screen */
|
/** find and update preference that already existed in preference screen */
|
||||||
abstract void initPreferencesFromPreferenceScreen();
|
protected abstract void initPreferencesFromPreferenceScreen();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
@@ -139,7 +160,7 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
|
|
||||||
void addCachedDevices() {
|
void addCachedDevices() {
|
||||||
Collection<CachedBluetoothDevice> cachedDevices =
|
Collection<CachedBluetoothDevice> cachedDevices =
|
||||||
mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
|
mCachedDeviceManager.getCachedDevicesCopy();
|
||||||
for (CachedBluetoothDevice cachedDevice : cachedDevices) {
|
for (CachedBluetoothDevice cachedDevice : cachedDevices) {
|
||||||
onDeviceAdded(cachedDevice);
|
onDeviceAdded(cachedDevice);
|
||||||
}
|
}
|
||||||
@@ -164,7 +185,7 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
return super.onPreferenceTreeClick(preference);
|
return super.onPreferenceTreeClick(preference);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
|
protected void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
|
||||||
btPreference.onClicked();
|
btPreference.onClicked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +198,8 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
// Prevent updates while the list shows one of the state messages
|
// Prevent updates while the list shows one of the state messages
|
||||||
if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) return;
|
if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) return;
|
||||||
|
|
||||||
if (mFilter.matches(cachedDevice.getDevice())) {
|
if (mLeScanFilters != null
|
||||||
|
|| (mFilter != null && mFilter.matches(cachedDevice.getDevice()))) {
|
||||||
createDevicePreference(cachedDevice);
|
createDevicePreference(cachedDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,7 +249,7 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void enableScanning() {
|
protected void enableScanning() {
|
||||||
// BluetoothAdapter already handles repeated scan requests
|
// BluetoothAdapter already handles repeated scan requests
|
||||||
if (!mScanEnabled) {
|
if (!mScanEnabled) {
|
||||||
startScanning();
|
startScanning();
|
||||||
@@ -236,7 +258,7 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void disableScanning() {
|
protected void disableScanning() {
|
||||||
if (mScanEnabled) {
|
if (mScanEnabled) {
|
||||||
stopScanning();
|
stopScanning();
|
||||||
mScanEnabled = false;
|
mScanEnabled = false;
|
||||||
@@ -250,31 +272,6 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add bluetooth device preferences to {@code preferenceGroup} which satisfy the {@code filter}
|
|
||||||
*
|
|
||||||
* This method will also (1) set the title for {@code preferenceGroup} and (2) change the
|
|
||||||
* default preferenceGroup and filter
|
|
||||||
* @param preferenceGroup
|
|
||||||
* @param titleId
|
|
||||||
* @param filter
|
|
||||||
* @param addCachedDevices
|
|
||||||
*/
|
|
||||||
public void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
|
|
||||||
BluetoothDeviceFilter.Filter filter, boolean addCachedDevices) {
|
|
||||||
cacheRemoveAllPrefs(preferenceGroup);
|
|
||||||
preferenceGroup.setTitle(titleId);
|
|
||||||
mDeviceListGroup = preferenceGroup;
|
|
||||||
if (addCachedDevices) {
|
|
||||||
// Don't show bonded devices when screen turned back on
|
|
||||||
setFilter(BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER);
|
|
||||||
addCachedDevices();
|
|
||||||
}
|
|
||||||
setFilter(filter);
|
|
||||||
preferenceGroup.setEnabled(true);
|
|
||||||
removeCachedPrefs(preferenceGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the key of the {@link PreferenceGroup} that contains the bluetooth devices
|
* Return the key of the {@link PreferenceGroup} that contains the bluetooth devices
|
||||||
*/
|
*/
|
||||||
@@ -284,15 +281,65 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
return mShowDevicesWithoutNames;
|
return mShowDevicesWithoutNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
void startScanning() {
|
void startScanning() {
|
||||||
|
if (mFilter != null) {
|
||||||
|
startClassicScanning();
|
||||||
|
} else if (mLeScanFilters != null) {
|
||||||
|
startLeScanning();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void stopScanning() {
|
||||||
|
if (mFilter != null) {
|
||||||
|
stopClassicScanning();
|
||||||
|
} else if (mLeScanFilters != null) {
|
||||||
|
stopLeScanning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startClassicScanning() {
|
||||||
if (!mBluetoothAdapter.isDiscovering()) {
|
if (!mBluetoothAdapter.isDiscovering()) {
|
||||||
mBluetoothAdapter.startDiscovery();
|
mBluetoothAdapter.startDiscovery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopScanning() {
|
private void stopClassicScanning() {
|
||||||
if (mBluetoothAdapter.isDiscovering()) {
|
if (mBluetoothAdapter.isDiscovering()) {
|
||||||
mBluetoothAdapter.cancelDiscovery();
|
mBluetoothAdapter.cancelDiscovery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startLeScanning() {
|
||||||
|
final BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
|
||||||
|
final ScanSettings settings = new ScanSettings.Builder()
|
||||||
|
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||||
|
.build();
|
||||||
|
mScanCallback = new ScanCallback() {
|
||||||
|
@Override
|
||||||
|
public void onScanResult(int callbackType, ScanResult result) {
|
||||||
|
final BluetoothDevice device = result.getDevice();
|
||||||
|
CachedBluetoothDevice cachedDevice = mCachedDeviceManager.findDevice(device);
|
||||||
|
if (cachedDevice == null) {
|
||||||
|
cachedDevice = mCachedDeviceManager.addDevice(device);
|
||||||
|
}
|
||||||
|
onDeviceAdded(cachedDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScanFailed(int errorCode) {
|
||||||
|
Log.w(TAG, "BLE Scan failed with error code " + errorCode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
scanner.startScan(mLeScanFilters, settings, mScanCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopLeScanning() {
|
||||||
|
final BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
|
||||||
|
if (scanner != null) {
|
||||||
|
scanner.stopScan(mScanCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,8 +27,8 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.util.Log;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void initPreferencesFromPreferenceScreen() {
|
public void initPreferencesFromPreferenceScreen() {
|
||||||
Intent intent = getActivity().getIntent();
|
Intent intent = getActivity().getIntent();
|
||||||
mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
|
mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
|
||||||
setFilter(intent.getIntExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
|
setFilter(intent.getIntExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
|
||||||
@@ -136,7 +136,7 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
|
public void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
|
||||||
disableScanning();
|
disableScanning();
|
||||||
LocalBluetoothPreferences.persistSelectedDeviceInPicker(
|
LocalBluetoothPreferences.persistSelectedDeviceInPicker(
|
||||||
getActivity(), mSelectedDevice.getAddress());
|
getActivity(), mSelectedDevice.getAddress());
|
||||||
|
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import com.android.settings.bluetooth.BluetoothProgressCategory;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadow.api.Shadow;
|
||||||
|
|
||||||
|
/** Tests for {@link HearingDevicePairingDetail}. */
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(shadows = {ShadowBluetoothAdapter.class})
|
||||||
|
public class HearingDevicePairingDetailTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||||
|
|
||||||
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||||
|
private BluetoothProgressCategory mProgressCategory;
|
||||||
|
private TestHearingDevicePairingDetail mFragment;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
final BluetoothAdapter bluetoothAdapter = spy(BluetoothAdapter.getDefaultAdapter());
|
||||||
|
final ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
|
||||||
|
BluetoothAdapter.getDefaultAdapter());
|
||||||
|
shadowBluetoothAdapter.setEnabled(true);
|
||||||
|
|
||||||
|
mProgressCategory = spy(new BluetoothProgressCategory(mContext));
|
||||||
|
mFragment = spy(new TestHearingDevicePairingDetail());
|
||||||
|
when(mFragment.getContext()).thenReturn(mContext);
|
||||||
|
when(mFragment.findPreference(
|
||||||
|
HearingDevicePairingDetail.KEY_AVAILABLE_HEARING_DEVICES)).thenReturn(
|
||||||
|
mProgressCategory);
|
||||||
|
mFragment.setBluetoothAdapter(bluetoothAdapter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDeviceListKey_expectedKey() {
|
||||||
|
assertThat(mFragment.getDeviceListKey()).isEqualTo(
|
||||||
|
HearingDevicePairingDetail.KEY_AVAILABLE_HEARING_DEVICES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onDeviceBondStateChanged_bondNone_setProgressFalse() {
|
||||||
|
mFragment.initPreferencesFromPreferenceScreen();
|
||||||
|
|
||||||
|
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE);
|
||||||
|
|
||||||
|
verify(mProgressCategory).setProgress(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onDeviceBondStateChanged_bonding_setProgressTrue() {
|
||||||
|
mFragment.initPreferencesFromPreferenceScreen();
|
||||||
|
|
||||||
|
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
|
||||||
|
|
||||||
|
verify(mProgressCategory).setProgress(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestHearingDevicePairingDetail extends HearingDevicePairingDetail {
|
||||||
|
TestHearingDevicePairingDetail() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBluetoothAdapter(BluetoothAdapter bluetoothAdapter) {
|
||||||
|
this.mBluetoothAdapter = bluetoothAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enableScanning() {
|
||||||
|
super.enableScanning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -26,6 +26,11 @@ import static org.mockito.Mockito.times;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothUuid;
|
||||||
|
import android.bluetooth.le.BluetoothLeScanner;
|
||||||
|
import android.bluetooth.le.ScanCallback;
|
||||||
|
import android.bluetooth.le.ScanFilter;
|
||||||
|
import android.bluetooth.le.ScanSettings;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
|
||||||
@@ -45,6 +50,7 @@ import org.robolectric.RobolectricTestRunner;
|
|||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@@ -57,10 +63,14 @@ public class DeviceListPreferenceFragmentTest {
|
|||||||
private Resources mResource;
|
private Resources mResource;
|
||||||
@Mock
|
@Mock
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
@Mock
|
||||||
|
private BluetoothLeScanner mBluetoothLeScanner;
|
||||||
|
|
||||||
private TestFragment mFragment;
|
private TestFragment mFragment;
|
||||||
private Preference mMyDevicePreference;
|
private Preference mMyDevicePreference;
|
||||||
|
|
||||||
|
|
||||||
|
private BluetoothAdapter mBluetoothAdapter;
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
@@ -68,7 +78,8 @@ public class DeviceListPreferenceFragmentTest {
|
|||||||
mFragment = spy(new TestFragment());
|
mFragment = spy(new TestFragment());
|
||||||
doReturn(mContext).when(mFragment).getContext();
|
doReturn(mContext).when(mFragment).getContext();
|
||||||
doReturn(mResource).when(mFragment).getResources();
|
doReturn(mResource).when(mFragment).getResources();
|
||||||
mFragment.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
mBluetoothAdapter = spy(BluetoothAdapter.getDefaultAdapter());
|
||||||
|
mFragment.mBluetoothAdapter = mBluetoothAdapter;
|
||||||
|
|
||||||
mMyDevicePreference = new Preference(RuntimeEnvironment.application);
|
mMyDevicePreference = new Preference(RuntimeEnvironment.application);
|
||||||
}
|
}
|
||||||
@@ -169,6 +180,20 @@ public class DeviceListPreferenceFragmentTest {
|
|||||||
verify(mFragment, times(1)).startScanning();
|
verify(mFragment, times(1)).startScanning();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void startScanning_setLeScanFilter_shouldStartLeScan() {
|
||||||
|
final ScanFilter leScanFilter = new ScanFilter.Builder()
|
||||||
|
.setServiceData(BluetoothUuid.HEARING_AID, new byte[]{0}, new byte[]{0})
|
||||||
|
.build();
|
||||||
|
doReturn(mBluetoothLeScanner).when(mBluetoothAdapter).getBluetoothLeScanner();
|
||||||
|
|
||||||
|
mFragment.setFilter(Collections.singletonList(leScanFilter));
|
||||||
|
mFragment.startScanning();
|
||||||
|
|
||||||
|
verify(mBluetoothLeScanner).startScan(eq(Collections.singletonList(leScanFilter)),
|
||||||
|
any(ScanSettings.class), any(ScanCallback.class));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment to test since {@code DeviceListPreferenceFragment} is abstract
|
* Fragment to test since {@code DeviceListPreferenceFragment} is abstract
|
||||||
*/
|
*/
|
||||||
@@ -187,7 +212,7 @@ public class DeviceListPreferenceFragmentTest {
|
|||||||
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {}
|
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void initPreferencesFromPreferenceScreen() {}
|
protected void initPreferencesFromPreferenceScreen() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDeviceListKey() {
|
public String getDeviceListKey() {
|
||||||
|
Reference in New Issue
Block a user