OSDN Git Service

am 84c8c175: Import revised translations. DO NOT MERGE
[android-x86/packages-apps-Settings.git] / src / com / android / settings / bluetooth / BluetoothSettings.java
1 /*
2  * Copyright (C) 2008 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 com.android.settings.ProgressCategory;
20 import com.android.settings.R;
21
22 import android.bluetooth.BluetoothAdapter;
23 import android.bluetooth.BluetoothClass;
24 import android.bluetooth.BluetoothDevice;
25 import android.bluetooth.BluetoothDevicePicker;
26 import android.bluetooth.BluetoothUuid;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.os.Bundle;
32 import android.os.ParcelUuid;
33 import android.preference.CheckBoxPreference;
34 import android.preference.Preference;
35 import android.preference.PreferenceActivity;
36 import android.preference.PreferenceScreen;
37 import android.view.ContextMenu;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.view.ContextMenu.ContextMenuInfo;
41 import android.widget.AdapterView.AdapterContextMenuInfo;
42
43 import java.util.List;
44 import java.util.WeakHashMap;
45
46 /**
47  * BluetoothSettings is the Settings screen for Bluetooth configuration and
48  * connection management.
49  */
50 public class BluetoothSettings extends PreferenceActivity
51         implements LocalBluetoothManager.Callback {
52
53     private static final String TAG = "BluetoothSettings";
54
55     private static final String KEY_BT_CHECKBOX = "bt_checkbox";
56     private static final String KEY_BT_DISCOVERABLE = "bt_discoverable";
57     private static final String KEY_BT_DEVICE_LIST = "bt_device_list";
58     private static final String KEY_BT_NAME = "bt_name";
59     private static final String KEY_BT_SCAN = "bt_scan";
60
61     private static final int SCREEN_TYPE_SETTINGS = 0;
62     private static final int SCREEN_TYPE_DEVICEPICKER = 1;
63
64     private int mScreenType;
65     private int mFilterType;
66     private boolean mNeedAuth;
67     private String mLaunchPackage;
68     private String mLaunchClass;
69
70     private BluetoothDevice mSelectedDevice= null;
71
72     private LocalBluetoothManager mLocalManager;
73
74     private BluetoothEnabler mEnabler;
75     private BluetoothDiscoverableEnabler mDiscoverableEnabler;
76
77     private BluetoothNamePreference mNamePreference;
78
79     private ProgressCategory mDeviceList;
80
81     private WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
82             new WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference>();
83
84     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
85         @Override
86         public void onReceive(Context context, Intent intent) {
87             // TODO: put this in callback instead of receiving
88
89             if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
90                 onBluetoothStateChanged(mLocalManager.getBluetoothState());
91             } else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
92                     && mScreenType == SCREEN_TYPE_DEVICEPICKER) {
93                 int bondState = intent
94                         .getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
95                 if (bondState == BluetoothDevice.BOND_BONDED) {
96                     BluetoothDevice device = intent
97                             .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
98                     if (device.equals(mSelectedDevice)) {
99                         sendDevicePickedIntent(device);
100                         finish();
101                     }
102                 }
103             }
104         }
105     };
106
107     @Override
108     protected void onCreate(Bundle savedInstanceState) {
109         super.onCreate(savedInstanceState);
110
111         mLocalManager = LocalBluetoothManager.getInstance(this);
112         if (mLocalManager == null) finish();
113
114         // Note:
115         // If an application wish to show the BT device list, it can send an
116         // intent to Settings application with below extra data:
117         // -DEVICE_PICKER_FILTER_TYPE: the type of BT devices that want to show.
118         // -DEVICE_PICKER_LAUNCH_PACKAGE: the package which the application belongs to.
119         // -DEVICE_PICKER_LAUNCH_CLASS: the class which will receive user's selected
120         // result from the BT list.
121         // -DEVICE_PICKER_NEED_AUTH: to show if bonding procedure needed.
122
123         mFilterType = BluetoothDevicePicker.FILTER_TYPE_ALL;
124         Intent intent = getIntent();
125         String action = intent.getAction();
126
127         if (action.equals(BluetoothDevicePicker.ACTION_LAUNCH)) {
128             mScreenType = SCREEN_TYPE_DEVICEPICKER;
129             mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
130             mFilterType = intent.getIntExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
131                     BluetoothDevicePicker.FILTER_TYPE_ALL);
132             mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE);
133             mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS);
134
135             setTitle(getString(R.string.device_picker));
136             addPreferencesFromResource(R.xml.device_picker);
137         } else {
138             addPreferencesFromResource(R.xml.bluetooth_settings);
139
140             mEnabler = new BluetoothEnabler(
141                     this,
142                     (CheckBoxPreference) findPreference(KEY_BT_CHECKBOX));
143
144             mDiscoverableEnabler = new BluetoothDiscoverableEnabler(
145                     this,
146                     (CheckBoxPreference) findPreference(KEY_BT_DISCOVERABLE));
147
148             mNamePreference = (BluetoothNamePreference) findPreference(KEY_BT_NAME);
149
150             mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
151         }
152
153         mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
154
155         registerForContextMenu(getListView());
156     }
157
158     @Override
159     protected void onResume() {
160         super.onResume();
161
162         // Repopulate (which isn't too bad since it's cached in the settings
163         // bluetooth manager
164         mDevicePreferenceMap.clear();
165         mDeviceList.removeAll();
166         addDevices();
167
168         if (mScreenType == SCREEN_TYPE_SETTINGS) {
169             mEnabler.resume();
170             mDiscoverableEnabler.resume();
171             mNamePreference.resume();
172         }
173
174         mLocalManager.registerCallback(this);
175
176         mDeviceList.setProgress(mLocalManager.getBluetoothAdapter().isDiscovering());
177         mLocalManager.startScanning(false);
178
179         IntentFilter intentFilter = new IntentFilter();
180         intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
181         intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
182         registerReceiver(mReceiver, intentFilter);
183         mLocalManager.setForegroundActivity(this);
184     }
185
186     @Override
187     protected void onPause() {
188         super.onPause();
189
190         mLocalManager.setForegroundActivity(null);
191         mDevicePreferenceMap.clear();
192         mDeviceList.removeAll();
193         unregisterReceiver(mReceiver);
194
195         mLocalManager.unregisterCallback(this);
196         if (mScreenType == SCREEN_TYPE_SETTINGS) {
197             mNamePreference.pause();
198             mDiscoverableEnabler.pause();
199             mEnabler.pause();
200         }
201     }
202
203     @Override
204     protected void onUserLeaveHint() {
205         super.onUserLeaveHint();
206         mLocalManager.stopScanning();
207     }
208
209     private void addDevices() {
210         List<CachedBluetoothDevice> cachedDevices =
211                 mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
212         for (CachedBluetoothDevice cachedDevice : cachedDevices) {
213             onDeviceAdded(cachedDevice);
214         }
215     }
216
217     @Override
218     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
219             Preference preference) {
220
221         if (KEY_BT_SCAN.equals(preference.getKey())) {
222             mLocalManager.startScanning(true);
223             return true;
224         }
225
226         if (preference instanceof BluetoothDevicePreference) {
227             BluetoothDevicePreference btPreference = (BluetoothDevicePreference)preference;
228             if (mScreenType == SCREEN_TYPE_SETTINGS) {
229                 btPreference.getCachedDevice().onClicked();
230             } else if (mScreenType == SCREEN_TYPE_DEVICEPICKER) {
231                 CachedBluetoothDevice device = btPreference.getCachedDevice();
232
233                 mSelectedDevice = device.getDevice();
234                 mLocalManager.stopScanning();
235                 mLocalManager.persistSelectedDeviceInPicker(mSelectedDevice.getAddress());
236                 if ((device.getBondState() == BluetoothDevice.BOND_BONDED) ||
237                         (mNeedAuth == false)) {
238                     sendDevicePickedIntent(mSelectedDevice);
239                     finish();
240                 } else {
241                     btPreference.getCachedDevice().onClicked();
242                 }
243             }
244             return true;
245         }
246
247         return super.onPreferenceTreeClick(preferenceScreen, preference);
248     }
249
250     @Override
251     public void onCreateContextMenu(ContextMenu menu, View v,
252             ContextMenuInfo menuInfo) {
253         //For device picker, disable Context Menu
254         if (mScreenType != SCREEN_TYPE_SETTINGS) {
255             return;
256         }
257         CachedBluetoothDevice cachedDevice = getDeviceFromMenuInfo(menuInfo);
258         if (cachedDevice == null) return;
259
260         cachedDevice.onCreateContextMenu(menu);
261     }
262
263     @Override
264     public boolean onContextItemSelected(MenuItem item) {
265         CachedBluetoothDevice cachedDevice = getDeviceFromMenuInfo(item.getMenuInfo());
266         if (cachedDevice == null) return false;
267
268         cachedDevice.onContextItemSelected(item);
269         return true;
270     }
271
272     private CachedBluetoothDevice getDeviceFromMenuInfo(ContextMenuInfo menuInfo) {
273         if ((menuInfo == null) || !(menuInfo instanceof AdapterContextMenuInfo)) {
274             return null;
275         }
276
277         AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo;
278         Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(
279                 adapterMenuInfo.position);
280         if (pref == null || !(pref instanceof BluetoothDevicePreference)) {
281             return null;
282         }
283
284         return ((BluetoothDevicePreference) pref).getCachedDevice();
285     }
286
287     public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
288
289         if (mDevicePreferenceMap.get(cachedDevice) != null) {
290             throw new IllegalStateException("Got onDeviceAdded, but cachedDevice already exists");
291         }
292
293         if (addDevicePreference(cachedDevice)) {
294             createDevicePreference(cachedDevice);
295         }
296      }
297
298     private boolean addDevicePreference(CachedBluetoothDevice cachedDevice) {
299         ParcelUuid[] uuids = cachedDevice.getDevice().getUuids();
300         BluetoothClass bluetoothClass = cachedDevice.getDevice().getBluetoothClass();
301
302         switch(mFilterType) {
303         case BluetoothDevicePicker.FILTER_TYPE_TRANSFER:
304             if (uuids != null)
305                 if (BluetoothUuid.containsAnyUuid(uuids,
306                         LocalBluetoothProfileManager.OPP_PROFILE_UUIDS))  return true;
307                 if (bluetoothClass != null
308                         && bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_OPP)) {
309                     return true;
310                 }
311             break;
312         case BluetoothDevicePicker.FILTER_TYPE_AUDIO:
313             if (uuids != null) {
314                 if (BluetoothUuid.containsAnyUuid(uuids,
315                         LocalBluetoothProfileManager.A2DP_PROFILE_UUIDS))  return true;
316
317                 if (BluetoothUuid.containsAnyUuid(uuids,
318                         LocalBluetoothProfileManager.HEADSET_PROFILE_UUIDS))  return true;
319             } else if (bluetoothClass != null) {
320                 if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) return true;
321
322                 if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) return true;
323             }
324             break;
325         default:
326             return true;
327         }
328         return false;
329     }
330
331     private void createDevicePreference(CachedBluetoothDevice cachedDevice) {
332         BluetoothDevicePreference preference = new BluetoothDevicePreference(this, cachedDevice);
333         mDeviceList.addPreference(preference);
334         mDevicePreferenceMap.put(cachedDevice, preference);
335     }
336
337     public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
338         BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
339         if (preference != null) {
340             mDeviceList.removePreference(preference);
341         }
342     }
343
344     public void onScanningStateChanged(boolean started) {
345         mDeviceList.setProgress(started);
346     }
347
348     private void onBluetoothStateChanged(int bluetoothState) {
349         // When bluetooth is enabled (and we are in the activity, which we are),
350         // we should start a scan
351         if (bluetoothState == BluetoothAdapter.STATE_ON) {
352             mLocalManager.startScanning(false);
353         } else if (bluetoothState == BluetoothAdapter.STATE_OFF) {
354             mDeviceList.setProgress(false);
355         }
356     }
357
358     private void sendDevicePickedIntent(BluetoothDevice device) {
359         Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
360         if (mLaunchPackage != null && mLaunchClass != null) {
361             intent.setClassName(mLaunchPackage, mLaunchClass);
362         }
363         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
364         sendBroadcast(intent);
365     }
366 }