BluetoothDeviceListAdapter.java revision b9104e0e877d1f2334e1cbb1715c7fd320f62345
1843fbc4b10a2c62cb3848836907630f0d56c647eroger xue/* 2843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * Copyright (C) 2017 The Android Open Source Project 3843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * 4843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * Licensed under the Apache License, Version 2.0 (the "License"); 5843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * you may not use this file except in compliance with the License. 6843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * You may obtain a copy of the License at 7843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * 8843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * http://www.apache.org/licenses/LICENSE-2.0 9843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * 10843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * Unless required by applicable law or agreed to in writing, software 11843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * distributed under the License is distributed on an "AS IS" BASIS, 12843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * See the License for the specific language governing permissions and 14843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * limitations under the License. 15843fbc4b10a2c62cb3848836907630f0d56c647eroger xue */ 16843fbc4b10a2c62cb3848836907630f0d56c647eroger xuepackage com.android.car.settings.bluetooth; 17843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 18843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.annotation.NonNull; 19843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.bluetooth.BluetoothAdapter; 20843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.bluetooth.BluetoothClass; 21843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.bluetooth.BluetoothDevice; 22843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.content.Context; 23843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.content.Intent; 24843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.content.res.Resources; 25843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.os.AsyncTask; 26843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.os.Handler; 27843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.os.Looper; 28843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.util.Log; 29843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.util.Pair; 30843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.support.car.ui.PagedListView; 31843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.support.v7.widget.RecyclerView; 32843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.view.LayoutInflater; 33843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.view.View; 34843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.view.View.OnClickListener; 35843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.view.ViewGroup; 36843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.widget.ImageButton; 37843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.widget.ImageView; 38843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.widget.TextView; 39843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport android.widget.Toast; 40843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 41843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.car.settings.R; 42843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.settingslib.bluetooth.BluetoothCallback; 43843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.settingslib.bluetooth.BluetoothDeviceFilter; 44843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.settingslib.bluetooth.CachedBluetoothDevice; 45843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 46843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.settingslib.bluetooth.LocalBluetoothAdapter; 47843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.settingslib.bluetooth.LocalBluetoothManager; 48843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.settingslib.bluetooth.LocalBluetoothProfile; 49843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport com.android.settingslib.bluetooth.HidProfile; 50843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 51843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport java.util.ArrayList; 52843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport java.util.Collection; 53843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport java.util.Collections; 54843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport java.util.HashSet; 55843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport java.util.List; 56843fbc4b10a2c62cb3848836907630f0d56c647eroger xueimport java.util.Set; 57843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 58843fbc4b10a2c62cb3848836907630f0d56c647eroger xue/** 59843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * Renders {@link android.bluetooth.BluetoothDevice} to a view to be displayed as a row in a list. 60843fbc4b10a2c62cb3848836907630f0d56c647eroger xue */ 61843fbc4b10a2c62cb3848836907630f0d56c647eroger xuepublic class BluetoothDeviceListAdapter 62843fbc4b10a2c62cb3848836907630f0d56c647eroger xue extends RecyclerView.Adapter<BluetoothDeviceListAdapter.ViewHolder> 63843fbc4b10a2c62cb3848836907630f0d56c647eroger xue implements PagedListView.ItemCap, BluetoothCallback { 64843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private static final String TAG = "BluetoothDeviceListAdapter"; 65843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private static final int DEVICE_ROW_TYPE = 1; 66843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private static final int BONDED_DEVICE_HEADER_TYPE = 2; 67843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private static final int AVAILABLE_DEVICE_HEADER_TYPE = 3; 68843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private static final int NUM_OF_HEADERS = 2; 69843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public static final int DELAY_MILLIS = 1000; 70843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 71843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final Handler mHandler = new Handler(Looper.getMainLooper()); 72843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final HashSet<CachedBluetoothDevice> mBondedDevices = new HashSet<>(); 73843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final HashSet<CachedBluetoothDevice> mAvailableDevices = new HashSet<>(); 74843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final LocalBluetoothAdapter mLocalAdapter; 75843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final LocalBluetoothManager mLocalManager; 76843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final CachedBluetoothDeviceManager mDeviceManager; 77843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final Context mContext; 78843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 79843fbc4b10a2c62cb3848836907630f0d56c647eroger xue /* Talk-back descriptions for various BT icons */ 80843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public final String mComputerDescription; 81843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public final String mInputPeripheralDescription; 82843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public final String mHeadsetDescription; 83843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public final String mPhoneDescription; 84843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public final String mImagingDescription; 85843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public final String mHeadphoneDescription; 86843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public final String mBluetoothDescription; 87843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 88843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private SortTask mSortTask = new SortTask(); 89843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 90843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private ArrayList<CachedBluetoothDevice> mBondedDevicesSorted = new ArrayList<>(); 91843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private ArrayList<CachedBluetoothDevice> mAvailableDevicesSorted = new ArrayList<>(); 92843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 93843fbc4b10a2c62cb3848836907630f0d56c647eroger xue class ViewHolder extends RecyclerView.ViewHolder { 94843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final ImageView mIcon; 95b9104e0e877d1f2334e1cbb1715c7fd320f62345roger xue private final TextView mTitle; 96843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final TextView mDesc; 97843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final ImageButton mActionButton; 98843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final DeviceAttributeChangeCallback mCallback = 99843fbc4b10a2c62cb3848836907630f0d56c647eroger xue new DeviceAttributeChangeCallback(this); 100843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 101843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public ViewHolder(View view) { 102843fbc4b10a2c62cb3848836907630f0d56c647eroger xue super(view); 103b9104e0e877d1f2334e1cbb1715c7fd320f62345roger xue mTitle = (TextView) view.findViewById(R.id.title); 104843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mDesc = (TextView) view.findViewById(R.id.desc); 105843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mIcon = (ImageView) view.findViewById(R.id.icon); 106843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mActionButton = (ImageButton) view.findViewById(R.id.action); 107843fbc4b10a2c62cb3848836907630f0d56c647eroger xue view.setOnClickListener(new BluetoothClickListener(this)); 108843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 109843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 110843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 111843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public BluetoothDeviceListAdapter( 112843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Context context, LocalBluetoothManager localBluetoothManager) { 113843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mContext = context; 114843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mLocalManager = localBluetoothManager; 115843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mLocalAdapter = mLocalManager.getBluetoothAdapter(); 116843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mDeviceManager = mLocalManager.getCachedDeviceManager(); 117843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 118843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Resources r = context.getResources(); 119843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mComputerDescription = r.getString(R.string.bluetooth_talkback_computer); 120843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mInputPeripheralDescription = r.getString( 121843fbc4b10a2c62cb3848836907630f0d56c647eroger xue R.string.bluetooth_talkback_input_peripheral); 122843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mHeadsetDescription = r.getString(R.string.bluetooth_talkback_headset); 123843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mPhoneDescription = r.getString(R.string.bluetooth_talkback_phone); 124843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mImagingDescription = r.getString(R.string.bluetooth_talkback_imaging); 125843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mHeadphoneDescription = r.getString(R.string.bluetooth_talkback_headphone); 126843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mBluetoothDescription = r.getString(R.string.bluetooth_talkback_bluetooth); 127843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 128843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 129843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void start() { 130843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mLocalManager.getEventManager().registerCallback(this); 131843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (mLocalAdapter.isEnabled()) { 132843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mLocalAdapter.startScanning(true); 133843fbc4b10a2c62cb3848836907630f0d56c647eroger xue addBondDevices(); 134843fbc4b10a2c62cb3848836907630f0d56c647eroger xue addCachedDevices(); 135843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 136843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mSortTask.execute(); 137843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 138843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 139843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void stop() { 140843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mLocalAdapter.stopScanning(); 141843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mDeviceManager.clearNonBondedDevices(); 142843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mLocalManager.getEventManager().unregisterCallback(this); 143843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mBondedDevices.clear(); 144843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mAvailableDevices.clear(); 145843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mSortTask.cancel(true); 146843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 147843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 148843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 149843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public BluetoothDeviceListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, 150843fbc4b10a2c62cb3848836907630f0d56c647eroger xue int viewType) { 151843fbc4b10a2c62cb3848836907630f0d56c647eroger xue View v; 152843fbc4b10a2c62cb3848836907630f0d56c647eroger xue LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); 153843fbc4b10a2c62cb3848836907630f0d56c647eroger xue switch (viewType) { 154843fbc4b10a2c62cb3848836907630f0d56c647eroger xue case BONDED_DEVICE_HEADER_TYPE: 155843fbc4b10a2c62cb3848836907630f0d56c647eroger xue v = layoutInflater.inflate(R.layout.in_list_header, parent, false); 156843fbc4b10a2c62cb3848836907630f0d56c647eroger xue ((TextView) v).setText(R.string.bluetooth_preference_paired_devices); 157843fbc4b10a2c62cb3848836907630f0d56c647eroger xue break; 158843fbc4b10a2c62cb3848836907630f0d56c647eroger xue case AVAILABLE_DEVICE_HEADER_TYPE: 159843fbc4b10a2c62cb3848836907630f0d56c647eroger xue v = layoutInflater.inflate(R.layout.in_list_header, parent, false); 160843fbc4b10a2c62cb3848836907630f0d56c647eroger xue ((TextView) v).setText(R.string.bluetooth_preference_found_devices); 161843fbc4b10a2c62cb3848836907630f0d56c647eroger xue break; 162843fbc4b10a2c62cb3848836907630f0d56c647eroger xue default: 163843fbc4b10a2c62cb3848836907630f0d56c647eroger xue v = layoutInflater.inflate(R.layout.list_item, parent, false); 164843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 165843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new ViewHolder(v); 166843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 167843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 168843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 169843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public int getItemCount() { 170843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return mAvailableDevicesSorted.size() + NUM_OF_HEADERS + mBondedDevicesSorted.size(); 171843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 172843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 173843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 174843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void setMaxItems(int maxItems) { 175843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // no limit in this list. 176843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 177843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 178843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 179843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onBindViewHolder(ViewHolder holder, int position) { 180843fbc4b10a2c62cb3848836907630f0d56c647eroger xue final CachedBluetoothDevice bluetoothDevice = getItem(position); 181843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (bluetoothDevice == null) { 182843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // this row is for in-list headers 183843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return; 184843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 185843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (holder.getOldPosition() != RecyclerView.NO_POSITION) { 186843fbc4b10a2c62cb3848836907630f0d56c647eroger xue getItem(holder.getOldPosition()).unregisterCallback(holder.mCallback); 187843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 188843fbc4b10a2c62cb3848836907630f0d56c647eroger xue bluetoothDevice.registerCallback(holder.mCallback); 189b9104e0e877d1f2334e1cbb1715c7fd320f62345roger xue holder.mTitle.setText(bluetoothDevice.getName()); 190843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Pair<Integer, String> pair = getBtClassDrawableWithDescription(bluetoothDevice); 191843fbc4b10a2c62cb3848836907630f0d56c647eroger xue holder.mIcon.setImageResource(pair.first); 192843fbc4b10a2c62cb3848836907630f0d56c647eroger xue int summaryResourceId = bluetoothDevice.getConnectionSummary(); 193843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (summaryResourceId != 0) { 194843fbc4b10a2c62cb3848836907630f0d56c647eroger xue holder.mDesc.setText(summaryResourceId); 195843fbc4b10a2c62cb3848836907630f0d56c647eroger xue holder.mDesc.setVisibility(View.VISIBLE); 196843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } else { 197843fbc4b10a2c62cb3848836907630f0d56c647eroger xue holder.mDesc.setVisibility(View.GONE); 198843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 199843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (BluetoothDeviceFilter.BONDED_DEVICE_FILTER.matches(bluetoothDevice.getDevice())) { 200843fbc4b10a2c62cb3848836907630f0d56c647eroger xue holder.mActionButton.setVisibility(View.VISIBLE); 201843fbc4b10a2c62cb3848836907630f0d56c647eroger xue holder.mActionButton.setOnClickListener(v -> { 202843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Intent intent = new Intent(mContext, BluetoothDetailActivity.class); 203843fbc4b10a2c62cb3848836907630f0d56c647eroger xue intent.putExtra( 204843fbc4b10a2c62cb3848836907630f0d56c647eroger xue BluetoothDetailActivity.BT_DEVICE_KEY, bluetoothDevice.getDevice()); 205843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mContext.startActivity(intent); 206843fbc4b10a2c62cb3848836907630f0d56c647eroger xue }); 207843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } else { 208843fbc4b10a2c62cb3848836907630f0d56c647eroger xue holder.mActionButton.setVisibility(View.GONE); 209843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 210843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 211843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 212843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 213843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public int getItemViewType(int position) { 214843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // the first row is the header for the bonded device list; 215843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (position == 0) { 216843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return BONDED_DEVICE_HEADER_TYPE; 217843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 218843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // after the end of the bonded device list is the header of the available device list. 219843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (position == mBondedDevicesSorted.size() + 1) { 220843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return AVAILABLE_DEVICE_HEADER_TYPE; 221843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 222843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return DEVICE_ROW_TYPE; 223843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 224843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 225843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private CachedBluetoothDevice getItem(int position) { 226843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (position > 0 && position <= mBondedDevicesSorted.size()) { 227843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // off set the header row 228843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return mBondedDevicesSorted.get(position - 1); 229843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 230843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (position > mBondedDevicesSorted.size() + 1 231843fbc4b10a2c62cb3848836907630f0d56c647eroger xue && position <= mBondedDevicesSorted.size() + 1 + mAvailableDevicesSorted.size()) { 232843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // off set two header row and the size of bonded device list. 233843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return mAvailableDevicesSorted.get( 234843fbc4b10a2c62cb3848836907630f0d56c647eroger xue position - NUM_OF_HEADERS - mBondedDevicesSorted.size()); 235843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 236843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // otherwise it's a in list header 237843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return null; 238843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 239843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 240843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // callback functions 241843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 242843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { 243843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (addDevice(cachedDevice)) { 244843fbc4b10a2c62cb3848836907630f0d56c647eroger xue ArrayList<CachedBluetoothDevice> devices = new ArrayList<>(mBondedDevices); 245843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Collections.sort(devices); 246843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mBondedDevicesSorted = devices; 247843fbc4b10a2c62cb3848836907630f0d56c647eroger xue notifyDataSetChanged(); 248843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 249843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 250843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 251843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 252843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { 253843fbc4b10a2c62cb3848836907630f0d56c647eroger xue onDeviceDeleted(cachedDevice, true /* refresh */); 254843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 255843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 256843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 257843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onBluetoothStateChanged(int bluetoothState) { 258843fbc4b10a2c62cb3848836907630f0d56c647eroger xue switch (bluetoothState) { 259843fbc4b10a2c62cb3848836907630f0d56c647eroger xue case BluetoothAdapter.STATE_OFF: 260843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mBondedDevices.clear(); 261843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mBondedDevicesSorted.clear(); 262843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mAvailableDevices.clear(); 263843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mAvailableDevicesSorted.clear(); 264843fbc4b10a2c62cb3848836907630f0d56c647eroger xue notifyDataSetChanged(); 265843fbc4b10a2c62cb3848836907630f0d56c647eroger xue break; 266843fbc4b10a2c62cb3848836907630f0d56c647eroger xue case BluetoothAdapter.STATE_ON: 267843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mLocalAdapter.startScanning(true); 268843fbc4b10a2c62cb3848836907630f0d56c647eroger xue addBondDevices(); 269843fbc4b10a2c62cb3848836907630f0d56c647eroger xue addCachedDevices(); 270843fbc4b10a2c62cb3848836907630f0d56c647eroger xue break; 271843fbc4b10a2c62cb3848836907630f0d56c647eroger xue default: 272843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 273843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 274843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 275843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 276843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onScanningStateChanged(boolean started) { 277843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // don't care 278843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 279843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 280843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 281843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { 282843fbc4b10a2c62cb3848836907630f0d56c647eroger xue onDeviceDeleted(cachedDevice, false /* refresh */); 283843fbc4b10a2c62cb3848836907630f0d56c647eroger xue onDeviceAdded(cachedDevice); 284843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 285843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 286843fbc4b10a2c62cb3848836907630f0d56c647eroger xue /** 287843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * Call back for the first connection or the last connection to ANY device/profile. Not 288843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * suitable for monitor per device level connection. 289843fbc4b10a2c62cb3848836907630f0d56c647eroger xue */ 290843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 291843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { 292843fbc4b10a2c62cb3848836907630f0d56c647eroger xue onDeviceDeleted(cachedDevice, false); 293843fbc4b10a2c62cb3848836907630f0d56c647eroger xue onDeviceAdded(cachedDevice); 294843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 295843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 296843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private void onDeviceDeleted(CachedBluetoothDevice cachedDevice, boolean refresh) { 297843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // the device might changed bonding state, so need to remove from both sets. 298843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (mBondedDevices.remove(cachedDevice)) { 299843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mBondedDevicesSorted.remove(cachedDevice); 300843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 301843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mAvailableDevices.remove(cachedDevice); 302843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (refresh) { 303843fbc4b10a2c62cb3848836907630f0d56c647eroger xue notifyDataSetChanged(); 304843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 305843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 306843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 307843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private void addDevices(Collection<CachedBluetoothDevice> cachedDevices) { 308843fbc4b10a2c62cb3848836907630f0d56c647eroger xue boolean needSort = false; 309843fbc4b10a2c62cb3848836907630f0d56c647eroger xue for (CachedBluetoothDevice device : cachedDevices) { 310843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (addDevice(device)) { 311843fbc4b10a2c62cb3848836907630f0d56c647eroger xue needSort = true; 312843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 313843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 314843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (needSort) { 315843fbc4b10a2c62cb3848836907630f0d56c647eroger xue ArrayList<CachedBluetoothDevice> devices = 316843fbc4b10a2c62cb3848836907630f0d56c647eroger xue new ArrayList<CachedBluetoothDevice>(mBondedDevices); 317843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Collections.sort(devices); 318843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mBondedDevicesSorted = devices; 319843fbc4b10a2c62cb3848836907630f0d56c647eroger xue notifyDataSetChanged(); 320843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 321843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 322843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 323843fbc4b10a2c62cb3848836907630f0d56c647eroger xue /** 324843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * @return {@code true} if list changed and needed sort again. 325843fbc4b10a2c62cb3848836907630f0d56c647eroger xue */ 326843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private boolean addDevice(CachedBluetoothDevice cachedDevice) { 327843fbc4b10a2c62cb3848836907630f0d56c647eroger xue boolean needSort = false; 328843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (BluetoothDeviceFilter.BONDED_DEVICE_FILTER.matches(cachedDevice.getDevice())) { 329843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (mBondedDevices.add(cachedDevice)) { 330843fbc4b10a2c62cb3848836907630f0d56c647eroger xue needSort = true; 331843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 332843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 333843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER.matches(cachedDevice.getDevice())) { 334843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // refresh is done at SortTask. 335843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mAvailableDevices.add(cachedDevice); 336843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 337843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return needSort; 338843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 339843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 340843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private void addBondDevices() { 341843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices(); 342843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (bondedDevices == null) { 343843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return; 344843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 345843fbc4b10a2c62cb3848836907630f0d56c647eroger xue ArrayList<CachedBluetoothDevice> cachedBluetoothDevices = new ArrayList<>(); 346843fbc4b10a2c62cb3848836907630f0d56c647eroger xue for (BluetoothDevice device : bondedDevices) { 347843fbc4b10a2c62cb3848836907630f0d56c647eroger xue CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 348843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (cachedDevice == null) { 349843fbc4b10a2c62cb3848836907630f0d56c647eroger xue cachedDevice = mDeviceManager.addDevice( 350843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mLocalAdapter, mLocalManager.getProfileManager(), device); 351843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 352843fbc4b10a2c62cb3848836907630f0d56c647eroger xue cachedBluetoothDevices.add(cachedDevice); 353843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 354843fbc4b10a2c62cb3848836907630f0d56c647eroger xue addDevices(cachedBluetoothDevices); 355843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 356843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 357843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private void addCachedDevices() { 358843fbc4b10a2c62cb3848836907630f0d56c647eroger xue addDevices(mDeviceManager.getCachedDevicesCopy()); 359843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 360843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 361843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private Pair<Integer, String> getBtClassDrawableWithDescription( 362843fbc4b10a2c62cb3848836907630f0d56c647eroger xue CachedBluetoothDevice bluetoothDevice) { 363843fbc4b10a2c62cb3848836907630f0d56c647eroger xue BluetoothClass btClass = bluetoothDevice.getBtClass(); 364843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (btClass != null) { 365843fbc4b10a2c62cb3848836907630f0d56c647eroger xue switch (btClass.getMajorDeviceClass()) { 366843fbc4b10a2c62cb3848836907630f0d56c647eroger xue case BluetoothClass.Device.Major.COMPUTER: 367843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new Pair<>(R.drawable.ic_bt_laptop, mComputerDescription); 368843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 369843fbc4b10a2c62cb3848836907630f0d56c647eroger xue case BluetoothClass.Device.Major.PHONE: 370843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new Pair<>(R.drawable.ic_bt_cellphone, mPhoneDescription); 371843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 372843fbc4b10a2c62cb3848836907630f0d56c647eroger xue case BluetoothClass.Device.Major.PERIPHERAL: 373843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new Pair<>(HidProfile.getHidClassDrawable(btClass), 374843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mInputPeripheralDescription); 375843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 376843fbc4b10a2c62cb3848836907630f0d56c647eroger xue case BluetoothClass.Device.Major.IMAGING: 377843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new Pair<>(R.drawable.ic_bt_imaging, mImagingDescription); 378843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 379843fbc4b10a2c62cb3848836907630f0d56c647eroger xue default: 380843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // unrecognized device class; continue 381843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 382843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } else { 383843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Log.w(TAG, "btClass is null"); 384843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 385843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 386843fbc4b10a2c62cb3848836907630f0d56c647eroger xue List<LocalBluetoothProfile> profiles = bluetoothDevice.getProfiles(); 387843fbc4b10a2c62cb3848836907630f0d56c647eroger xue for (LocalBluetoothProfile profile : profiles) { 388843fbc4b10a2c62cb3848836907630f0d56c647eroger xue int resId = profile.getDrawableResource(btClass); 389843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (resId != 0) { 390843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new Pair<Integer, String>(resId, null); 391843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 392843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 393843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (btClass != null) { 394843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) { 395843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new Pair<Integer, String>(R.drawable.ic_bt_headset_hfp, mHeadsetDescription); 396843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 397843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) { 398843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new Pair<Integer, String>(R.drawable.ic_bt_headphones_a2dp, 399843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mHeadphoneDescription); 400843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 401843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 402843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return new Pair<Integer, String>(R.drawable.ic_settings_bluetooth, mBluetoothDescription); 403843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 404843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 405843fbc4b10a2c62cb3848836907630f0d56c647eroger xue /** 406843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * Updates device render upon device attribute change. 407843fbc4b10a2c62cb3848836907630f0d56c647eroger xue */ 408843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // TODO: This is a walk around for handling attribute callback. Since the callback doesn't 409843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // contain the information about which device needs to be updated, we have to maintain a 410843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // local reference to the device. Fix the code in CachedBluetoothDevice.Callback to return 411843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // a reference of the device been updated. 412843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback { 413843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 414843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final ViewHolder mViewHolder; 415843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 416843fbc4b10a2c62cb3848836907630f0d56c647eroger xue DeviceAttributeChangeCallback(ViewHolder viewHolder) { 417843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mViewHolder = viewHolder; 418843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 419843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 420843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 421843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onDeviceAttributesChanged() { 422843fbc4b10a2c62cb3848836907630f0d56c647eroger xue notifyItemChanged(mViewHolder.getAdapterPosition()); 423843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 424843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 425843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 426843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private class BluetoothClickListener implements OnClickListener { 427843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private final ViewHolder mViewHolder; 428843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 429843fbc4b10a2c62cb3848836907630f0d56c647eroger xue BluetoothClickListener(ViewHolder viewHolder) { 430843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mViewHolder = viewHolder; 431843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 432843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 433843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 434843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void onClick(View v) { 435843fbc4b10a2c62cb3848836907630f0d56c647eroger xue CachedBluetoothDevice device = getItem(mViewHolder.getAdapterPosition()); 436843fbc4b10a2c62cb3848836907630f0d56c647eroger xue int bondState = device.getBondState(); 437843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 438843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (device.isConnected()) { 439843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // TODO: ask user for confirmation 440843fbc4b10a2c62cb3848836907630f0d56c647eroger xue device.disconnect(); 441843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } else if (bondState == BluetoothDevice.BOND_BONDED) { 442843fbc4b10a2c62cb3848836907630f0d56c647eroger xue device.connect(true); 443843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } else if (bondState == BluetoothDevice.BOND_NONE) { 444843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (!device.startPairing()) { 445843fbc4b10a2c62cb3848836907630f0d56c647eroger xue showError(device.getName(), 446843fbc4b10a2c62cb3848836907630f0d56c647eroger xue R.string.bluetooth_pairing_error_message); 447843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 448843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 449843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 450843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 451843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 452843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private void showError(String name, int messageResId) { 453843fbc4b10a2c62cb3848836907630f0d56c647eroger xue String message = mContext.getString(messageResId, name); 454843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show(); 455843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 456843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 457843fbc4b10a2c62cb3848836907630f0d56c647eroger xue /** 458843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * Provides an ordered bt device list periodically. 459843fbc4b10a2c62cb3848836907630f0d56c647eroger xue */ 460843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // TODO: improve the way we sort BT devices. Ideally we should keep all devices in a TreeSet 461843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // and as devices are added the correct order is maintained, that requires a consistent 462843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // logic between equals and compareTo function, unfortunately it's not the case in 463843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // CachedBluetoothDevice class. Fix that and improve the way we order devices. 464843fbc4b10a2c62cb3848836907630f0d56c647eroger xue private class SortTask extends AsyncTask<Void, Void, ArrayList<CachedBluetoothDevice>> { 465843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 466843fbc4b10a2c62cb3848836907630f0d56c647eroger xue /** 467843fbc4b10a2c62cb3848836907630f0d56c647eroger xue * Returns {code null} if no changed are made. 468843fbc4b10a2c62cb3848836907630f0d56c647eroger xue */ 469843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 470843fbc4b10a2c62cb3848836907630f0d56c647eroger xue protected ArrayList<CachedBluetoothDevice> doInBackground(Void... v) { 471843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (mAvailableDevicesSorted != null 472843fbc4b10a2c62cb3848836907630f0d56c647eroger xue && mAvailableDevicesSorted.size() == mAvailableDevices.size()) { 473843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return null; 474843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 475843fbc4b10a2c62cb3848836907630f0d56c647eroger xue ArrayList<CachedBluetoothDevice> devices = 476843fbc4b10a2c62cb3848836907630f0d56c647eroger xue new ArrayList<CachedBluetoothDevice>(mAvailableDevices); 477843fbc4b10a2c62cb3848836907630f0d56c647eroger xue Collections.sort(devices); 478843fbc4b10a2c62cb3848836907630f0d56c647eroger xue return devices; 479843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 480843fbc4b10a2c62cb3848836907630f0d56c647eroger xue 481843fbc4b10a2c62cb3848836907630f0d56c647eroger xue @Override 482843fbc4b10a2c62cb3848836907630f0d56c647eroger xue protected void onPostExecute(ArrayList<CachedBluetoothDevice> devices) { 483843fbc4b10a2c62cb3848836907630f0d56c647eroger xue // skip if no changes are made. 484843fbc4b10a2c62cb3848836907630f0d56c647eroger xue if (devices != null) { 485843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mAvailableDevicesSorted = devices; 486843fbc4b10a2c62cb3848836907630f0d56c647eroger xue notifyDataSetChanged(); 487843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 488843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mHandler.postDelayed(new Runnable() { 489843fbc4b10a2c62cb3848836907630f0d56c647eroger xue public void run() { 490843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mSortTask = new SortTask(); 491843fbc4b10a2c62cb3848836907630f0d56c647eroger xue mSortTask.execute(); 492843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 493843fbc4b10a2c62cb3848836907630f0d56c647eroger xue }, DELAY_MILLIS); 494843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 495843fbc4b10a2c62cb3848836907630f0d56c647eroger xue } 496843fbc4b10a2c62cb3848836907630f0d56c647eroger xue} 497