• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.accessibility;
18 
19 import android.bluetooth.BluetoothProfile;
20 import android.content.Context;
21 import android.util.Log;
22 
23 import androidx.annotation.VisibleForTesting;
24 import androidx.fragment.app.FragmentManager;
25 import androidx.preference.Preference;
26 import androidx.preference.PreferenceScreen;
27 
28 import com.android.settings.R;
29 import com.android.settings.bluetooth.BluetoothDeviceUpdater;
30 import com.android.settings.connecteddevice.DevicePreferenceCallback;
31 import com.android.settings.dashboard.DashboardFragment;
32 import com.android.settingslib.bluetooth.BluetoothCallback;
33 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
34 import com.android.settingslib.bluetooth.LocalBluetoothManager;
35 import com.android.settingslib.core.lifecycle.LifecycleObserver;
36 import com.android.settingslib.core.lifecycle.events.OnStart;
37 import com.android.settingslib.core.lifecycle.events.OnStop;
38 import com.android.settingslib.search.SearchIndexableRaw;
39 
40 import java.util.List;
41 
42 /**
43  * Controller to update the {@link androidx.preference.PreferenceCategory} for all
44  * connected hearing devices, including ASHA and HAP profile.
45  * Parent class {@link BaseBluetoothDevicePreferenceController} will use
46  * {@link DevicePreferenceCallback} to add/remove {@link Preference}.
47  */
48 public class AvailableHearingDevicePreferenceController extends
49         BaseBluetoothDevicePreferenceController implements LifecycleObserver, OnStart, OnStop,
50         BluetoothCallback {
51 
52     private static final String TAG = "AvailableHearingDevicePreferenceController";
53     private static final String SEARCH_DATA_KEY_PREFIX = "a11y_available_hearing_device";
54 
55     private BluetoothDeviceUpdater mAvailableHearingDeviceUpdater;
56     private final LocalBluetoothManager mLocalBluetoothManager;
57     private FragmentManager mFragmentManager;
58 
AvailableHearingDevicePreferenceController(Context context, String preferenceKey)59     public AvailableHearingDevicePreferenceController(Context context,
60             String preferenceKey) {
61         super(context, preferenceKey);
62         mLocalBluetoothManager = com.android.settings.bluetooth.Utils.getLocalBluetoothManager(
63                 context);
64     }
65 
66     @VisibleForTesting
init(AvailableHearingDeviceUpdater availableHearingDeviceUpdater)67     void init(AvailableHearingDeviceUpdater availableHearingDeviceUpdater) {
68         if (mAvailableHearingDeviceUpdater != null) {
69             throw new IllegalStateException("Should not call init() more than 1 time.");
70         }
71         mAvailableHearingDeviceUpdater = availableHearingDeviceUpdater;
72     }
73 
74     /**
75      * Initializes objects in this controller. Need to call this before onStart().
76      *
77      * <p>Should not call this more than 1 time.
78      *
79      * @param fragment The {@link DashboardFragment} uses the controller.
80      */
init(DashboardFragment fragment)81     public void init(DashboardFragment fragment) {
82         if (mAvailableHearingDeviceUpdater != null) {
83             throw new IllegalStateException("Should not call init() more than 1 time.");
84         }
85         mAvailableHearingDeviceUpdater = new AvailableHearingDeviceUpdater(fragment.getContext(),
86                 this, fragment.getMetricsCategory());
87         mFragmentManager = fragment.getParentFragmentManager();
88     }
89 
90     @Override
onStart()91     public void onStart() {
92         mAvailableHearingDeviceUpdater.registerCallback();
93         mAvailableHearingDeviceUpdater.refreshPreference();
94         mLocalBluetoothManager.getEventManager().registerCallback(this);
95     }
96 
97     @Override
onStop()98     public void onStop() {
99         mAvailableHearingDeviceUpdater.unregisterCallback();
100         mLocalBluetoothManager.getEventManager().unregisterCallback(this);
101     }
102 
103     @Override
displayPreference(PreferenceScreen screen)104     public void displayPreference(PreferenceScreen screen) {
105         super.displayPreference(screen);
106 
107         if (isAvailable()) {
108             final Context context = screen.getContext();
109             mAvailableHearingDeviceUpdater.setPrefContext(context);
110             mAvailableHearingDeviceUpdater.forceUpdate();
111         }
112     }
113 
114     @Override
onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile)115     public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
116         if (activeDevice == null) {
117             return;
118         }
119 
120         if (bluetoothProfile == BluetoothProfile.HEARING_AID) {
121             HearingAidUtils.launchHearingAidPairingDialog(mFragmentManager, activeDevice,
122                     getMetricsCategory());
123         }
124     }
125 
126     @Override
updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData)127     public void updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData) {
128         if (Flags.fixA11ySettingsSearch()) {
129             if (mLocalBluetoothManager == null) {
130                 Log.d(TAG, "Bluetooth is not supported");
131                 return;
132             }
133 
134             for (CachedBluetoothDevice cachedDevice :
135                     mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) {
136 
137                 if (!AvailableHearingDeviceUpdater.isAvailableHearingDevice(cachedDevice)) {
138                     continue;
139                 }
140 
141                 SearchIndexableRaw data = new SearchIndexableRaw(mContext);
142                 // Include the identity address and add prefix to ensure the key is unique and
143                 // distinguish from Bluetooth's connected devices.
144                 data.key = SEARCH_DATA_KEY_PREFIX
145                         + cachedDevice.getName() + cachedDevice.getIdentityAddress();
146                 data.title = cachedDevice.getName();
147                 data.summaryOn = mContext.getString(R.string.accessibility_hearingaid_title);
148                 data.screenTitle = mContext.getString(R.string.accessibility_hearingaid_title);
149                 rawData.add(data);
150             }
151         } else {
152             super.updateDynamicRawDataToIndex(rawData);
153         }
154     }
155 }
156