Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2011 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 android.app.Activity;
     20 import android.bluetooth.BluetoothAdapter;
     21 import android.bluetooth.BluetoothDevice;
     22 import android.content.BroadcastReceiver;
     23 import android.content.ContentResolver;
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.content.IntentFilter;
     27 import android.content.res.Resources;
     28 import android.os.Bundle;
     29 import android.provider.Settings;
     30 import android.support.annotation.VisibleForTesting;
     31 import android.support.v7.preference.PreferenceCategory;
     32 import android.support.v7.preference.PreferenceGroup;
     33 import android.support.v7.preference.PreferenceScreen;
     34 import android.text.BidiFormatter;
     35 import android.text.Spannable;
     36 import android.text.style.TextAppearanceSpan;
     37 import android.util.Log;
     38 import android.view.Menu;
     39 import android.view.MenuInflater;
     40 import android.view.MenuItem;
     41 import android.view.View;
     42 import android.widget.TextView;
     43 
     44 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     45 import com.android.settings.LinkifyUtils;
     46 import com.android.settings.R;
     47 import com.android.settings.SettingsActivity;
     48 import com.android.settings.dashboard.SummaryLoader;
     49 import com.android.settings.location.ScanningSettings;
     50 import com.android.settings.search.BaseSearchIndexProvider;
     51 import com.android.settings.search.Indexable;
     52 import com.android.settings.search.SearchIndexableRaw;
     53 import com.android.settings.widget.FooterPreference;
     54 import com.android.settings.widget.GearPreference;
     55 import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener;
     56 import com.android.settings.widget.SwitchBar;
     57 import com.android.settings.widget.SwitchBarController;
     58 import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
     59 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
     60 import com.android.settingslib.bluetooth.LocalBluetoothManager;
     61 
     62 import java.util.ArrayList;
     63 import java.util.List;
     64 import java.util.Locale;
     65 import java.util.Set;
     66 
     67 import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
     68 
     69 /**
     70  * BluetoothSettings is the Settings screen for Bluetooth configuration and
     71  * connection management.
     72  */
     73 public final class BluetoothSettings extends DeviceListPreferenceFragment implements Indexable {
     74     private static final String TAG = "BluetoothSettings";
     75 
     76     private static final int MENU_ID_SCAN = Menu.FIRST;
     77     private static final int MENU_ID_RENAME_DEVICE = Menu.FIRST + 1;
     78     private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 2;
     79 
     80     /* Private intent to show the list of received files */
     81     private static final String BTOPP_ACTION_OPEN_RECEIVED_FILES =
     82             "android.btopp.intent.action.OPEN_RECEIVED_FILES";
     83     private static final String BTOPP_PACKAGE =
     84             "com.android.bluetooth";
     85 
     86     private static final String KEY_PAIRED_DEVICES = "paired_devices";
     87 
     88     private static View mSettingsDialogView = null;
     89 
     90     private BluetoothEnabler mBluetoothEnabler;
     91 
     92     private PreferenceGroup mPairedDevicesCategory;
     93     private PreferenceGroup mAvailableDevicesCategory;
     94     private boolean mAvailableDevicesCategoryIsPresent;
     95 
     96     private boolean mInitialScanStarted;
     97     private boolean mInitiateDiscoverable;
     98 
     99     private SwitchBar mSwitchBar;
    100 
    101     private final IntentFilter mIntentFilter;
    102 
    103     // For Search
    104     private static final String DATA_KEY_REFERENCE = "main_toggle_bluetooth";
    105 
    106     // accessed from inner class (not private to avoid thunks)
    107     FooterPreference mMyDevicePreference;
    108 
    109     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    110         @Override
    111         public void onReceive(Context context, Intent intent) {
    112             final String action = intent.getAction();
    113             final int state =
    114                     intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
    115 
    116             if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
    117                 updateDeviceName(context);
    118             }
    119 
    120             if (state == BluetoothAdapter.STATE_ON) {
    121                 mInitiateDiscoverable = true;
    122             }
    123         }
    124 
    125         private void updateDeviceName(Context context) {
    126             if (mLocalAdapter.isEnabled() && mMyDevicePreference != null) {
    127                 final Resources res = context.getResources();
    128                 final Locale locale = res.getConfiguration().getLocales().get(0);
    129                 final BidiFormatter bidiFormatter = BidiFormatter.getInstance(locale);
    130                 mMyDevicePreference.setTitle(res.getString(
    131                         R.string.bluetooth_is_visible_message,
    132                         bidiFormatter.unicodeWrap(mLocalAdapter.getName())));
    133             }
    134         }
    135     };
    136 
    137     public BluetoothSettings() {
    138         super(DISALLOW_CONFIG_BLUETOOTH);
    139         mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
    140     }
    141 
    142     @Override
    143     public int getMetricsCategory() {
    144         return MetricsEvent.BLUETOOTH;
    145     }
    146 
    147     @Override
    148     public void onActivityCreated(Bundle savedInstanceState) {
    149         super.onActivityCreated(savedInstanceState);
    150         mInitialScanStarted = false;
    151         mInitiateDiscoverable = true;
    152 
    153         final SettingsActivity activity = (SettingsActivity) getActivity();
    154         mSwitchBar = activity.getSwitchBar();
    155 
    156         mBluetoothEnabler = new BluetoothEnabler(activity, new SwitchBarController(mSwitchBar),
    157             mMetricsFeatureProvider, Utils.getLocalBtManager(activity),
    158             MetricsEvent.ACTION_BLUETOOTH_TOGGLE);
    159         mBluetoothEnabler.setupSwitchController();
    160     }
    161 
    162     @Override
    163     public void onDestroyView() {
    164         super.onDestroyView();
    165 
    166         mBluetoothEnabler.teardownSwitchController();
    167     }
    168 
    169     @Override
    170     void addPreferencesForActivity() {
    171         addPreferencesFromResource(R.xml.bluetooth_settings);
    172         final Context prefContext = getPrefContext();
    173         mPairedDevicesCategory = new PreferenceCategory(prefContext);
    174         mPairedDevicesCategory.setKey(KEY_PAIRED_DEVICES);
    175         mPairedDevicesCategory.setOrder(1);
    176         getPreferenceScreen().addPreference(mPairedDevicesCategory);
    177 
    178         mAvailableDevicesCategory = new BluetoothProgressCategory(prefContext);
    179         mAvailableDevicesCategory.setSelectable(false);
    180         mAvailableDevicesCategory.setOrder(2);
    181         getPreferenceScreen().addPreference(mAvailableDevicesCategory);
    182 
    183         mMyDevicePreference = mFooterPreferenceMixin.createFooterPreference();
    184         mMyDevicePreference.setSelectable(false);
    185 
    186         setHasOptionsMenu(true);
    187     }
    188 
    189     @Override
    190     public void onStart() {
    191         // resume BluetoothEnabler before calling super.onStart() so we don't get
    192         // any onDeviceAdded() callbacks before setting up view in updateContent()
    193         if (mBluetoothEnabler != null) {
    194             mBluetoothEnabler.resume(getActivity());
    195         }
    196         super.onStart();
    197 
    198         mInitiateDiscoverable = true;
    199 
    200         if (isUiRestricted()) {
    201             setDeviceListGroup(getPreferenceScreen());
    202             if (!isUiRestrictedByOnlyAdmin()) {
    203                 getEmptyTextView().setText(R.string.bluetooth_empty_list_user_restricted);
    204             }
    205             removeAllDevices();
    206             return;
    207         }
    208 
    209         getActivity().registerReceiver(mReceiver, mIntentFilter);
    210         if (mLocalAdapter != null) {
    211             updateContent(mLocalAdapter.getBluetoothState());
    212         }
    213     }
    214 
    215     @Override
    216     public void onStop() {
    217         super.onStop();
    218         if (mBluetoothEnabler != null) {
    219             mBluetoothEnabler.pause();
    220         }
    221 
    222         // Make the device only visible to connected devices.
    223         mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
    224 
    225         if (isUiRestricted()) {
    226             return;
    227         }
    228 
    229         getActivity().unregisterReceiver(mReceiver);
    230     }
    231 
    232     @Override
    233     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    234         if (mLocalAdapter == null) return;
    235         // If the user is not allowed to configure bluetooth, do not show the menu.
    236         if (isUiRestricted()) return;
    237 
    238         boolean bluetoothIsEnabled = mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON;
    239         boolean isDiscovering = mLocalAdapter.isDiscovering();
    240         int textId = isDiscovering ? R.string.bluetooth_searching_for_devices :
    241                 R.string.bluetooth_search_for_devices;
    242         menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
    243                 .setEnabled(bluetoothIsEnabled && !isDiscovering)
    244                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
    245         menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
    246                 .setEnabled(bluetoothIsEnabled)
    247                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
    248         menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
    249                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
    250         super.onCreateOptionsMenu(menu, inflater);
    251     }
    252 
    253     @Override
    254     public boolean onOptionsItemSelected(MenuItem item) {
    255         switch (item.getItemId()) {
    256             case MENU_ID_SCAN:
    257                 if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {
    258                     mMetricsFeatureProvider.action(getActivity(),
    259                             MetricsEvent.ACTION_BLUETOOTH_SCAN);
    260                     startScanning();
    261                 }
    262                 return true;
    263 
    264             case MENU_ID_RENAME_DEVICE:
    265                 mMetricsFeatureProvider.action(getActivity(),
    266                         MetricsEvent.ACTION_BLUETOOTH_RENAME);
    267                 new BluetoothNameDialogFragment().show(
    268                         getFragmentManager(), "rename device");
    269                 return true;
    270 
    271             case MENU_ID_SHOW_RECEIVED:
    272                 mMetricsFeatureProvider.action(getActivity(),
    273                         MetricsEvent.ACTION_BLUETOOTH_FILES);
    274                 Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
    275                 intent.setPackage(BTOPP_PACKAGE);
    276                 getActivity().sendBroadcast(intent);
    277                 return true;
    278         }
    279         return super.onOptionsItemSelected(item);
    280     }
    281 
    282     private void startScanning() {
    283         if (isUiRestricted()) {
    284             return;
    285         }
    286 
    287         if (!mAvailableDevicesCategoryIsPresent) {
    288             getPreferenceScreen().addPreference(mAvailableDevicesCategory);
    289             mAvailableDevicesCategoryIsPresent = true;
    290         }
    291 
    292         if (mAvailableDevicesCategory != null) {
    293             setDeviceListGroup(mAvailableDevicesCategory);
    294             removeAllDevices();
    295         }
    296 
    297         mLocalManager.getCachedDeviceManager().clearNonBondedDevices();
    298         mAvailableDevicesCategory.removeAll();
    299         mInitialScanStarted = true;
    300         mLocalAdapter.startScanning(true);
    301     }
    302 
    303     @Override
    304     void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
    305         mLocalAdapter.stopScanning();
    306         super.onDevicePreferenceClick(btPreference);
    307     }
    308 
    309     private void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
    310             BluetoothDeviceFilter.Filter filter, boolean addCachedDevices) {
    311         cacheRemoveAllPrefs(preferenceGroup);
    312         preferenceGroup.setTitle(titleId);
    313         setFilter(filter);
    314         setDeviceListGroup(preferenceGroup);
    315         if (addCachedDevices) {
    316             addCachedDevices();
    317         }
    318         preferenceGroup.setEnabled(true);
    319         removeCachedPrefs(preferenceGroup);
    320     }
    321 
    322     private void updateContent(int bluetoothState) {
    323         final PreferenceScreen preferenceScreen = getPreferenceScreen();
    324         int messageId = 0;
    325 
    326         switch (bluetoothState) {
    327             case BluetoothAdapter.STATE_ON:
    328                 mDevicePreferenceMap.clear();
    329 
    330                 if (isUiRestricted()) {
    331                     messageId = R.string.bluetooth_empty_list_user_restricted;
    332                     break;
    333                 }
    334                 getPreferenceScreen().removeAll();
    335                 getPreferenceScreen().addPreference(mPairedDevicesCategory);
    336                 getPreferenceScreen().addPreference(mAvailableDevicesCategory);
    337                 getPreferenceScreen().addPreference(mMyDevicePreference);
    338 
    339                 // Paired devices category
    340                 addDeviceCategory(mPairedDevicesCategory,
    341                         R.string.bluetooth_preference_paired_devices,
    342                         BluetoothDeviceFilter.BONDED_DEVICE_FILTER, true);
    343                 int numberOfPairedDevices = mPairedDevicesCategory.getPreferenceCount();
    344 
    345                 if (isUiRestricted() || numberOfPairedDevices <= 0) {
    346                     if (preferenceScreen.findPreference(KEY_PAIRED_DEVICES) != null) {
    347                         preferenceScreen.removePreference(mPairedDevicesCategory);
    348                     }
    349                 } else {
    350                     if (preferenceScreen.findPreference(KEY_PAIRED_DEVICES) == null) {
    351                         preferenceScreen.addPreference(mPairedDevicesCategory);
    352                     }
    353                 }
    354 
    355                 // Available devices category
    356                 addDeviceCategory(mAvailableDevicesCategory,
    357                         R.string.bluetooth_preference_found_devices,
    358                         BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER, mInitialScanStarted);
    359 
    360                 if (!mInitialScanStarted) {
    361                     startScanning();
    362                 }
    363 
    364                 final Resources res = getResources();
    365                 final Locale locale = res.getConfiguration().getLocales().get(0);
    366                 final BidiFormatter bidiFormatter = BidiFormatter.getInstance(locale);
    367                 mMyDevicePreference.setTitle(res.getString(
    368                         R.string.bluetooth_is_visible_message,
    369                         bidiFormatter.unicodeWrap(mLocalAdapter.getName())));
    370 
    371                 getActivity().invalidateOptionsMenu();
    372 
    373                 // mLocalAdapter.setScanMode is internally synchronized so it is okay for multiple
    374                 // threads to execute.
    375                 if (mInitiateDiscoverable) {
    376                     // Make the device visible to other devices.
    377                     mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
    378                     mInitiateDiscoverable = false;
    379                 }
    380                 return; // not break
    381 
    382             case BluetoothAdapter.STATE_TURNING_OFF:
    383                 messageId = R.string.bluetooth_turning_off;
    384                 break;
    385 
    386             case BluetoothAdapter.STATE_OFF:
    387                 setOffMessage();
    388                 if (isUiRestricted()) {
    389                     messageId = R.string.bluetooth_empty_list_user_restricted;
    390                 }
    391                 break;
    392 
    393             case BluetoothAdapter.STATE_TURNING_ON:
    394                 messageId = R.string.bluetooth_turning_on;
    395                 mInitialScanStarted = false;
    396                 break;
    397         }
    398 
    399         setDeviceListGroup(preferenceScreen);
    400         removeAllDevices();
    401         if (messageId != 0) {
    402             getEmptyTextView().setText(messageId);
    403         }
    404         if (!isUiRestricted()) {
    405             getActivity().invalidateOptionsMenu();
    406         }
    407     }
    408 
    409     private void setOffMessage() {
    410         final TextView emptyView = getEmptyTextView();
    411         if (emptyView == null) {
    412             return;
    413         }
    414         final CharSequence briefText = getText(R.string.bluetooth_empty_list_bluetooth_off);
    415 
    416         final ContentResolver resolver = getActivity().getContentResolver();
    417         final boolean bleScanningMode = Settings.Global.getInt(
    418                 resolver, Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
    419 
    420         if (!bleScanningMode) {
    421             // Show only the brief text if the scanning mode has been turned off.
    422             emptyView.setText(briefText, TextView.BufferType.SPANNABLE);
    423         } else {
    424             final StringBuilder contentBuilder = new StringBuilder();
    425             contentBuilder.append(briefText);
    426             contentBuilder.append("\n\n");
    427             contentBuilder.append(getText(R.string.ble_scan_notify_text));
    428             LinkifyUtils.linkify(emptyView, contentBuilder, new LinkifyUtils.OnClickListener() {
    429                 @Override
    430                 public void onClick() {
    431                     final SettingsActivity activity =
    432                             (SettingsActivity) BluetoothSettings.this.getActivity();
    433                     activity.startPreferencePanel(BluetoothSettings.this,
    434                             ScanningSettings.class.getName(), null,
    435                             R.string.location_scanning_screen_title, null, null, 0);
    436                 }
    437             });
    438         }
    439         getPreferenceScreen().removeAll();
    440         setTextSpan(emptyView.getText(), briefText);
    441     }
    442 
    443     @Override
    444     public void onBluetoothStateChanged(int bluetoothState) {
    445         super.onBluetoothStateChanged(bluetoothState);
    446         // If BT is turned off/on staying in the same BT Settings screen
    447         // discoverability to be set again
    448         if (BluetoothAdapter.STATE_ON == bluetoothState) {
    449             mInitiateDiscoverable = true;
    450         }
    451         updateContent(bluetoothState);
    452     }
    453 
    454     @Override
    455     public void onScanningStateChanged(boolean started) {
    456         super.onScanningStateChanged(started);
    457         // Update options' enabled state
    458         if (getActivity() != null) {
    459             getActivity().invalidateOptionsMenu();
    460         }
    461     }
    462 
    463     @Override
    464     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
    465         setDeviceListGroup(getPreferenceScreen());
    466         removeAllDevices();
    467         updateContent(mLocalAdapter.getBluetoothState());
    468     }
    469 
    470     @VisibleForTesting
    471     void setTextSpan(CharSequence text, CharSequence briefText) {
    472         if (text instanceof Spannable) {
    473             Spannable boldSpan = (Spannable) text;
    474             boldSpan.setSpan(
    475                 new TextAppearanceSpan(getActivity(), android.R.style.TextAppearance_Medium), 0,
    476                 briefText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    477         }
    478     }
    479 
    480     private final GearPreference.OnGearClickListener mDeviceProfilesListener = pref -> {
    481         // User clicked on advanced options icon for a device in the list
    482         if (!(pref instanceof BluetoothDevicePreference)) {
    483             Log.w(TAG, "onClick() called for other View: " + pref);
    484             return;
    485         }
    486         final CachedBluetoothDevice device =
    487                 ((BluetoothDevicePreference) pref).getBluetoothDevice();
    488         if (device == null) {
    489             Log.w(TAG, "No BT device attached with this pref: " + pref);
    490             return;
    491         }
    492         final Bundle args = new Bundle();
    493         args.putString(DeviceProfilesSettings.ARG_DEVICE_ADDRESS,
    494                 device.getDevice().getAddress());
    495         final DeviceProfilesSettings profileSettings = new DeviceProfilesSettings();
    496         profileSettings.setArguments(args);
    497         profileSettings.show(getFragmentManager(),
    498                 DeviceProfilesSettings.class.getSimpleName());
    499     };
    500 
    501     /**
    502      * Add a listener, which enables the advanced settings icon.
    503      *
    504      * @param preference the newly added preference
    505      */
    506     @Override
    507     void initDevicePreference(BluetoothDevicePreference preference) {
    508         CachedBluetoothDevice cachedDevice = preference.getCachedDevice();
    509         if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
    510             // Only paired device have an associated advanced settings screen
    511             preference.setOnGearClickListener(mDeviceProfilesListener);
    512         }
    513     }
    514 
    515     @Override
    516     protected int getHelpResource() {
    517         return R.string.help_url_bluetooth;
    518     }
    519 
    520     @VisibleForTesting
    521     static class SummaryProvider implements SummaryLoader.SummaryProvider, OnSummaryChangeListener {
    522 
    523         private final LocalBluetoothManager mBluetoothManager;
    524         private final Context mContext;
    525         private final SummaryLoader mSummaryLoader;
    526 
    527         @VisibleForTesting
    528         BluetoothSummaryUpdater mSummaryUpdater;
    529 
    530         public SummaryProvider(Context context, SummaryLoader summaryLoader,
    531                 LocalBluetoothManager bluetoothManager) {
    532             mBluetoothManager = bluetoothManager;
    533             mContext = context;
    534             mSummaryLoader = summaryLoader;
    535             mSummaryUpdater = new BluetoothSummaryUpdater(mContext, this, mBluetoothManager);
    536         }
    537 
    538         @Override
    539         public void setListening(boolean listening) {
    540             mSummaryUpdater.register(listening);
    541         }
    542 
    543         @Override
    544         public void onSummaryChanged(String summary) {
    545             if (mSummaryLoader != null) {
    546                 mSummaryLoader.setSummary(this, summary);
    547             }
    548         }
    549     }
    550 
    551     public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
    552             = new SummaryLoader.SummaryProviderFactory() {
    553         @Override
    554         public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
    555                 SummaryLoader summaryLoader) {
    556 
    557             return new SummaryProvider(activity, summaryLoader, Utils.getLocalBtManager(activity));
    558         }
    559     };
    560 
    561     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
    562             new BaseSearchIndexProvider() {
    563                 @Override
    564                 public List<SearchIndexableRaw> getRawDataToIndex(Context context,
    565                         boolean enabled) {
    566 
    567                     final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
    568 
    569                     final Resources res = context.getResources();
    570 
    571                     // Add fragment title
    572                     SearchIndexableRaw data = new SearchIndexableRaw(context);
    573                     data.title = res.getString(R.string.bluetooth_settings);
    574                     data.screenTitle = res.getString(R.string.bluetooth_settings);
    575                     data.key = DATA_KEY_REFERENCE;
    576                     result.add(data);
    577 
    578                     // Add cached paired BT devices
    579                     LocalBluetoothManager lbtm = Utils.getLocalBtManager(context);
    580                     // LocalBluetoothManager.getInstance can return null if the device does not
    581                     // support bluetooth (e.g. the emulator).
    582                     if (lbtm != null) {
    583                         Set<BluetoothDevice> bondedDevices =
    584                                 lbtm.getBluetoothAdapter().getBondedDevices();
    585 
    586                         for (BluetoothDevice device : bondedDevices) {
    587                             data = new SearchIndexableRaw(context);
    588                             data.title = device.getName();
    589                             data.screenTitle = res.getString(R.string.bluetooth_settings);
    590                             data.enabled = enabled;
    591                             result.add(data);
    592                         }
    593                     }
    594                     return result;
    595                 }
    596             };
    597 }
    598