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 */ 16package com.android.car.settings.bluetooth; 17 18import android.bluetooth.BluetoothAdapter; 19import android.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.os.Bundle; 24import android.util.Log; 25import android.view.View; 26import android.support.v7.app.AppCompatActivity; 27import android.support.v7.widget.RecyclerView; 28import android.support.v4.widget.SwipeRefreshLayout; 29import android.widget.ProgressBar; 30import android.widget.Switch; 31import android.widget.TextView; 32import android.widget.ViewSwitcher; 33 34import com.android.car.settings.common.BaseFragment; 35import com.android.car.settings.R; 36import com.android.car.view.PagedListView; 37 38import com.android.settingslib.bluetooth.BluetoothCallback; 39import com.android.settingslib.bluetooth.BluetoothDeviceFilter; 40import com.android.settingslib.bluetooth.CachedBluetoothDevice; 41import com.android.settingslib.bluetooth.LocalBluetoothAdapter; 42import com.android.settingslib.bluetooth.LocalBluetoothManager; 43 44/** 45 * Hosts Bluetooth related preferences. 46 */ 47public class BluetoothSettingsFragment extends BaseFragment implements BluetoothCallback { 48 private static final String TAG = "BluetoothSettingsFragment"; 49 50 private SwipeRefreshLayout mSwipeRefreshLayout; 51 private Switch mBluetoothSwitch; 52 private ProgressBar mProgressBar; 53 private PagedListView mDeviceListView; 54 private ViewSwitcher mViewSwitcher; 55 private TextView mMessageView; 56 private BluetoothDeviceListAdapter mDeviceAdapter; 57 private LocalBluetoothAdapter mLocalAdapter; 58 private LocalBluetoothManager mLocalManager; 59 60 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 61 @Override 62 public void onReceive(Context context, Intent intent) { 63 if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) { 64 setProgressBarVisible(true); 65 mBluetoothSwitch.setChecked(true); 66 if (mViewSwitcher.getCurrentView() != mSwipeRefreshLayout) { 67 mViewSwitcher.showPrevious(); 68 } 69 } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) { 70 setProgressBarVisible(false); 71 } 72 } 73 }; 74 75 public static BluetoothSettingsFragment getInstance() { 76 BluetoothSettingsFragment bluetoothSettingsFragment = new BluetoothSettingsFragment(); 77 Bundle bundle = BaseFragment.getBundle(); 78 bundle.putInt(EXTRA_TITLE_ID, R.string.bluetooth_settings); 79 bundle.putInt(EXTRA_LAYOUT, R.layout.bluetooth_list); 80 bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar_with_toggle); 81 bluetoothSettingsFragment.setArguments(bundle); 82 return bluetoothSettingsFragment; 83 } 84 85 @Override 86 public void onActivityCreated(Bundle savedInstanceState) { 87 super.onActivityCreated(savedInstanceState); 88 mBluetoothSwitch = getActivity().findViewById(R.id.toggle_switch); 89 mSwipeRefreshLayout = getActivity().findViewById(R.id.swiperefresh); 90 mSwipeRefreshLayout.setSize(SwipeRefreshLayout.LARGE); 91 mSwipeRefreshLayout.setOnRefreshListener( 92 new SwipeRefreshLayout.OnRefreshListener() { 93 @Override 94 public void onRefresh() { 95 mSwipeRefreshLayout.setRefreshing(false); 96 if (mLocalAdapter.isDiscovering()) { 97 mLocalAdapter.cancelDiscovery(); 98 } 99 mDeviceAdapter.reset(); 100 } 101 } 102 ); 103 104 mBluetoothSwitch.setOnCheckedChangeListener((v, isChecked) -> { 105 if (mBluetoothSwitch.isChecked()) { 106 // bt scan was turned on at state listener, when state is on. 107 mLocalAdapter.setBluetoothEnabled(true); 108 } else { 109 mLocalAdapter.stopScanning(); 110 mLocalAdapter.setBluetoothEnabled(false); 111 } 112 }); 113 114 mProgressBar = getView().findViewById(R.id.bt_search_progress); 115 mDeviceListView = getView().findViewById(R.id.list); 116 mViewSwitcher = getView().findViewById(R.id.view_switcher); 117 mMessageView = getView().findViewById(R.id.bt_message); 118 119 mLocalManager = LocalBluetoothManager.getInstance(getContext(), null /* listener */); 120 if (mLocalManager == null) { 121 Log.e(TAG, "Bluetooth is not supported on this device"); 122 return; 123 } 124 mLocalAdapter = mLocalManager.getBluetoothAdapter(); 125 126 // Set this to light mode, since the scroll bar buttons always appear 127 // on top of a dark scrim. 128 mDeviceListView.setDarkMode(); 129 mDeviceAdapter = new BluetoothDeviceListAdapter( 130 getContext() , mLocalManager, mFragmentController); 131 mDeviceListView.setAdapter(mDeviceAdapter); 132 } 133 134 @Override 135 public void onStart() { 136 super.onStart(); 137 if (mLocalManager == null) { 138 return; 139 } 140 IntentFilter filter = new IntentFilter(); 141 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); 142 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 143 getActivity().registerReceiver(mBroadcastReceiver, filter); 144 145 mLocalManager.setForegroundActivity(getActivity()); 146 mLocalManager.getEventManager().registerCallback(this); 147 mBluetoothSwitch.setChecked(mLocalAdapter.isEnabled()); 148 if (mLocalAdapter.isEnabled()) { 149 setProgressBarVisible(true); 150 mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); 151 mLocalAdapter.startScanning(true); 152 if (mViewSwitcher.getCurrentView() != mSwipeRefreshLayout) { 153 mViewSwitcher.showPrevious(); 154 } 155 } else { 156 setProgressBarVisible(false); 157 if (mViewSwitcher.getCurrentView() != mMessageView) { 158 mViewSwitcher.showNext(); 159 } 160 } 161 mDeviceAdapter.start(); 162 } 163 164 @Override 165 public void onStop() { 166 super.onStop(); 167 if (mLocalManager == null) { 168 return; 169 } 170 getActivity().unregisterReceiver(mBroadcastReceiver); 171 mDeviceAdapter.stop(); 172 mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE); 173 mLocalManager.setForegroundActivity(null); 174 mLocalAdapter.stopScanning(); 175 mLocalManager.getEventManager().unregisterCallback(this); 176 } 177 178 @Override 179 public void onBluetoothStateChanged(int bluetoothState) { 180 switch (bluetoothState) { 181 case BluetoothAdapter.STATE_OFF: 182 setProgressBarVisible(false); 183 mBluetoothSwitch.setChecked(false); 184 if (mViewSwitcher.getCurrentView() != mMessageView) { 185 mViewSwitcher.showNext(); 186 } 187 break; 188 case BluetoothAdapter.STATE_ON: 189 case BluetoothAdapter.STATE_TURNING_ON: 190 setProgressBarVisible(true); 191 mBluetoothSwitch.setChecked(true); 192 if (mViewSwitcher.getCurrentView() != mSwipeRefreshLayout) { 193 mViewSwitcher.showPrevious(); 194 } 195 break; 196 case BluetoothAdapter.STATE_TURNING_OFF: 197 setProgressBarVisible(true); 198 break; 199 } 200 } 201 202 @Override 203 public void onScanningStateChanged(boolean started) { 204 if (!started) { 205 setProgressBarVisible(false); 206 } 207 } 208 209 @Override 210 public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { 211 // no-op 212 } 213 214 @Override 215 public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { 216 // no-op 217 } 218 219 @Override 220 public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { 221 // no-op 222 } 223 224 @Override 225 public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { 226 // no-op 227 } 228 229 private void setProgressBarVisible(boolean visible) { 230 if (mProgressBar != null) { 231 mProgressBar.setVisibility(visible ? View.VISIBLE : View.GONE); 232 } 233 } 234} 235