Files
packages_apps_Settings/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
Isha Bobra 35e217f91f Show only 1 entry for hearing aid devices without killing the activity.
This CL tries to detect Bluetooth hearing aid devices and tries to
combine the entry of the hearing aids with the same HiSyncIds and
show only 1 entry for each pair in the connected devices list.

This CL also shows 2 battery status in the device details page.

This change shows the combined entry after a user returns to the
settings activity after pressing the back button or somehow
without killing it. It also combines the entries just after pairing.

Test: RunSettingsRoboTests
Bug: 74204427

Change-Id: I47fb0bdd96b1cc972d88a4aef85d0113985d63bb
2018-04-13 22:51:58 +00:00

230 lines
8.7 KiB
Java

/*
* Copyright (C) 2017 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.bluetooth;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemProperties;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.widget.GearPreference;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HeadsetProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* Update the bluetooth devices. It gets bluetooth event from {@link LocalBluetoothManager} using
* {@link BluetoothCallback}. It notifies the upper level whether to add/remove the preference
* through {@link DevicePreferenceCallback}
*
* In {@link BluetoothDeviceUpdater}, it uses {@link BluetoothDeviceFilter.Filter} to detect
* whether the {@link CachedBluetoothDevice} is relevant.
*/
public abstract class BluetoothDeviceUpdater implements BluetoothCallback {
private static final String TAG = "BluetoothDeviceUpdater";
private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
"persist.bluetooth.showdeviceswithoutnames";
protected final LocalBluetoothManager mLocalManager;
protected final DevicePreferenceCallback mDevicePreferenceCallback;
protected final Map<BluetoothDevice, Preference> mPreferenceMap;
protected Context mPrefContext;
private final boolean mShowDeviceWithoutNames;
private DashboardFragment mFragment;
private Preference.OnPreferenceClickListener mDevicePreferenceClickListener = null;
@VisibleForTesting
final GearPreference.OnGearClickListener mDeviceProfilesListener = pref -> {
final CachedBluetoothDevice device =
((BluetoothDevicePreference) pref).getBluetoothDevice();
if (device == null) {
return;
}
final Bundle args = new Bundle();
args.putString(BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS,
device.getDevice().getAddress());
new SubSettingLauncher(mFragment.getContext())
.setDestination(BluetoothDeviceDetailsFragment.class.getName())
.setArguments(args)
.setTitle(R.string.device_details_title)
.setSourceMetricsCategory(mFragment.getMetricsCategory())
.launch();
};
private class PreferenceClickListener implements
Preference.OnPreferenceClickListener {
@Override
public boolean onPreferenceClick(Preference preference) {
final CachedBluetoothDevice device =
((BluetoothDevicePreference) preference).getBluetoothDevice();
Log.i(TAG, "OnPreferenceClickListener: device=" + device);
return device.setActive();
}
}
public BluetoothDeviceUpdater(Context context, DashboardFragment fragment,
DevicePreferenceCallback devicePreferenceCallback) {
this(fragment, devicePreferenceCallback, Utils.getLocalBtManager(context));
}
@VisibleForTesting
BluetoothDeviceUpdater(DashboardFragment fragment,
DevicePreferenceCallback devicePreferenceCallback, LocalBluetoothManager localManager) {
mFragment = fragment;
mDevicePreferenceCallback = devicePreferenceCallback;
mShowDeviceWithoutNames = SystemProperties.getBoolean(
BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
mPreferenceMap = new HashMap<>();
mLocalManager = localManager;
mDevicePreferenceClickListener = new PreferenceClickListener();
}
/**
* Register the bluetooth event callback and update the list
*/
public void registerCallback() {
mLocalManager.setForegroundActivity(mFragment.getContext());
mLocalManager.getEventManager().registerCallback(this);
forceUpdate();
}
/**
* Unregister the bluetooth event callback
*/
public void unregisterCallback() {
mLocalManager.setForegroundActivity(null);
mLocalManager.getEventManager().unregisterCallback(this);
}
/**
* Force to update the list of bluetooth devices
*/
public void forceUpdate() {
Collection<CachedBluetoothDevice> cachedDevices =
mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
for (CachedBluetoothDevice cachedBluetoothDevice : cachedDevices) {
update(cachedBluetoothDevice);
}
}
@Override
public void onBluetoothStateChanged(int bluetoothState) {
forceUpdate();
}
@Override
public void onScanningStateChanged(boolean started) {}
@Override
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
update(cachedDevice);
}
@Override
public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
// Used to combine the hearing aid entries just after pairing. Once both the hearing aids
// get connected and their hiSyncId gets populated, this gets called for one of the
// 2 hearing aids so that only one entry in the connected devices list will be seen.
removePreference(cachedDevice);
}
@Override
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
update(cachedDevice);
}
@Override
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {}
@Override
public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
}
@Override
public void onAudioModeChanged() {
}
/**
* Set the context to generate the {@link Preference}, so it could get the correct theme.
*/
public void setPrefContext(Context context) {
mPrefContext = context;
}
/**
* Return {@code true} if {@code cachedBluetoothDevice} matches this
* {@link BluetoothDeviceUpdater} and should stay in the list, otherwise return {@code false}
*/
public abstract boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice);
/**
* Update whether to show {@cde cachedBluetoothDevice} in the list.
*/
protected void update(CachedBluetoothDevice cachedBluetoothDevice) {
if (isFilterMatched(cachedBluetoothDevice)) {
// Add the preference if it is new one
addPreference(cachedBluetoothDevice);
} else {
removePreference(cachedBluetoothDevice);
}
}
/**
* Add the {@link Preference} that represents the {@code cachedDevice}
*/
protected void addPreference(CachedBluetoothDevice cachedDevice) {
final BluetoothDevice device = cachedDevice.getDevice();
if (!mPreferenceMap.containsKey(device)) {
BluetoothDevicePreference btPreference =
new BluetoothDevicePreference(mPrefContext, cachedDevice,
mShowDeviceWithoutNames);
btPreference.setOnGearClickListener(mDeviceProfilesListener);
btPreference.setOnPreferenceClickListener(mDevicePreferenceClickListener);
mPreferenceMap.put(device, btPreference);
mDevicePreferenceCallback.onDeviceAdded(btPreference);
}
}
/**
* Remove the {@link Preference} that represents the {@code cachedDevice}
*/
protected void removePreference(CachedBluetoothDevice cachedDevice) {
final BluetoothDevice device = cachedDevice.getDevice();
if (mPreferenceMap.containsKey(device)) {
mDevicePreferenceCallback.onDeviceRemoved(mPreferenceMap.get(device));
mPreferenceMap.remove(device);
}
}
}