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
17package com.android.settings.bluetooth;
18
19import android.bluetooth.BluetoothAdapter;
20import android.bluetooth.BluetoothDevice;
21import android.os.Bundle;
22import android.preference.Preference;
23import android.preference.PreferenceCategory;
24import android.preference.PreferenceGroup;
25import android.preference.PreferenceScreen;
26import android.util.Log;
27
28import com.android.settings.ProgressCategory;
29import com.android.settings.SettingsPreferenceFragment;
30
31import java.util.Collection;
32import java.util.WeakHashMap;
33
34/**
35 * Parent class for settings fragments that contain a list of Bluetooth
36 * devices.
37 *
38 * @see BluetoothSettings
39 * @see DevicePickerFragment
40 */
41public abstract class DeviceListPreferenceFragment extends
42        SettingsPreferenceFragment implements BluetoothCallback {
43
44    private static final String TAG = "DeviceListPreferenceFragment";
45
46    private static final String KEY_BT_DEVICE_LIST = "bt_device_list";
47    private static final String KEY_BT_SCAN = "bt_scan";
48
49    private BluetoothDeviceFilter.Filter mFilter;
50
51    BluetoothDevice mSelectedDevice;
52
53    LocalBluetoothAdapter mLocalAdapter;
54    LocalBluetoothManager mLocalManager;
55
56    private PreferenceGroup mDeviceListGroup;
57
58    final WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
59            new WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference>();
60
61    DeviceListPreferenceFragment() {
62        mFilter = BluetoothDeviceFilter.ALL_FILTER;
63    }
64
65    final void setFilter(BluetoothDeviceFilter.Filter filter) {
66        mFilter = filter;
67    }
68
69    final void setFilter(int filterType) {
70        mFilter = BluetoothDeviceFilter.getFilter(filterType);
71    }
72
73    @Override
74    public void onCreate(Bundle savedInstanceState) {
75        super.onCreate(savedInstanceState);
76
77        mLocalManager = LocalBluetoothManager.getInstance(getActivity());
78        if (mLocalManager == null) {
79            Log.e(TAG, "Bluetooth is not supported on this device");
80            return;
81        }
82        mLocalAdapter = mLocalManager.getBluetoothAdapter();
83
84        addPreferencesForActivity();
85
86        mDeviceListGroup = (PreferenceCategory) findPreference(KEY_BT_DEVICE_LIST);
87    }
88
89    void setDeviceListGroup(PreferenceGroup preferenceGroup) {
90        mDeviceListGroup = preferenceGroup;
91    }
92
93    /** Add preferences from the subclass. */
94    abstract void addPreferencesForActivity();
95
96    @Override
97    public void onResume() {
98        super.onResume();
99
100        mLocalManager.setForegroundActivity(getActivity());
101        mLocalManager.getEventManager().registerCallback(this);
102
103        updateProgressUi(mLocalAdapter.isDiscovering());
104    }
105
106    @Override
107    public void onPause() {
108        super.onPause();
109        removeAllDevices();
110        mLocalManager.setForegroundActivity(null);
111        mLocalManager.getEventManager().unregisterCallback(this);
112    }
113
114    void removeAllDevices() {
115        mLocalAdapter.stopScanning();
116        mDevicePreferenceMap.clear();
117        mDeviceListGroup.removeAll();
118    }
119
120    void addCachedDevices() {
121        Collection<CachedBluetoothDevice> cachedDevices =
122                mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
123        for (CachedBluetoothDevice cachedDevice : cachedDevices) {
124            onDeviceAdded(cachedDevice);
125        }
126    }
127
128    @Override
129    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
130            Preference preference) {
131        if (KEY_BT_SCAN.equals(preference.getKey())) {
132            mLocalAdapter.startScanning(true);
133            return true;
134        }
135
136        if (preference instanceof BluetoothDevicePreference) {
137            BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;
138            CachedBluetoothDevice device = btPreference.getCachedDevice();
139            mSelectedDevice = device.getDevice();
140            onDevicePreferenceClick(btPreference);
141            return true;
142        }
143
144        return super.onPreferenceTreeClick(preferenceScreen, preference);
145    }
146
147    void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
148        btPreference.onClicked();
149    }
150
151    public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
152        if (mDevicePreferenceMap.get(cachedDevice) != null) {
153            return;
154        }
155
156        // Prevent updates while the list shows one of the state messages
157        if (mLocalAdapter.getBluetoothState() != BluetoothAdapter.STATE_ON) return;
158
159        if (mFilter.matches(cachedDevice.getDevice())) {
160            createDevicePreference(cachedDevice);
161        }
162     }
163
164    void createDevicePreference(CachedBluetoothDevice cachedDevice) {
165        BluetoothDevicePreference preference = new BluetoothDevicePreference(
166                getActivity(), cachedDevice);
167
168        initDevicePreference(preference);
169        mDeviceListGroup.addPreference(preference);
170        mDevicePreferenceMap.put(cachedDevice, preference);
171    }
172
173    /**
174     * Overridden in {@link BluetoothSettings} to add a listener.
175     * @param preference the newly added preference
176     */
177    void initDevicePreference(BluetoothDevicePreference preference) {
178        // Does nothing by default
179    }
180
181    public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
182        BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
183        if (preference != null) {
184            mDeviceListGroup.removePreference(preference);
185        }
186    }
187
188    public void onScanningStateChanged(boolean started) {
189        updateProgressUi(started);
190    }
191
192    private void updateProgressUi(boolean start) {
193        if (mDeviceListGroup instanceof ProgressCategory) {
194            ((ProgressCategory) mDeviceListGroup).setProgress(start);
195        }
196    }
197
198    public void onBluetoothStateChanged(int bluetoothState) {
199        if (bluetoothState == BluetoothAdapter.STATE_OFF) {
200            updateProgressUi(false);
201        }
202    }
203}
204