• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 package com.android.settings.bluetooth;
17 
18 import android.bluetooth.BluetoothProfile;
19 import android.content.Context;
20 import android.media.AudioManager;
21 import android.util.Log;
22 
23 import androidx.preference.Preference;
24 
25 import com.android.settings.connecteddevice.DevicePreferenceCallback;
26 import com.android.settingslib.bluetooth.BluetoothUtils;
27 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
28 import com.android.settingslib.bluetooth.LocalBluetoothManager;
29 import com.android.settingslib.utils.ThreadUtils;
30 
31 /** Controller to maintain available media Bluetooth devices */
32 public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater
33         implements Preference.OnPreferenceClickListener {
34 
35     private static final String TAG = "AvailableMediaBluetoothDeviceUpdater";
36     private static final boolean DBG = Log.isLoggable(BluetoothDeviceUpdater.TAG, Log.DEBUG);
37 
38     private static final String PREF_KEY_PREFIX = "available_media_bt_";
39 
40     private final AudioManager mAudioManager;
41     private final LocalBluetoothManager mLocalBtManager;
42     private int mAudioMode;
43 
AvailableMediaBluetoothDeviceUpdater( Context context, DevicePreferenceCallback devicePreferenceCallback, int metricsCategory)44     public AvailableMediaBluetoothDeviceUpdater(
45             Context context,
46             DevicePreferenceCallback devicePreferenceCallback,
47             int metricsCategory) {
48         super(context, devicePreferenceCallback, metricsCategory);
49         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
50         mLocalBtManager = Utils.getLocalBtManager(context);
51         mAudioMode = mAudioManager.getMode();
52     }
53 
54     @Override
onAudioModeChanged()55     public void onAudioModeChanged() {
56         // TODO: move to background thread
57         mAudioMode = mAudioManager.getMode();
58         forceUpdate();
59     }
60 
61     @Override
isFilterMatched(CachedBluetoothDevice cachedDevice)62     public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
63         final int currentAudioProfile;
64 
65         if (mAudioMode == AudioManager.MODE_RINGTONE
66                 || mAudioMode == AudioManager.MODE_IN_CALL
67                 || mAudioMode == AudioManager.MODE_IN_COMMUNICATION) {
68             // in phone call
69             currentAudioProfile = BluetoothProfile.HEADSET;
70         } else {
71             // without phone call
72             currentAudioProfile = BluetoothProfile.A2DP;
73         }
74 
75         boolean isFilterMatched = false;
76         if (isDeviceConnected(cachedDevice) && isDeviceInCachedDevicesList(cachedDevice)) {
77             Log.d(TAG, "isFilterMatched() current audio profile : " + currentAudioProfile);
78 
79             // If device is LE Audio, it is compatible with HFP and A2DP.
80             // It would show in Available Devices group if the audio sharing flag is disabled or
81             // the device is not in the audio sharing session.
82             if (cachedDevice.isConnectedLeAudioDevice()
83                     || cachedDevice.hasConnectedLeAudioMemberDevice()) {
84                 if (BluetoothUtils.isAudioSharingUIAvailable(mContext)
85                         && BluetoothUtils.hasConnectedBroadcastSource(
86                         cachedDevice, mLocalBtManager)) {
87                     Log.d(
88                             TAG,
89                             "Filter out device : "
90                                     + cachedDevice.getName()
91                                     + ", it is in audio sharing.");
92                     return false;
93 
94                 } else {
95                     Log.d(
96                             TAG,
97                             "isFilterMatched() device : "
98                                     + cachedDevice.getName()
99                                     + ", the LE Audio profile is connected and not in sharing "
100                                     + "if broadcast enabled.");
101                     return true;
102                 }
103             }
104 
105             // If device is Hearing Aid, it is compatible with HFP and A2DP.
106             // It would show in Available Devices group.
107             if (cachedDevice.isConnectedAshaHearingAidDevice()) {
108                 Log.d(
109                         TAG,
110                         "isFilterMatched() device : "
111                                 + cachedDevice.getName()
112                                 + ", the Hearing Aid profile is connected.");
113                 return true;
114             }
115 
116             // According to the current audio profile type,
117             // this page will show the bluetooth device that have corresponding profile.
118             // For example:
119             // If current audio profile is a2dp, show the bluetooth device that have a2dp profile.
120             // If current audio profile is headset,
121             // show the bluetooth device that have headset profile.
122             switch (currentAudioProfile) {
123                 case BluetoothProfile.A2DP:
124                     isFilterMatched = cachedDevice.isConnectedA2dpDevice();
125                     break;
126                 case BluetoothProfile.HEADSET:
127                     isFilterMatched = cachedDevice.isConnectedHfpDevice();
128                     break;
129             }
130             Log.d(
131                     TAG,
132                     "isFilterMatched() device : "
133                             + cachedDevice.getName()
134                             + ", isFilterMatched : "
135                             + isFilterMatched);
136         }
137         return isFilterMatched;
138     }
139 
140     @Override
onPreferenceClick(Preference preference)141     public boolean onPreferenceClick(Preference preference) {
142         mMetricsFeatureProvider.logClickedPreference(preference, mMetricsCategory);
143         var unused =
144                 ThreadUtils.postOnBackgroundThread(
145                         () -> mDevicePreferenceCallback.onDeviceClick(preference));
146         return true;
147     }
148 
149     @Override
getPreferenceKeyPrefix()150     protected String getPreferenceKeyPrefix() {
151         return PREF_KEY_PREFIX;
152     }
153 
154     @Override
getLogTag()155     protected String getLogTag() {
156         return TAG;
157     }
158 
159     @Override
update(CachedBluetoothDevice cachedBluetoothDevice)160     protected void update(CachedBluetoothDevice cachedBluetoothDevice) {
161         super.update(cachedBluetoothDevice);
162         Log.d(TAG, "Map : " + mPreferenceMap);
163     }
164 }
165