Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f6efc94 authored by Yiyi Shen's avatar Yiyi Shen Committed by Android (Google) Code Review
Browse files

Merge "[Audiosharing] Fix volume control." into main

parents b940da0f afbd9d98
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -102,7 +102,9 @@ public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdat
                        }
                    };
            AudioSharingDeviceVolumePreference vPreference =
                    new AudioSharingDeviceVolumePreference(mPrefContext, cachedDevice, listener);
                    new AudioSharingDeviceVolumePreference(mPrefContext, cachedDevice);
            vPreference.initialize();
            vPreference.setOnSeekBarChangeListener(listener);
            vPreference.setKey(getPreferenceKey());
            vPreference.setIcon(com.android.settingslib.R.drawable.ic_bt_untethered_earbuds);
            vPreference.setTitle(cachedDevice.getName());
+49 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothVolumeControl;
import android.content.Context;
import android.media.AudioManager;
import android.util.Log;

import androidx.annotation.NonNull;
@@ -36,10 +37,12 @@ import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.VolumeControlProfile;
import com.android.settingslib.utils.ThreadUtils;

import java.util.HashMap;
import java.util.Map;
@@ -48,6 +51,7 @@ import java.util.concurrent.Executors;

public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePreferenceController
        implements DevicePreferenceCallback {
    private static final boolean DEBUG = BluetoothUtils.D;

    private static final String TAG = "AudioSharingDeviceVolumeGroupController";
    private static final String KEY = "audio_sharing_device_volume_group";
@@ -189,6 +193,17 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
        mBluetoothDeviceUpdater.unregisterCallback();
    }

    @Override
    public void onDestroy(@NonNull LifecycleOwner owner) {
        for (var entry : mCallbackMap.entrySet()) {
            if (DEBUG) {
                Log.d(TAG, "onDestroy: unregister callback for " + entry.getKey());
            }
            mVolumeControl.unregisterCallback(entry.getValue());
        }
        mCallbackMap.clear();
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
@@ -217,6 +232,9 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
            BluetoothVolumeControl.Callback callback =
                    buildVcCallback((AudioSharingDeviceVolumePreference) preference);
            mCallbackMap.put(preference, callback);
            if (DEBUG) {
                Log.d(TAG, "onDeviceAdded: register callback for " + preference);
            }
            mVolumeControl.registerCallback(mExecutor, callback);
        }
    }
@@ -228,6 +246,9 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
            mPreferenceGroup.setVisible(false);
        }
        if (mVolumeControl != null && mCallbackMap.containsKey(preference)) {
            if (DEBUG) {
                Log.d(TAG, "onDeviceRemoved: unregister callback for " + preference);
            }
            mVolumeControl.unregisterCallback(mCallbackMap.get(preference));
            mCallbackMap.remove(preference);
        }
@@ -266,16 +287,41 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
            @Override
            public void onDeviceVolumeChanged(
                    @android.annotation.NonNull BluetoothDevice device,
                    @IntRange(from = 0, to = 255) int volume) {
                Log.d(TAG, "onDeviceVolumeChanged changed " + device.getAnonymizedAddress());
                    @IntRange(from = -255, to = 255) int volume) {
                CachedBluetoothDevice cachedDevice =
                        mLocalBtManager.getCachedDeviceManager().findDevice(device);
                if (cachedDevice == null) return;
                if (preference.getCachedDevice() != null
                        && preference.getCachedDevice().getGroupId() == cachedDevice.getGroupId()) {
                    preference.setProgress(volume);
                    // If the callback return invalid volume, try to get the volume from
                    // AudioManager.STREAM_MUSIC
                    int finalVolume = getAudioVolumeIfNeeded(volume);
                    Log.d(
                            TAG,
                            "onDeviceVolumeChanged: set volume to "
                                    + finalVolume
                                    + " for "
                                    + device.getAnonymizedAddress());
                    ThreadUtils.postOnMainThread(
                            () -> {
                                preference.setProgress(finalVolume);
                            });
                }
            }
        };
    }

    private int getAudioVolumeIfNeeded(int volume) {
        if (volume >= 0) return volume;
        try {
            AudioManager audioManager = mContext.getSystemService(AudioManager.class);
            int max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            int min = audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
            return Math.round(
                    audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) * 255f / (max - min));
        } catch (RuntimeException e) {
            Log.e(TAG, "Fail to fetch current music stream volume, error = " + e);
            return volume;
        }
    }
}
+8 −25
Original line number Diff line number Diff line
@@ -21,33 +21,23 @@ import android.widget.SeekBar;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceViewHolder;

import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;

public class AudioSharingDeviceVolumePreference extends SeekBarPreference {
    private static final String TAG = "AudioSharingDeviceVolumePreference";
    public static final int MIN_VOLUME = 0;
    public static final int MAX_VOLUME = 255;

    protected SeekBar mSeekBar;
    private final LocalBluetoothManager mLocalBtManager;
    private final CachedBluetoothDevice mCachedDevice;
    private final SeekBar.OnSeekBarChangeListener mListener;

    public AudioSharingDeviceVolumePreference(
            Context context,
            @NonNull CachedBluetoothDevice device,
            SeekBar.OnSeekBarChangeListener listener) {
            Context context, @NonNull CachedBluetoothDevice device) {
        super(context);
        setLayoutResource(R.layout.preference_volume_slider);
        mLocalBtManager = Utils.getLocalBtManager(context);
        mCachedDevice = device;
        mListener = listener;
    }

    @Nullable
@@ -55,19 +45,12 @@ public class AudioSharingDeviceVolumePreference extends SeekBarPreference {
        return mCachedDevice;
    }

    @Override
    public void onBindViewHolder(PreferenceViewHolder view) {
        super.onBindViewHolder(view);
        mSeekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
        mSeekBar.setMax(MAX_VOLUME);
        mSeekBar.setMin(MIN_VOLUME);
        mSeekBar.setOnSeekBarChangeListener(mListener);
    }

    /** Set the progress bar to target progress */
    public void setProgress(int progress) {
        if (mSeekBar != null) {
            mSeekBar.setProgress(progress);
        }
    /**
     * Initialize {@link AudioSharingDeviceVolumePreference}.
     * Need to be called after creating the preference.
     */
    public void initialize() {
        setMax(MAX_VOLUME);
        setMin(MIN_VOLUME);
    }
}