1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.connecteddevice.audiosharing.audiostreams;
18 
19 import android.bluetooth.BluetoothProfile;
20 import android.content.Context;
21 import android.text.TextUtils;
22 import android.util.Log;
23 
24 import androidx.annotation.Nullable;
25 
26 import com.android.settings.R;
27 import com.android.settings.bluetooth.Utils;
28 import com.android.settingslib.bluetooth.BluetoothCallback;
29 import com.android.settingslib.bluetooth.BluetoothUtils;
30 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
31 import com.android.settingslib.bluetooth.LocalBluetoothManager;
32 import com.android.settingslib.utils.ThreadUtils;
33 
34 public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback {
35     private static final String TAG = "AudioStreamsActiveDeviceSummaryUpdater";
36     private static final boolean DEBUG = BluetoothUtils.D;
37     private final LocalBluetoothManager mBluetoothManager;
38     private Context mContext;
39     @Nullable private String mSummary;
40     private OnSummaryChangeListener mListener;
41 
AudioStreamsActiveDeviceSummaryUpdater( Context context, OnSummaryChangeListener listener)42     public AudioStreamsActiveDeviceSummaryUpdater(
43             Context context, OnSummaryChangeListener listener) {
44         mContext = context;
45         mBluetoothManager = Utils.getLocalBluetoothManager(context);
46         mListener = listener;
47     }
48 
49     @Override
onActiveDeviceChanged( @ullable CachedBluetoothDevice activeDevice, int bluetoothProfile)50     public void onActiveDeviceChanged(
51             @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
52         if (DEBUG) {
53             Log.d(
54                     TAG,
55                     "onActiveDeviceChanged() with activeDevice : "
56                             + (activeDevice == null ? "null" : activeDevice.getAddress())
57                             + " on profile : "
58                             + bluetoothProfile);
59         }
60         if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
61             notifyChangeIfNeeded();
62         }
63     }
64 
register(boolean register)65     void register(boolean register) {
66         if (register) {
67             notifyChangeIfNeeded();
68             mBluetoothManager.getEventManager().registerCallback(this);
69         } else {
70             mBluetoothManager.getEventManager().unregisterCallback(this);
71         }
72     }
73 
notifyChangeIfNeeded()74     private void notifyChangeIfNeeded() {
75         var unused =
76                 ThreadUtils.postOnBackgroundThread(
77                         () -> {
78                             String summary = getSummary();
79                             if (!TextUtils.equals(mSummary, summary)) {
80                                 mSummary = summary;
81                                 ThreadUtils.postOnMainThread(
82                                         () -> mListener.onSummaryChanged(summary));
83                             }
84                         });
85     }
86 
getSummary()87     private String getSummary() {
88         var connectedSink =
89                 AudioStreamsHelper.getCachedBluetoothDeviceInSharingOrLeConnected(
90                         mBluetoothManager);
91         if (connectedSink.isEmpty()) {
92             return mContext.getString(R.string.audio_streams_dialog_no_le_device_title);
93         }
94         return connectedSink.get().getName();
95     }
96 
97     /** Interface definition for a callback to be invoked when the summary has been changed. */
98     interface OnSummaryChangeListener {
99         /**
100          * Called when summary has changed.
101          *
102          * @param summary The new summary.
103          */
onSummaryChanged(String summary)104         void onSummaryChanged(String summary);
105     }
106 }
107