12748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby/*
22748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * Copyright (C) 2011 The Android Open Source Project
32748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby *
42748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * Licensed under the Apache License, Version 2.0 (the "License");
52748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * you may not use this file except in compliance with the License.
62748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * You may obtain a copy of the License at
72748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby *
82748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby *      http://www.apache.org/licenses/LICENSE-2.0
92748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby *
102748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * Unless required by applicable law or agreed to in writing, software
112748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * distributed under the License is distributed on an "AS IS" BASIS,
122748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * See the License for the specific language governing permissions and
142748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * limitations under the License.
152748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby */
162748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
172748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambypackage com.android.settings.bluetooth;
182748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
192748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambyimport android.bluetooth.BluetoothAdapter;
202748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambyimport android.bluetooth.BluetoothDevice;
212748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambyimport android.os.Bundle;
222748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambyimport android.preference.Preference;
232748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambyimport android.preference.PreferenceCategory;
24e78c1879058571c00879f0d3e756951302adf513Gilles Debunneimport android.preference.PreferenceGroup;
252748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambyimport android.preference.PreferenceScreen;
262748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambyimport android.util.Log;
272748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
28fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaardimport com.android.settings.RestrictedSettingsFragment;
292748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
30436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collection;
312748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hambyimport java.util.WeakHashMap;
322748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
332748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby/**
342748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * Parent class for settings fragments that contain a list of Bluetooth
352748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * devices.
362748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby *
372748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * @see BluetoothSettings
382748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby * @see DevicePickerFragment
392748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby */
40436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambypublic abstract class DeviceListPreferenceFragment extends
41fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard        RestrictedSettingsFragment implements BluetoothCallback {
422748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
432748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    private static final String TAG = "DeviceListPreferenceFragment";
442748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
45436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final String KEY_BT_DEVICE_LIST = "bt_device_list";
46436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final String KEY_BT_SCAN = "bt_scan";
472748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
48436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private BluetoothDeviceFilter.Filter mFilter;
492748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
50436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    BluetoothDevice mSelectedDevice;
512748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    LocalBluetoothAdapter mLocalAdapter;
532748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    LocalBluetoothManager mLocalManager;
542748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
55e78c1879058571c00879f0d3e756951302adf513Gilles Debunne    private PreferenceGroup mDeviceListGroup;
562748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
57436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    final WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
582748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            new WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference>();
592748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
60fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard    DeviceListPreferenceFragment(String restrictedKey) {
61fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard        super(restrictedKey);
62436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mFilter = BluetoothDeviceFilter.ALL_FILTER;
63436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
654346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    final void setFilter(BluetoothDeviceFilter.Filter filter) {
66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mFilter = filter;
67436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
68436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
69436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    final void setFilter(int filterType) {
70436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mFilter = BluetoothDeviceFilter.getFilter(filterType);
71436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
722748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
732748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    @Override
74436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    public void onCreate(Bundle savedInstanceState) {
75436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        super.onCreate(savedInstanceState);
762748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mLocalManager = LocalBluetoothManager.getInstance(getActivity());
782748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        if (mLocalManager == null) {
79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            Log.e(TAG, "Bluetooth is not supported on this device");
80436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return;
812748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mLocalAdapter = mLocalManager.getBluetoothAdapter();
832748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        addPreferencesForActivity();
852748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
86e78c1879058571c00879f0d3e756951302adf513Gilles Debunne        mDeviceListGroup = (PreferenceCategory) findPreference(KEY_BT_DEVICE_LIST);
874346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    }
884346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne
894346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    void setDeviceListGroup(PreferenceGroup preferenceGroup) {
904346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne        mDeviceListGroup = preferenceGroup;
912748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
922748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
932748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    /** Add preferences from the subclass. */
94436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    abstract void addPreferencesForActivity();
952748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
962748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    @Override
972748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    public void onResume() {
982748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        super.onResume();
991a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        if (mLocalManager == null || isUiRestricted()) return;
1002748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1012748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        mLocalManager.setForegroundActivity(getActivity());
102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mLocalManager.getEventManager().registerCallback(this);
103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        updateProgressUi(mLocalAdapter.isDiscovering());
1052748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
1062748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1072748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    @Override
1082748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    public void onPause() {
1092748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        super.onPause();
1101a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        if (mLocalManager == null || isUiRestricted()) {
1111a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds            return;
1121a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        }
1135fb53f36cb77c3d924b3fe5c305ce7d082ecdfb8Amith Yamasani
114e78c1879058571c00879f0d3e756951302adf513Gilles Debunne        removeAllDevices();
1152748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        mLocalManager.setForegroundActivity(null);
116436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mLocalManager.getEventManager().unregisterCallback(this);
117e78c1879058571c00879f0d3e756951302adf513Gilles Debunne    }
118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
119e78c1879058571c00879f0d3e756951302adf513Gilles Debunne    void removeAllDevices() {
120e78c1879058571c00879f0d3e756951302adf513Gilles Debunne        mLocalAdapter.stopScanning();
1212748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        mDevicePreferenceMap.clear();
122e78c1879058571c00879f0d3e756951302adf513Gilles Debunne        mDeviceListGroup.removeAll();
1232748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
1242748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1254346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    void addCachedDevices() {
126436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        Collection<CachedBluetoothDevice> cachedDevices =
1272748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby                mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
1282748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        for (CachedBluetoothDevice cachedDevice : cachedDevices) {
1292748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            onDeviceAdded(cachedDevice);
1302748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
1312748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
1322748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1332748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    @Override
1342748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
1352748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            Preference preference) {
1362748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        if (KEY_BT_SCAN.equals(preference.getKey())) {
137436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            mLocalAdapter.startScanning(true);
1382748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            return true;
1392748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
1402748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1412748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        if (preference instanceof BluetoothDevicePreference) {
142e78c1879058571c00879f0d3e756951302adf513Gilles Debunne            BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;
1432748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            CachedBluetoothDevice device = btPreference.getCachedDevice();
1442748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            mSelectedDevice = device.getDevice();
1452748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            onDevicePreferenceClick(btPreference);
1462748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            return true;
1472748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
1482748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1492748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        return super.onPreferenceTreeClick(preferenceScreen, preference);
1502748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
1512748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1522748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
153436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        btPreference.onClicked();
1542748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
1552748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1562748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
1572748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        if (mDevicePreferenceMap.get(cachedDevice) != null) {
1582748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            return;
1592748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
1602748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1614346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne        // Prevent updates while the list shows one of the state messages
162e78c1879058571c00879f0d3e756951302adf513Gilles Debunne        if (mLocalAdapter.getBluetoothState() != BluetoothAdapter.STATE_ON) return;
163e78c1879058571c00879f0d3e756951302adf513Gilles Debunne
164436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (mFilter.matches(cachedDevice.getDevice())) {
1652748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            createDevicePreference(cachedDevice);
1662748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
1672748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby     }
1682748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1692748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    void createDevicePreference(CachedBluetoothDevice cachedDevice) {
170f42a0a27e3b67602f63ab138e78fdefde81a40b6PauloftheWest        if (mDeviceListGroup == null) {
171f42a0a27e3b67602f63ab138e78fdefde81a40b6PauloftheWest            Log.w(TAG, "Trying to create a device preference before the list group/category "
172f42a0a27e3b67602f63ab138e78fdefde81a40b6PauloftheWest                    + "exists!");
173f42a0a27e3b67602f63ab138e78fdefde81a40b6PauloftheWest            return;
174f42a0a27e3b67602f63ab138e78fdefde81a40b6PauloftheWest        }
175f42a0a27e3b67602f63ab138e78fdefde81a40b6PauloftheWest
1762748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        BluetoothDevicePreference preference = new BluetoothDevicePreference(
1772748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby                getActivity(), cachedDevice);
1782748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1792748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        initDevicePreference(preference);
180e78c1879058571c00879f0d3e756951302adf513Gilles Debunne        mDeviceListGroup.addPreference(preference);
1812748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        mDevicePreferenceMap.put(cachedDevice, preference);
1822748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
1832748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1842748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    /**
1852748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby     * Overridden in {@link BluetoothSettings} to add a listener.
1862748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby     * @param preference the newly added preference
1872748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby     */
188e78c1879058571c00879f0d3e756951302adf513Gilles Debunne    void initDevicePreference(BluetoothDevicePreference preference) {
189e78c1879058571c00879f0d3e756951302adf513Gilles Debunne        // Does nothing by default
190e78c1879058571c00879f0d3e756951302adf513Gilles Debunne    }
1912748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1922748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
193e78c1879058571c00879f0d3e756951302adf513Gilles Debunne        BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
1942748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        if (preference != null) {
195e78c1879058571c00879f0d3e756951302adf513Gilles Debunne            mDeviceListGroup.removePreference(preference);
1962748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
1972748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
1982748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
1992748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    public void onScanningStateChanged(boolean started) {
2002748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        updateProgressUi(started);
2012748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
2022748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
2032748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    private void updateProgressUi(boolean start) {
204a17a5b814f1c578df28cd5d444bd8abc3adbbba0Jeff Brown        if (mDeviceListGroup instanceof BluetoothProgressCategory) {
205a17a5b814f1c578df28cd5d444bd8abc3adbbba0Jeff Brown            ((BluetoothProgressCategory) mDeviceListGroup).setProgress(start);
2062748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
2072748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
2082748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby
209436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    public void onBluetoothStateChanged(int bluetoothState) {
2102748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        if (bluetoothState == BluetoothAdapter.STATE_OFF) {
2112748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby            updateProgressUi(false);
2122748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby        }
2132748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby    }
2142748fc24cfeef9a79fc5e29c02a71737def35e6aJake Hamby}
215