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 17 package com.android.settings.bluetooth; 18 19 import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH; 20 21 import android.bluetooth.BluetoothAdapter; 22 import android.bluetooth.BluetoothDevice; 23 import android.content.Context; 24 import android.os.Bundle; 25 import android.support.annotation.VisibleForTesting; 26 import android.util.Log; 27 28 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 29 import com.android.settings.R; 30 import com.android.settings.search.Indexable; 31 import com.android.settingslib.bluetooth.BluetoothDeviceFilter; 32 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 33 import com.android.settingslib.widget.FooterPreference; 34 35 /** 36 * BluetoothPairingDetail is a page to scan bluetooth devices and pair them. 37 */ 38 public class BluetoothPairingDetail extends DeviceListPreferenceFragment implements 39 Indexable { 40 private static final String TAG = "BluetoothPairingDetail"; 41 42 @VisibleForTesting 43 static final String KEY_AVAIL_DEVICES = "available_devices"; 44 @VisibleForTesting 45 static final String KEY_FOOTER_PREF = "footer_preference"; 46 47 @VisibleForTesting 48 BluetoothProgressCategory mAvailableDevicesCategory; 49 @VisibleForTesting 50 FooterPreference mFooterPreference; 51 @VisibleForTesting 52 AlwaysDiscoverable mAlwaysDiscoverable; 53 54 private boolean mInitialScanStarted; 55 BluetoothPairingDetail()56 public BluetoothPairingDetail() { 57 super(DISALLOW_CONFIG_BLUETOOTH); 58 } 59 60 @Override onActivityCreated(Bundle savedInstanceState)61 public void onActivityCreated(Bundle savedInstanceState) { 62 super.onActivityCreated(savedInstanceState); 63 mInitialScanStarted = false; 64 mAlwaysDiscoverable = new AlwaysDiscoverable(getContext(), mLocalAdapter); 65 } 66 67 @Override onStart()68 public void onStart() { 69 super.onStart(); 70 if (mLocalManager == null){ 71 Log.e(TAG, "Bluetooth is not supported on this device"); 72 return; 73 } 74 updateBluetooth(); 75 mAvailableDevicesCategory.setProgress(mLocalAdapter.isDiscovering()); 76 } 77 78 @Override onAttach(Context context)79 public void onAttach(Context context) { 80 super.onAttach(context); 81 use(BluetoothDeviceRenamePreferenceController.class).setFragment(this); 82 } 83 84 @VisibleForTesting updateBluetooth()85 void updateBluetooth() { 86 if (mLocalAdapter.isEnabled()) { 87 updateContent(mLocalAdapter.getBluetoothState()); 88 } else { 89 // Turn on bluetooth if it is disabled 90 mLocalAdapter.enable(); 91 } 92 } 93 94 @Override onStop()95 public void onStop() { 96 super.onStop(); 97 if (mLocalManager == null){ 98 Log.e(TAG, "Bluetooth is not supported on this device"); 99 return; 100 } 101 // Make the device only visible to connected devices. 102 mAlwaysDiscoverable.stop(); 103 disableScanning(); 104 } 105 106 @Override initPreferencesFromPreferenceScreen()107 void initPreferencesFromPreferenceScreen() { 108 mAvailableDevicesCategory = (BluetoothProgressCategory) findPreference(KEY_AVAIL_DEVICES); 109 mFooterPreference = (FooterPreference) findPreference(KEY_FOOTER_PREF); 110 mFooterPreference.setSelectable(false); 111 } 112 113 @Override getMetricsCategory()114 public int getMetricsCategory() { 115 return MetricsEvent.BLUETOOTH_PAIRING; 116 } 117 118 @Override enableScanning()119 void enableScanning() { 120 // Clear all device states before first scan 121 if (!mInitialScanStarted) { 122 if (mAvailableDevicesCategory != null) { 123 removeAllDevices(); 124 } 125 mLocalManager.getCachedDeviceManager().clearNonBondedDevices(); 126 mInitialScanStarted = true; 127 } 128 super.enableScanning(); 129 } 130 131 @Override onDevicePreferenceClick(BluetoothDevicePreference btPreference)132 void onDevicePreferenceClick(BluetoothDevicePreference btPreference) { 133 disableScanning(); 134 super.onDevicePreferenceClick(btPreference); 135 } 136 137 @Override onScanningStateChanged(boolean started)138 public void onScanningStateChanged(boolean started) { 139 super.onScanningStateChanged(started); 140 started |= mScanEnabled; 141 mAvailableDevicesCategory.setProgress(started); 142 } 143 144 @VisibleForTesting updateContent(int bluetoothState)145 void updateContent(int bluetoothState) { 146 switch (bluetoothState) { 147 case BluetoothAdapter.STATE_ON: 148 mDevicePreferenceMap.clear(); 149 mLocalAdapter.setBluetoothEnabled(true); 150 151 addDeviceCategory(mAvailableDevicesCategory, 152 R.string.bluetooth_preference_found_media_devices, 153 BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER, mInitialScanStarted); 154 updateFooterPreference(mFooterPreference); 155 mAlwaysDiscoverable.start(); 156 enableScanning(); 157 break; 158 159 case BluetoothAdapter.STATE_OFF: 160 finish(); 161 break; 162 } 163 } 164 165 @Override onBluetoothStateChanged(int bluetoothState)166 public void onBluetoothStateChanged(int bluetoothState) { 167 super.onBluetoothStateChanged(bluetoothState); 168 updateContent(bluetoothState); 169 } 170 171 @Override onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState)172 public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { 173 if (bondState == BluetoothDevice.BOND_BONDED) { 174 // If one device is connected(bonded), then close this fragment. 175 finish(); 176 return; 177 } 178 if (mSelectedDevice != null && cachedDevice != null) { 179 BluetoothDevice device = cachedDevice.getDevice(); 180 if (device != null && mSelectedDevice.equals(device) 181 && bondState == BluetoothDevice.BOND_NONE) { 182 // If currently selected device failed to bond, restart scanning 183 enableScanning(); 184 } 185 } 186 } 187 188 @Override getHelpResource()189 public int getHelpResource() { 190 return R.string.help_url_bluetooth; 191 } 192 193 @Override getLogTag()194 protected String getLogTag() { 195 return TAG; 196 } 197 198 @Override getPreferenceScreenResId()199 protected int getPreferenceScreenResId() { 200 return R.xml.bluetooth_pairing_detail; 201 } 202 203 @Override getDeviceListKey()204 public String getDeviceListKey() { 205 return KEY_AVAIL_DEVICES; 206 } 207 208 } 209