[Ambient Volume] Show value with local data
Flag: com.android.settingslib.flags.hearing_devices_ambient_volume_control Bug: 357878944 Test: atest BluetoothDetailsAmbientVolumePreferenceControllerTest Change-Id: I3dad0f5424b44fee6d049fd778c4f8f71db0b58e
This commit is contained in:
@@ -16,11 +16,16 @@
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import static android.bluetooth.BluetoothDevice.BOND_BONDED;
|
||||
|
||||
import static com.android.settings.bluetooth.AmbientVolumePreference.SIDE_UNIFIED;
|
||||
import static com.android.settings.bluetooth.AmbientVolumePreference.VALID_SIDES;
|
||||
import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.KEY_HEARING_DEVICE_GROUP;
|
||||
import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.ORDER_AMBIENT_VOLUME;
|
||||
import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_INVALID;
|
||||
import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_LEFT;
|
||||
import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_RIGHT;
|
||||
import static com.android.settingslib.bluetooth.HearingDeviceLocalDataManager.Data.INVALID_VOLUME;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
@@ -29,15 +34,21 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.widget.SeekBarPreference;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.HearingDeviceLocalDataManager;
|
||||
import com.android.settingslib.bluetooth.HearingDeviceLocalDataManager.Data;
|
||||
import com.android.settingslib.bluetooth.VolumeControlProfile;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
@@ -47,7 +58,8 @@ import java.util.Set;
|
||||
|
||||
/** A {@link BluetoothDetailsController} that manages ambient volume control preferences. */
|
||||
public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
BluetoothDetailsController implements Preference.OnPreferenceChangeListener {
|
||||
BluetoothDetailsController implements Preference.OnPreferenceChangeListener,
|
||||
HearingDeviceLocalDataManager.OnDeviceLocalDataChangeListener, OnStart, OnStop {
|
||||
|
||||
private static final boolean DEBUG = true;
|
||||
private static final String TAG = "AmbientPrefController";
|
||||
@@ -60,6 +72,7 @@ public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
private final Set<CachedBluetoothDevice> mCachedDevices = new ArraySet<>();
|
||||
private final BiMap<Integer, BluetoothDevice> mSideToDeviceMap = HashBiMap.create();
|
||||
private final BiMap<Integer, SeekBarPreference> mSideToSliderMap = HashBiMap.create();
|
||||
private final HearingDeviceLocalDataManager mLocalDataManager;
|
||||
|
||||
@Nullable
|
||||
private PreferenceCategory mDeviceControls;
|
||||
@@ -71,6 +84,19 @@ public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
@NonNull CachedBluetoothDevice device,
|
||||
@NonNull Lifecycle lifecycle) {
|
||||
super(context, fragment, device, lifecycle);
|
||||
mLocalDataManager = new HearingDeviceLocalDataManager(context);
|
||||
mLocalDataManager.setOnDeviceLocalDataChangeListener(this,
|
||||
ThreadUtils.getBackgroundExecutor());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
BluetoothDetailsAmbientVolumePreferenceController(@NonNull Context context,
|
||||
@NonNull PreferenceFragmentCompat fragment,
|
||||
@NonNull CachedBluetoothDevice device,
|
||||
@NonNull Lifecycle lifecycle,
|
||||
@NonNull HearingDeviceLocalDataManager localSettings) {
|
||||
super(context, fragment, device, lifecycle);
|
||||
mLocalDataManager = localSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,13 +108,33 @@ public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
loadDevices();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
mLocalDataManager.start();
|
||||
mCachedDevices.forEach(device -> {
|
||||
device.registerCallback(ThreadUtils.getBackgroundExecutor(), this);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
mLocalDataManager.stop();
|
||||
mCachedDevices.forEach(device -> {
|
||||
device.unregisterCallback(this);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refresh() {
|
||||
if (!isAvailable()) {
|
||||
return;
|
||||
}
|
||||
// TODO: load data from remote
|
||||
refreshControlUi();
|
||||
loadLocalDataToUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,6 +157,8 @@ public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onPreferenceChange: side=" + side + ", value=" + value);
|
||||
}
|
||||
setVolumeIfValid(side, value);
|
||||
|
||||
if (side == SIDE_UNIFIED) {
|
||||
// TODO: set the value on the devices
|
||||
} else {
|
||||
@@ -139,15 +187,31 @@ public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceLocalDataChange(@NonNull String address, @Nullable Data data) {
|
||||
if (data == null) {
|
||||
// The local data is removed because the device is unpaired, do nothing
|
||||
return;
|
||||
}
|
||||
for (BluetoothDevice device : mSideToDeviceMap.values()) {
|
||||
if (device.getAnonymizedAddress().equals(address)) {
|
||||
mContext.getMainExecutor().execute(() -> loadLocalDataToUi(device));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDevices() {
|
||||
mSideToDeviceMap.clear();
|
||||
mCachedDevices.clear();
|
||||
if (VALID_SIDES.contains(mCachedDevice.getDeviceSide())) {
|
||||
if (VALID_SIDES.contains(mCachedDevice.getDeviceSide())
|
||||
&& mCachedDevice.getBondState() == BOND_BONDED) {
|
||||
mSideToDeviceMap.put(mCachedDevice.getDeviceSide(), mCachedDevice.getDevice());
|
||||
mCachedDevices.add(mCachedDevice);
|
||||
}
|
||||
for (CachedBluetoothDevice memberDevice : mCachedDevice.getMemberDevice()) {
|
||||
if (VALID_SIDES.contains(memberDevice.getDeviceSide())) {
|
||||
if (VALID_SIDES.contains(memberDevice.getDeviceSide())
|
||||
&& memberDevice.getBondState() == BOND_BONDED) {
|
||||
mSideToDeviceMap.put(memberDevice.getDeviceSide(), memberDevice.getDevice());
|
||||
mCachedDevices.add(memberDevice);
|
||||
}
|
||||
@@ -164,9 +228,16 @@ public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
if (mPreference != null || mDeviceControls == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPreference = new AmbientVolumePreference(mDeviceControls.getContext());
|
||||
mPreference.setKey(KEY_AMBIENT_VOLUME);
|
||||
mPreference.setOrder(ORDER_AMBIENT_VOLUME);
|
||||
mPreference.setOnIconClickListener(() -> {
|
||||
mSideToDeviceMap.forEach((s, d) -> {
|
||||
// Update new value to local data
|
||||
mLocalDataManager.updateAmbientControlExpanded(d, isControlExpanded());
|
||||
});
|
||||
});
|
||||
if (mDeviceControls.findPreference(mPreference.getKey()) == null) {
|
||||
mDeviceControls.addPreference(mPreference);
|
||||
}
|
||||
@@ -186,6 +257,12 @@ public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
preference.setKey(KEY_AMBIENT_VOLUME_SLIDER + "_" + side);
|
||||
preference.setOrder(order);
|
||||
preference.setOnPreferenceChangeListener(this);
|
||||
if (side == SIDE_LEFT) {
|
||||
preference.setTitle(mContext.getString(R.string.bluetooth_ambient_volume_control_left));
|
||||
} else if (side == SIDE_RIGHT) {
|
||||
preference.setTitle(
|
||||
mContext.getString(R.string.bluetooth_ambient_volume_control_right));
|
||||
}
|
||||
mSideToSliderMap.put(side, preference);
|
||||
}
|
||||
|
||||
@@ -195,4 +272,50 @@ public class BluetoothDetailsAmbientVolumePreferenceController extends
|
||||
mPreference.updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the volume to the corresponding control slider. */
|
||||
private void setVolumeIfValid(int side, int volume) {
|
||||
if (volume == INVALID_VOLUME) {
|
||||
return;
|
||||
}
|
||||
if (mPreference != null) {
|
||||
mPreference.setSliderValue(side, volume);
|
||||
}
|
||||
// Update new value to local data
|
||||
if (side == SIDE_UNIFIED) {
|
||||
mSideToDeviceMap.forEach((s, d) -> mLocalDataManager.updateGroupAmbient(d, volume));
|
||||
} else {
|
||||
mLocalDataManager.updateAmbient(mSideToDeviceMap.get(side), volume);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadLocalDataToUi() {
|
||||
mSideToDeviceMap.forEach((s, d) -> loadLocalDataToUi(d));
|
||||
}
|
||||
|
||||
private void loadLocalDataToUi(BluetoothDevice device) {
|
||||
final Data data = mLocalDataManager.get(device);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "loadLocalDataToUi, data=" + data + ", device=" + device);
|
||||
}
|
||||
final int side = mSideToDeviceMap.inverse().getOrDefault(device, SIDE_INVALID);
|
||||
setVolumeIfValid(side, data.ambient());
|
||||
setVolumeIfValid(SIDE_UNIFIED, data.groupAmbient());
|
||||
setControlExpanded(data.ambientControlExpanded());
|
||||
refreshControlUi();
|
||||
}
|
||||
|
||||
private boolean isControlExpanded() {
|
||||
return mPreference != null && mPreference.isExpanded();
|
||||
}
|
||||
|
||||
private void setControlExpanded(boolean expanded) {
|
||||
if (mPreference != null && mPreference.isExpanded() != expanded) {
|
||||
mPreference.setExpanded(expanded);
|
||||
}
|
||||
mSideToDeviceMap.forEach((s, d) -> {
|
||||
// Update new value to local data
|
||||
mLocalDataManager.updateAmbientControlExpanded(d, expanded);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user