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 } 107 } 108 109 @Override onStart()110 public void onStart() { 111 mBluetoothDeviceUpdater.registerCallback(); 112 mSavedDockUpdater.registerCallback(); 113 mContext.registerReceiver(mReceiver, mIntentFilter); 114 } 115 116 @Override onStop()117 public void onStop() { 118 mBluetoothDeviceUpdater.unregisterCallback(); 119 mSavedDockUpdater.unregisterCallback(); 120 mContext.unregisterReceiver(mReceiver); 121 } 122 init(DashboardFragment fragment)123 public void init(DashboardFragment fragment) { 124 mBluetoothDeviceUpdater = new SavedBluetoothDeviceUpdater(fragment.getContext(), 125 fragment, PreviouslyConnectedDevicePreferenceController.this); 126 } 127 128 @Override onDeviceAdded(Preference preference)129 public void onDeviceAdded(Preference preference) { 130 final List<BluetoothDevice> bluetoothDevices = 131 mBluetoothAdapter.getMostRecentlyConnectedDevices(); 132 final int index = preference instanceof BluetoothDevicePreference 133 ? bluetoothDevices.indexOf(((BluetoothDevicePreference) preference) 134 .getBluetoothDevice().getDevice()) : DOCK_DEVICE_INDEX; 135 if (DEBUG) { 136 Log.d(TAG, "onDeviceAdded() " + preference.getTitle() + ", index of : " + index); 137 for (BluetoothDevice device : bluetoothDevices) { 138 Log.d(TAG, "onDeviceAdded() most recently device : " + device.getName()); 139 } 140 } 141 addPreference(index, preference); 142 updatePreferenceVisibility(); 143 } 144 addPreference(int index, Preference preference)145 private void addPreference(int index, Preference preference) { 146 if (preference instanceof BluetoothDevicePreference) { 147 if (mDevicesList.size() >= index) { 148 mDevicesList.add(index, preference); 149 } else { 150 mDevicesList.add(preference); 151 } 152 } else { 153 mDockDevicesList.add(preference); 154 } 155 addPreference(); 156 } 157 addPreference()158 private void addPreference() { 159 mPreferenceGroup.removeAll(); 160 mPreferenceGroup.addPreference(mSeeAllPreference); 161 final int size = getDeviceListSize(); 162 for (int i = 0; i < size; i++) { 163 if (DEBUG) { 164 Log.d(TAG, "addPreference() add device : " + mDevicesList.get(i).getTitle()); 165 } 166 mDevicesList.get(i).setOrder(i); 167 mPreferenceGroup.addPreference(mDevicesList.get(i)); 168 } 169 if (mDockDevicesList.size() > 0) { 170 for (int i = 0; i < getDockDeviceListSize(MAX_DEVICE_NUM - size); i++) { 171 if (DEBUG) { 172 Log.d(TAG, "addPreference() add dock device : " 173 + mDockDevicesList.get(i).getTitle()); 174 } 175 mDockDevicesList.get(i).setOrder(DOCK_DEVICE_INDEX); 176 mPreferenceGroup.addPreference(mDockDevicesList.get(i)); 177 } 178 } 179 } 180 getDeviceListSize()181 private int getDeviceListSize() { 182 return mDevicesList.size() >= MAX_DEVICE_NUM 183 ? MAX_DEVICE_NUM : mDevicesList.size(); 184 } 185 getDockDeviceListSize(int availableSize)186 private int getDockDeviceListSize(int availableSize) { 187 return mDockDevicesList.size() >= availableSize 188 ? availableSize : mDockDevicesList.size(); 189 } 190 191 @Override onDeviceRemoved(Preference preference)192 public void onDeviceRemoved(Preference preference) { 193 if (preference instanceof BluetoothDevicePreference) { 194 mDevicesList.remove(preference); 195 } else { 196 mDockDevicesList.remove(preference); 197 } 198 199 addPreference(); 200 updatePreferenceVisibility(); 201 } 202 203 @VisibleForTesting setBluetoothDeviceUpdater(BluetoothDeviceUpdater bluetoothDeviceUpdater)204 void setBluetoothDeviceUpdater(BluetoothDeviceUpdater bluetoothDeviceUpdater) { 205 mBluetoothDeviceUpdater = bluetoothDeviceUpdater; 206 } 207 208 @VisibleForTesting setSavedDockUpdater(DockUpdater savedDockUpdater)209 void setSavedDockUpdater(DockUpdater savedDockUpdater) { 210 mSavedDockUpdater = savedDockUpdater; 211 } 212 213 @VisibleForTesting setPreferenceGroup(PreferenceGroup preferenceGroup)214 void setPreferenceGroup(PreferenceGroup preferenceGroup) { 215 mPreferenceGroup = preferenceGroup; 216 } 217 218 @VisibleForTesting updatePreferenceVisibility()219 void updatePreferenceVisibility() { 220 if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) { 221 mSeeAllPreference.setSummary(""); 222 } else { 223 mSeeAllPreference.setSummary( 224 mContext.getString(R.string.connected_device_see_all_summary)); 225 } 226 } 227 } 228