OSDN Git Service

Merge "Update WifiP2pManager API use"
[android-x86/packages-apps-Settings.git] / src / com / android / settings / bluetooth / BluetoothSettings.java
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.ActionBar;
20 import android.app.Activity;
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.os.Bundle;
28 import android.preference.Preference;
29 import android.preference.PreferenceActivity;
30 import android.preference.PreferenceCategory;
31 import android.preference.PreferenceGroup;
32 import android.preference.PreferenceScreen;
33 import android.util.Log;
34 import android.view.Gravity;
35 import android.view.LayoutInflater;
36 import android.view.Menu;
37 import android.view.MenuInflater;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.view.ViewGroup;
41 import android.widget.Switch;
42 import android.widget.TextView;
43
44 import com.android.settings.ProgressCategory;
45 import com.android.settings.R;
46
47 /**
48  * BluetoothSettings is the Settings screen for Bluetooth configuration and
49  * connection management.
50  */
51 public final class BluetoothSettings extends DeviceListPreferenceFragment {
52     private static final String TAG = "BluetoothSettings";
53
54     private static final int MENU_ID_SCAN = Menu.FIRST;
55     private static final int MENU_ID_RENAME_DEVICE = Menu.FIRST + 1;
56     private static final int MENU_ID_VISIBILITY_TIMEOUT = Menu.FIRST + 2;
57     private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 3;
58
59     /* Private intent to show the list of received files */
60     private static final String BTOPP_ACTION_OPEN_RECEIVED_FILES =
61             "android.btopp.intent.action.OPEN_RECEIVED_FILES";
62
63     private BluetoothEnabler mBluetoothEnabler;
64
65     private BluetoothDiscoverableEnabler mDiscoverableEnabler;
66
67     private PreferenceGroup mPairedDevicesCategory;
68
69     private PreferenceGroup mAvailableDevicesCategory;
70     private boolean mAvailableDevicesCategoryIsPresent;
71     private boolean mActivityStarted;
72
73     private TextView mEmptyView;
74
75     private final IntentFilter mIntentFilter;
76
77     // accessed from inner class (not private to avoid thunks)
78     Preference mMyDevicePreference;
79
80     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
81         @Override
82         public void onReceive(Context context, Intent intent) {
83             String action = intent.getAction();
84             if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
85                 updateDeviceName();
86             }
87         }
88
89         private void updateDeviceName() {
90             if (mLocalAdapter.isEnabled() && mMyDevicePreference != null) {
91                 mMyDevicePreference.setTitle(mLocalAdapter.getName());
92             }
93         }
94     };
95
96     public BluetoothSettings() {
97         mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
98     }
99
100     @Override
101     public void onActivityCreated(Bundle savedInstanceState) {
102         mActivityStarted = true;
103         super.onActivityCreated(savedInstanceState);
104
105         mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
106         getListView().setEmptyView(mEmptyView);
107     }
108
109     @Override
110     void addPreferencesForActivity() {
111         addPreferencesFromResource(R.xml.bluetooth_settings);
112
113         Activity activity = getActivity();
114
115         Switch actionBarSwitch = new Switch(activity);
116
117         if (activity instanceof PreferenceActivity) {
118             PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
119             if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) {
120                 final int padding = activity.getResources().getDimensionPixelSize(
121                         R.dimen.action_bar_switch_padding);
122                 actionBarSwitch.setPadding(0, 0, padding, 0);
123                 activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
124                         ActionBar.DISPLAY_SHOW_CUSTOM);
125                 activity.getActionBar().setCustomView(actionBarSwitch, new ActionBar.LayoutParams(
126                         ActionBar.LayoutParams.WRAP_CONTENT,
127                         ActionBar.LayoutParams.WRAP_CONTENT,
128                         Gravity.CENTER_VERTICAL | Gravity.RIGHT));
129             }
130         }
131
132         mBluetoothEnabler = new BluetoothEnabler(activity, actionBarSwitch);
133
134         setHasOptionsMenu(true);
135     }
136
137     @Override
138     public void onResume() {
139         // resume BluetoothEnabler before calling super.onResume() so we don't get
140         // any onDeviceAdded() callbacks before setting up view in updateContent()
141         mBluetoothEnabler.resume();
142         super.onResume();
143
144         if (mDiscoverableEnabler != null) {
145             mDiscoverableEnabler.resume();
146         }
147         getActivity().registerReceiver(mReceiver, mIntentFilter);
148
149         updateContent(mLocalAdapter.getBluetoothState(), mActivityStarted);
150     }
151
152     @Override
153     public void onPause() {
154         super.onPause();
155         mBluetoothEnabler.pause();
156         getActivity().unregisterReceiver(mReceiver);
157         if (mDiscoverableEnabler != null) {
158             mDiscoverableEnabler.pause();
159         }
160     }
161
162     @Override
163     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
164         boolean bluetoothIsEnabled = mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON;
165         boolean isDiscovering = mLocalAdapter.isDiscovering();
166         int textId = isDiscovering ? R.string.bluetooth_searching_for_devices :
167             R.string.bluetooth_search_for_devices;
168         menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
169                 .setEnabled(bluetoothIsEnabled && !isDiscovering)
170                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
171         menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
172                 .setEnabled(bluetoothIsEnabled)
173                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
174         menu.add(Menu.NONE, MENU_ID_VISIBILITY_TIMEOUT, 0, R.string.bluetooth_visibility_timeout)
175                 .setEnabled(bluetoothIsEnabled)
176                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
177         menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
178                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
179     }
180
181     @Override
182     public boolean onOptionsItemSelected(MenuItem item) {
183         switch (item.getItemId()) {
184             case MENU_ID_SCAN:
185                 if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {
186                     startScanning();
187                 }
188                 return true;
189
190             case MENU_ID_RENAME_DEVICE:
191                 new BluetoothNameDialogFragment().show(
192                         getFragmentManager(), "rename device");
193                 return true;
194
195             case MENU_ID_VISIBILITY_TIMEOUT:
196                 new BluetoothVisibilityTimeoutFragment().show(
197                         getFragmentManager(), "visibility timeout");
198                 return true;
199
200             case MENU_ID_SHOW_RECEIVED:
201                 Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
202                 getActivity().sendBroadcast(intent);
203                 return true;
204         }
205         return super.onOptionsItemSelected(item);
206     }
207
208     private void startScanning() {
209         if (!mAvailableDevicesCategoryIsPresent) {
210             getPreferenceScreen().addPreference(mAvailableDevicesCategory);
211         }
212         mLocalAdapter.startScanning(true);
213     }
214
215     @Override
216     void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
217         mLocalAdapter.stopScanning();
218         super.onDevicePreferenceClick(btPreference);
219     }
220
221     private void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
222             BluetoothDeviceFilter.Filter filter) {
223         preferenceGroup.setTitle(titleId);
224         getPreferenceScreen().addPreference(preferenceGroup);
225         setFilter(filter);
226         setDeviceListGroup(preferenceGroup);
227         addCachedDevices();
228         preferenceGroup.setEnabled(true);
229     }
230
231     private void updateContent(int bluetoothState, boolean scanState) {
232         final PreferenceScreen preferenceScreen = getPreferenceScreen();
233         int messageId = 0;
234
235         switch (bluetoothState) {
236             case BluetoothAdapter.STATE_ON:
237                 preferenceScreen.removeAll();
238                 preferenceScreen.setOrderingAsAdded(true);
239
240                 // This device
241                 if (mMyDevicePreference == null) {
242                     mMyDevicePreference = new Preference(getActivity());
243                 }
244                 mMyDevicePreference.setTitle(mLocalAdapter.getName());
245                 if (getResources().getBoolean(com.android.internal.R.bool.config_voice_capable)) {
246                     mMyDevicePreference.setIcon(R.drawable.ic_bt_cellphone);    // for phones
247                 } else {
248                     mMyDevicePreference.setIcon(R.drawable.ic_bt_laptop);   // for tablets, etc.
249                 }
250                 mMyDevicePreference.setPersistent(false);
251                 mMyDevicePreference.setEnabled(true);
252                 preferenceScreen.addPreference(mMyDevicePreference);
253
254                 if (mDiscoverableEnabler == null) {
255                     mDiscoverableEnabler = new BluetoothDiscoverableEnabler(getActivity(),
256                             mLocalAdapter, mMyDevicePreference);
257                     mDiscoverableEnabler.resume();
258                     LocalBluetoothManager.getInstance(getActivity()).setDiscoverableEnabler(
259                             mDiscoverableEnabler);
260                 }
261
262                 // Paired devices category
263                 if (mPairedDevicesCategory == null) {
264                     mPairedDevicesCategory = new PreferenceCategory(getActivity());
265                 } else {
266                     mPairedDevicesCategory.removeAll();
267                 }
268                 addDeviceCategory(mPairedDevicesCategory,
269                         R.string.bluetooth_preference_paired_devices,
270                         BluetoothDeviceFilter.BONDED_DEVICE_FILTER);
271                 int numberOfPairedDevices = mPairedDevicesCategory.getPreferenceCount();
272
273                 mDiscoverableEnabler.setNumberOfPairedDevices(numberOfPairedDevices);
274
275                 // Available devices category
276                 if (mAvailableDevicesCategory == null) {
277                     mAvailableDevicesCategory = new ProgressCategory(getActivity(), null);
278                 } else {
279                     mAvailableDevicesCategory.removeAll();
280                 }
281                 addDeviceCategory(mAvailableDevicesCategory,
282                         R.string.bluetooth_preference_found_devices,
283                         BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER);
284                 int numberOfAvailableDevices = mAvailableDevicesCategory.getPreferenceCount();
285                 mAvailableDevicesCategoryIsPresent = true;
286
287                 if (numberOfAvailableDevices == 0) {
288                     preferenceScreen.removePreference(mAvailableDevicesCategory);
289                     mAvailableDevicesCategoryIsPresent = false;
290                 }
291
292                 if (numberOfPairedDevices == 0) {
293                     preferenceScreen.removePreference(mPairedDevicesCategory);
294                     if (scanState == true) {
295                         mActivityStarted = false;
296                         startScanning();
297                     } else {
298                         if (!mAvailableDevicesCategoryIsPresent) {
299                             getPreferenceScreen().addPreference(mAvailableDevicesCategory);
300                         }
301                     }
302                 }
303                 getActivity().invalidateOptionsMenu();
304                 return; // not break
305
306             case BluetoothAdapter.STATE_TURNING_OFF:
307                 messageId = R.string.bluetooth_turning_off;
308                 break;
309
310             case BluetoothAdapter.STATE_OFF:
311                 messageId = R.string.bluetooth_empty_list_bluetooth_off;
312                 break;
313
314             case BluetoothAdapter.STATE_TURNING_ON:
315                 messageId = R.string.bluetooth_turning_on;
316                 break;
317         }
318
319         setDeviceListGroup(preferenceScreen);
320         removeAllDevices();
321         mEmptyView.setText(messageId);
322         getActivity().invalidateOptionsMenu();
323     }
324
325     @Override
326     public void onBluetoothStateChanged(int bluetoothState) {
327         super.onBluetoothStateChanged(bluetoothState);
328         updateContent(bluetoothState, true);
329     }
330
331     @Override
332     public void onScanningStateChanged(boolean started) {
333         super.onScanningStateChanged(started);
334         // Update options' enabled state
335         getActivity().invalidateOptionsMenu();
336     }
337
338     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
339         setDeviceListGroup(getPreferenceScreen());
340         removeAllDevices();
341         updateContent(mLocalAdapter.getBluetoothState(), false);
342     }
343
344     private final View.OnClickListener mDeviceProfilesListener = new View.OnClickListener() {
345         public void onClick(View v) {
346             // User clicked on advanced options icon for a device in the list
347             if (v.getTag() instanceof CachedBluetoothDevice) {
348                 CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
349
350                 Bundle args = new Bundle(1);
351                 args.putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, device.getDevice());
352
353                 ((PreferenceActivity) getActivity()).startPreferencePanel(
354                         DeviceProfilesSettings.class.getName(), args,
355                         R.string.bluetooth_device_advanced_title, null, null, 0);
356             } else {
357                 Log.w(TAG, "onClick() called for other View: " + v); // TODO remove
358             }
359         }
360     };
361
362     /**
363      * Add a listener, which enables the advanced settings icon.
364      * @param preference the newly added preference
365      */
366     @Override
367     void initDevicePreference(BluetoothDevicePreference preference) {
368         CachedBluetoothDevice cachedDevice = preference.getCachedDevice();
369         if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
370             // Only paired device have an associated advanced settings screen
371             preference.setOnSettingsClickListener(mDeviceProfilesListener);
372         }
373     }
374 }