blob: 0535d153e91221363f9a75a496a7a5972a872d47 [file] [log] [blame]
hughchenbd3e5de2018-03-23 16:14:13 +08001/*
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 */
16package com.android.settings.connecteddevice;
17
hughchenf4310882018-04-17 16:36:58 +080018import static com.android.settingslib.Utils.isAudioModeOngoingCall;
19
jasonwshsuacd3f942022-03-20 16:12:18 +080020import android.bluetooth.BluetoothProfile;
hughchenbd3e5de2018-03-23 16:14:13 +080021import android.content.Context;
22import android.content.pm.PackageManager;
hughchen34066fa2018-06-25 11:06:45 +080023import android.util.Log;
Fan Zhangc7162cd2018-06-18 15:21:41 -070024
Yiyi Shenbf6e2732023-12-13 18:14:42 +080025import androidx.annotation.NonNull;
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080026import androidx.annotation.Nullable;
Fan Zhang23f8d592018-08-28 15:11:40 -070027import androidx.annotation.VisibleForTesting;
jasonwshsuacd3f942022-03-20 16:12:18 +080028import androidx.fragment.app.FragmentManager;
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080029import androidx.lifecycle.DefaultLifecycleObserver;
30import androidx.lifecycle.LifecycleOwner;
Fan Zhang23f8d592018-08-28 15:11:40 -070031import androidx.preference.Preference;
32import androidx.preference.PreferenceGroup;
33import androidx.preference.PreferenceScreen;
34
Fan Zhangc7162cd2018-06-18 15:21:41 -070035import com.android.settings.R;
jasonwshsuacd3f942022-03-20 16:12:18 +080036import com.android.settings.accessibility.HearingAidUtils;
hughchenbd3e5de2018-03-23 16:14:13 +080037import com.android.settings.bluetooth.AvailableMediaBluetoothDeviceUpdater;
38import com.android.settings.bluetooth.BluetoothDeviceUpdater;
hughchenf4310882018-04-17 16:36:58 +080039import com.android.settings.bluetooth.Utils;
hughchenbd3e5de2018-03-23 16:14:13 +080040import com.android.settings.core.BasePreferenceController;
41import com.android.settings.dashboard.DashboardFragment;
hughchenf4310882018-04-17 16:36:58 +080042import com.android.settingslib.bluetooth.BluetoothCallback;
Yiyi Shenbf6e2732023-12-13 18:14:42 +080043import com.android.settingslib.bluetooth.BluetoothUtils;
jasonwshsuacd3f942022-03-20 16:12:18 +080044import com.android.settingslib.bluetooth.CachedBluetoothDevice;
hughchenf4310882018-04-17 16:36:58 +080045import com.android.settingslib.bluetooth.LocalBluetoothManager;
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080046import com.android.settingslib.core.lifecycle.Lifecycle;
Yiyi Shenbf6e2732023-12-13 18:14:42 +080047
hughchenbd3e5de2018-03-23 16:14:13 +080048/**
Yiyi Shenbf6e2732023-12-13 18:14:42 +080049 * Controller to maintain the {@link androidx.preference.PreferenceGroup} for all available media
50 * devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
hughchenbd3e5de2018-03-23 16:14:13 +080051 */
52public class AvailableMediaDeviceGroupController extends BasePreferenceController
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080053 implements DefaultLifecycleObserver, DevicePreferenceCallback, BluetoothCallback {
Yiyi Shenbf6e2732023-12-13 18:14:42 +080054 private static final boolean DEBUG = BluetoothUtils.D;
hughchenbd3e5de2018-03-23 16:14:13 +080055
hughchen34066fa2018-06-25 11:06:45 +080056 private static final String TAG = "AvailableMediaDeviceGroupController";
hughchenbd3e5de2018-03-23 16:14:13 +080057 private static final String KEY = "available_device_list";
58
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080059 @VisibleForTesting @Nullable PreferenceGroup mPreferenceGroup;
Yiyi Shenbf6e2732023-12-13 18:14:42 +080060 @VisibleForTesting LocalBluetoothManager mLocalBluetoothManager;
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080061 @Nullable private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
62 @Nullable private FragmentManager mFragmentManager;
Yiyi Shenbf6e2732023-12-13 18:14:42 +080063
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080064 public AvailableMediaDeviceGroupController(
65 Context context,
66 @Nullable DashboardFragment fragment,
67 @Nullable Lifecycle lifecycle) {
hughchenbd3e5de2018-03-23 16:14:13 +080068 super(context, KEY);
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080069 if (fragment != null) {
70 init(fragment);
71 }
72 if (lifecycle != null) {
73 lifecycle.addObserver(this);
74 }
hughchenf4310882018-04-17 16:36:58 +080075 mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
hughchenbd3e5de2018-03-23 16:14:13 +080076 }
77
78 @Override
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080079 public void onStart(@NonNull LifecycleOwner owner) {
hughchen34066fa2018-06-25 11:06:45 +080080 if (mLocalBluetoothManager == null) {
81 Log.e(TAG, "onStart() Bluetooth is not supported on this device");
82 return;
83 }
hughchenf4310882018-04-17 16:36:58 +080084 mLocalBluetoothManager.getEventManager().registerCallback(this);
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080085 if (mBluetoothDeviceUpdater != null) {
86 mBluetoothDeviceUpdater.registerCallback();
87 mBluetoothDeviceUpdater.refreshPreference();
88 }
hughchenbd3e5de2018-03-23 16:14:13 +080089 }
90
91 @Override
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080092 public void onStop(@NonNull LifecycleOwner owner) {
hughchen34066fa2018-06-25 11:06:45 +080093 if (mLocalBluetoothManager == null) {
94 Log.e(TAG, "onStop() Bluetooth is not supported on this device");
95 return;
96 }
Yiyi Shen42b8fbb2024-02-23 15:11:11 +080097 if (mBluetoothDeviceUpdater != null) {
98 mBluetoothDeviceUpdater.unregisterCallback();
Yiyi Shenbf6e2732023-12-13 18:14:42 +080099 }
hughchenf4310882018-04-17 16:36:58 +0800100 mLocalBluetoothManager.getEventManager().unregisterCallback(this);
hughchenbd3e5de2018-03-23 16:14:13 +0800101 }
102
103 @Override
104 public void displayPreference(PreferenceScreen screen) {
105 super.displayPreference(screen);
hughchenef2c1a12019-04-17 15:43:22 +0800106
107 mPreferenceGroup = screen.findPreference(KEY);
Yiyi Shen42b8fbb2024-02-23 15:11:11 +0800108 if (mPreferenceGroup != null) {
109 mPreferenceGroup.setVisible(false);
110 }
hughchenef2c1a12019-04-17 15:43:22 +0800111
hughchenbd3e5de2018-03-23 16:14:13 +0800112 if (isAvailable()) {
hughchenf4310882018-04-17 16:36:58 +0800113 updateTitle();
Yiyi Shen42b8fbb2024-02-23 15:11:11 +0800114 if (mBluetoothDeviceUpdater != null) {
115 mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
116 mBluetoothDeviceUpdater.forceUpdate();
117 }
hughchenbd3e5de2018-03-23 16:14:13 +0800118 }
119 }
120
121 @Override
122 public int getAvailabilityStatus() {
123 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
Fan Zhang9ce4a1f2018-08-15 12:55:56 -0700124 ? AVAILABLE_UNSEARCHABLE
Matthew Fritzef87a1f32018-05-03 16:46:51 -0700125 : UNSUPPORTED_ON_DEVICE;
hughchenbd3e5de2018-03-23 16:14:13 +0800126 }
127
128 @Override
129 public String getPreferenceKey() {
130 return KEY;
131 }
132
133 @Override
134 public void onDeviceAdded(Preference preference) {
Yiyi Shen42b8fbb2024-02-23 15:11:11 +0800135 if (mPreferenceGroup != null) {
136 if (mPreferenceGroup.getPreferenceCount() == 0) {
137 mPreferenceGroup.setVisible(true);
138 }
139 mPreferenceGroup.addPreference(preference);
hughchenbd3e5de2018-03-23 16:14:13 +0800140 }
hughchenbd3e5de2018-03-23 16:14:13 +0800141 }
142
143 @Override
144 public void onDeviceRemoved(Preference preference) {
Yiyi Shen42b8fbb2024-02-23 15:11:11 +0800145 if (mPreferenceGroup != null) {
146 mPreferenceGroup.removePreference(preference);
147 if (mPreferenceGroup.getPreferenceCount() == 0) {
148 mPreferenceGroup.setVisible(false);
149 }
hughchenbd3e5de2018-03-23 16:14:13 +0800150 }
151 }
152
153 public void init(DashboardFragment fragment) {
jasonwshsuacd3f942022-03-20 16:12:18 +0800154 mFragmentManager = fragment.getParentFragmentManager();
Yiyi Shenbf6e2732023-12-13 18:14:42 +0800155 mBluetoothDeviceUpdater =
156 new AvailableMediaBluetoothDeviceUpdater(
157 fragment.getContext(),
158 AvailableMediaDeviceGroupController.this,
159 fragment.getMetricsCategory());
hughchenbd3e5de2018-03-23 16:14:13 +0800160 }
161
162 @VisibleForTesting
Angela Wangbb1fe042023-09-08 11:35:03 +0000163 public void setFragmentManager(FragmentManager fragmentManager) {
164 mFragmentManager = fragmentManager;
165 }
166
167 @VisibleForTesting
hughchenbd3e5de2018-03-23 16:14:13 +0800168 public void setBluetoothDeviceUpdater(BluetoothDeviceUpdater bluetoothDeviceUpdater) {
Fan Zhang7db118e2019-02-14 12:25:29 -0800169 mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
hughchenbd3e5de2018-03-23 16:14:13 +0800170 }
hughchenf4310882018-04-17 16:36:58 +0800171
172 @Override
hughchenf4310882018-04-17 16:36:58 +0800173 public void onAudioModeChanged() {
174 updateTitle();
175 }
176
jasonwshsuacd3f942022-03-20 16:12:18 +0800177 @Override
178 public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
179 // exclude inactive device
180 if (activeDevice == null) {
181 return;
182 }
183
184 if (bluetoothProfile == BluetoothProfile.HEARING_AID) {
Yiyi Shenbf6e2732023-12-13 18:14:42 +0800185 HearingAidUtils.launchHearingAidPairingDialog(
186 mFragmentManager, activeDevice, getMetricsCategory());
jasonwshsuacd3f942022-03-20 16:12:18 +0800187 }
188 }
189
hughchenf4310882018-04-17 16:36:58 +0800190 private void updateTitle() {
Yiyi Shen42b8fbb2024-02-23 15:11:11 +0800191 if (mPreferenceGroup != null) {
192 if (isAudioModeOngoingCall(mContext)) {
193 // in phone call
194 mPreferenceGroup.setTitle(
195 mContext.getString(R.string.connected_device_call_device_title));
196 } else {
197 // without phone call
198 mPreferenceGroup.setTitle(
199 mContext.getString(R.string.connected_device_media_device_title));
200 }
hughchenf4310882018-04-17 16:36:58 +0800201 }
202 }
hughchenbd3e5de2018-03-23 16:14:13 +0800203}