1 /*
2  * Copyright (C) 2017 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.BluetoothAdapter;
19 import android.bluetooth.BluetoothDevice;
20 import android.content.Context;
21 import android.util.Log;
22 
23 import androidx.annotation.VisibleForTesting;
24 import androidx.preference.Preference;
25 
26 import com.android.settings.connecteddevice.DevicePreferenceCallback;
27 import com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment;
28 import com.android.settings.dashboard.DashboardFragment;
29 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
30 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
31 
32 import java.util.ArrayList;
33 import java.util.List;
34 
35 /**
36  * Maintain and update saved bluetooth devices(bonded but not connected)
37  */
38 public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater
39         implements Preference.OnPreferenceClickListener {
40 
41     private static final String TAG = "SavedBluetoothDeviceUpdater";
42     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
43 
44     private static final String PREF_KEY = "saved_bt";
45 
46     private final boolean mDisplayConnected;
47 
48     @VisibleForTesting
49     BluetoothAdapter mBluetoothAdapter;
50 
SavedBluetoothDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback)51     public SavedBluetoothDeviceUpdater(Context context, DashboardFragment fragment,
52             DevicePreferenceCallback devicePreferenceCallback) {
53         super(context, fragment, devicePreferenceCallback);
54         mDisplayConnected = (fragment instanceof PreviouslyConnectedDeviceDashboardFragment);
55         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
56     }
57 
58     @Override
forceUpdate()59     public void forceUpdate() {
60         if (mBluetoothAdapter.isEnabled()) {
61             final CachedBluetoothDeviceManager cachedManager =
62                     mLocalManager.getCachedDeviceManager();
63             final List<BluetoothDevice> bluetoothDevices =
64                     mBluetoothAdapter.getMostRecentlyConnectedDevices();
65             removePreferenceIfNecessary(bluetoothDevices, cachedManager);
66             for (BluetoothDevice device : bluetoothDevices) {
67                 final CachedBluetoothDevice cachedDevice = cachedManager.findDevice(device);
68                 if (cachedDevice != null) {
69                     update(cachedDevice);
70                 }
71             }
72         } else {
73             removeAllDevicesFromPreference();
74         }
75     }
76 
removePreferenceIfNecessary(List<BluetoothDevice> bluetoothDevices, CachedBluetoothDeviceManager cachedManager)77     private void removePreferenceIfNecessary(List<BluetoothDevice> bluetoothDevices,
78             CachedBluetoothDeviceManager cachedManager) {
79         for (BluetoothDevice device : new ArrayList<>(mPreferenceMap.keySet())) {
80             if (!bluetoothDevices.contains(device)) {
81                 final CachedBluetoothDevice cachedDevice = cachedManager.findDevice(device);
82                 if (cachedDevice != null) {
83                     removePreference(cachedDevice);
84                 }
85             }
86         }
87     }
88 
89     @Override
update(CachedBluetoothDevice cachedDevice)90     public void update(CachedBluetoothDevice cachedDevice) {
91         if (isFilterMatched(cachedDevice)) {
92             // Add the preference if it is new one
93             addPreference(cachedDevice, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
94         } else {
95             removePreference(cachedDevice);
96         }
97     }
98 
99     @Override
isFilterMatched(CachedBluetoothDevice cachedDevice)100     public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
101         final BluetoothDevice device = cachedDevice.getDevice();
102         if (DBG) {
103             Log.d(TAG, "isFilterMatched() device name : " + cachedDevice.getName() +
104                     ", is connected : " + device.isConnected() + ", is profile connected : "
105                     + cachedDevice.isConnected());
106         }
107         return device.getBondState() == BluetoothDevice.BOND_BONDED
108                 && (mDisplayConnected || !device.isConnected());
109     }
110 
111     @Override
onPreferenceClick(Preference preference)112     public boolean onPreferenceClick(Preference preference) {
113         mMetricsFeatureProvider.logClickedPreference(preference, mFragment.getMetricsCategory());
114         final CachedBluetoothDevice device = ((BluetoothDevicePreference) preference)
115                 .getBluetoothDevice();
116         if (device.isConnected()) {
117             return device.setActive();
118         }
119         device.connect();
120         return true;
121     }
122 
123     @Override
getPreferenceKey()124     protected String getPreferenceKey() {
125         return PREF_KEY;
126     }
127 }
128