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.connecteddevice; 17 18 import android.bluetooth.BluetoothAdapter; 19 import android.bluetooth.BluetoothDevice; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.pm.PackageManager; 25 import android.util.Log; 26 27 import androidx.annotation.VisibleForTesting; 28 import androidx.preference.Preference; 29 import androidx.preference.PreferenceGroup; 30 import androidx.preference.PreferenceScreen; 31 32 import com.android.settings.R; 33 import com.android.settings.bluetooth.BluetoothDevicePreference; 34 import com.android.settings.bluetooth.BluetoothDeviceUpdater; 35 import com.android.settings.bluetooth.SavedBluetoothDeviceUpdater; 36 import com.android.settings.connecteddevice.dock.DockUpdater; 37 import com.android.settings.core.BasePreferenceController; 38 import com.android.settings.dashboard.DashboardFragment; 39 import com.android.settings.overlay.FeatureFactory; 40 import com.android.settingslib.core.lifecycle.LifecycleObserver; 41 import com.android.settingslib.core.lifecycle.events.OnStart; 42 import com.android.settingslib.core.lifecycle.events.OnStop; 43 44 import java.util.ArrayList; 45 import java.util.List; 46 47 public class PreviouslyConnectedDevicePreferenceController extends BasePreferenceController 48 implements LifecycleObserver, OnStart, OnStop, DevicePreferenceCallback { 49 50 private static final String TAG = "PreviouslyDevicePreController"; 51 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 52 53 private static final int MAX_DEVICE_NUM = 3; 54 private static final int DOCK_DEVICE_INDEX = 9; 55 private static final String KEY_SEE_ALL = "previously_connected_devices_see_all"; 56 57 private final List<Preference> mDevicesList = new ArrayList<>(); 58 private final List<Preference> mDockDevicesList = new ArrayList<>(); 59 60 private PreferenceGroup mPreferenceGroup; 61 private BluetoothDeviceUpdater mBluetoothDeviceUpdater; 62 private DockUpdater mSavedDockUpdater; 63 private BluetoothAdapter mBluetoothAdapter; 64 65 @VisibleForTesting 66 Preference mSeeAllPreference; 67 @VisibleForTesting 68 IntentFilter mIntentFilter; 69 70 @VisibleForTesting 71 BroadcastReceiver mReceiver = new BroadcastReceiver() { 72 @Override 73 public void onReceive(Context context, Intent intent) { 74 updatePreferenceVisibility(); 75 } 76 }; 77 PreviouslyConnectedDevicePreferenceController(Context context, String preferenceKey)78 public PreviouslyConnectedDevicePreferenceController(Context context, String preferenceKey) { 79 super(context, preferenceKey); 80 81 mSavedDockUpdater = FeatureFactory.getFactory( 82 context).getDockUpdaterFeatureProvider().getSavedDockUpdater(context, this); 83 mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); 84 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 85 } 86 87 @Override getAvailabilityStatus()88 public int getAvailabilityStatus() { 89 return (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH) 90 || mSavedDockUpdater != null) 91 ? AVAILABLE 92 : CONDITIONALLY_UNAVAILABLE; 93 } 94 95 @Override displayPreference(PreferenceScreen screen)96 public void displayPreference(PreferenceScreen screen) { 97 super.displayPreference(screen); 98 mPreferenceGroup = screen.findPreference(getPreferenceKey()); 99 mSeeAllPreference = mPreferenceGroup.findPreference(KEY_SEE_ALL); 100 updatePreferenceVisibility(); 101 102 if (isAvailable()) { 103 final Context context = screen.getContext(); 104 mBluetoothDeviceUpdater.setPrefContext(context); 105 mSavedDockUpdater.setPreferenceContext(context); 106 mBluetoothDeviceUpdater.forceUpdate(); 107 } 108 } 109 110 @Override onStart()111 public void onStart() { 112 mBluetoothDeviceUpdater.registerCallback(); 113 mSavedDockUpdater.registerCallback(); 114 mContext.registerReceiver(mReceiver, mIntentFilter); 115 mBluetoothDeviceUpdater.refreshPreference(); 116 } 117 118 @Override onStop()119 public void onStop() { 120 mBluetoothDeviceUpdater.unregisterCallback(); 121 mSavedDockUpdater.unregisterCallback(); 122 mContext.unregisterReceiver(mReceiver); 123 } 124 init(DashboardFragment fragment)125 public void init(DashboardFragment fragment) { 126 mBluetoothDeviceUpdater = new SavedBluetoothDeviceUpdater(fragment.getContext(), 127 fragment, PreviouslyConnectedDevicePreferenceController.this); 128 } 129 130 @Override onDeviceAdded(Preference preference)131 public void onDeviceAdded(Preference preference) { 132 final List<BluetoothDevice> bluetoothDevices = 133 mBluetoothAdapter.getMostRecentlyConnectedDevices(); 134 final int index = preference instanceof BluetoothDevicePreference 135 ? bluetoothDevices.indexOf(((BluetoothDevicePreference) preference) 136 .getBluetoothDevice().getDevice()) : DOCK_DEVICE_INDEX; 137 if (DEBUG) { 138 Log.d(TAG, "onDeviceAdded() " + preference.getTitle() + ", index of : " + index); 139 for (BluetoothDevice device : bluetoothDevices) { 140 Log.d(TAG, "onDeviceAdded() most recently device : " + device.getName()); 141 } 142 } 143 addPreference(index, preference); 144 updatePreferenceVisibility(); 145 } 146 addPreference(int index, Preference preference)147 private void addPreference(int index, Preference preference) { 148 if (preference instanceof BluetoothDevicePreference) { 149 if (index >= 0 && mDevicesList.size() >= index) { 150 mDevicesList.add(index, preference); 151 } else { 152 mDevicesList.add(preference); 153 } 154 } else { 155 mDockDevicesList.add(preference); 156 } 157 addPreference(); 158 } 159 addPreference()160 private void addPreference() { 161 mPreferenceGroup.removeAll(); 162 mPreferenceGroup.addPreference(mSeeAllPreference); 163 final int size = getDeviceListSize(); 164 for (int i = 0; i < size; i++) { 165 if (DEBUG) { 166 Log.d(TAG, "addPreference() add device : " + mDevicesList.get(i).getTitle()); 167 } 168 mDevicesList.get(i).setOrder(i); 169 mPreferenceGroup.addPreference(mDevicesList.get(i)); 170 } 171 if (mDockDevicesList.size() > 0) { 172 for (int i = 0; i < getDockDeviceListSize(MAX_DEVICE_NUM - size); i++) { 173 if (DEBUG) { 174 Log.d(TAG, "addPreference() add dock device : " 175 + mDockDevicesList.get(i).getTitle()); 176 } 177 mDockDevicesList.get(i).setOrder(DOCK_DEVICE_INDEX); 178 mPreferenceGroup.addPreference(mDockDevicesList.get(i)); 179 } 180 } 181 } 182 getDeviceListSize()183 private int getDeviceListSize() { 184 return mDevicesList.size() >= MAX_DEVICE_NUM 185 ? MAX_DEVICE_NUM : mDevicesList.size(); 186 } 187 getDockDeviceListSize(int availableSize)188 private int getDockDeviceListSize(int availableSize) { 189 return mDockDevicesList.size() >= availableSize 190 ? availableSize : mDockDevicesList.size(); 191 } 192 193 @Override onDeviceRemoved(Preference preference)194 public void onDeviceRemoved(Preference preference) { 195 if (preference instanceof BluetoothDevicePreference) { 196 mDevicesList.remove(preference); 197 } else { 198 mDockDevicesList.remove(preference); 199 } 200 201 addPreference(); 202 updatePreferenceVisibility(); 203 } 204 205 @VisibleForTesting setBluetoothDeviceUpdater(BluetoothDeviceUpdater bluetoothDeviceUpdater)206 void setBluetoothDeviceUpdater(BluetoothDeviceUpdater bluetoothDeviceUpdater) { 207 mBluetoothDeviceUpdater = bluetoothDeviceUpdater; 208 } 209 210 @VisibleForTesting setSavedDockUpdater(DockUpdater savedDockUpdater)211 void setSavedDockUpdater(DockUpdater savedDockUpdater) { 212 mSavedDockUpdater = savedDockUpdater; 213 } 214 215 @VisibleForTesting setPreferenceGroup(PreferenceGroup preferenceGroup)216 void setPreferenceGroup(PreferenceGroup preferenceGroup) { 217 mPreferenceGroup = preferenceGroup; 218 } 219 220 @VisibleForTesting updatePreferenceVisibility()221 void updatePreferenceVisibility() { 222 if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) { 223 mSeeAllPreference.setSummary(""); 224 } else { 225 mSeeAllPreference.setSummary( 226 mContext.getString(R.string.connected_device_see_all_summary)); 227 } 228 } 229 } 230