OSDN Git Service

Import translations. DO NOT MERGE
[android-x86/packages-apps-Settings.git] / src / com / android / settings / bluetooth / DeviceProfilesSettings.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.AlertDialog;
20 import android.app.Fragment;
21 import android.bluetooth.BluetoothDevice;
22 import android.bluetooth.BluetoothProfile;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.os.Bundle;
26 import android.preference.CheckBoxPreference;
27 import android.preference.EditTextPreference;
28 import android.preference.Preference;
29 import android.preference.PreferenceGroup;
30 import android.preference.PreferenceScreen;
31 import android.text.Html;
32 import android.text.TextUtils;
33 import android.util.Log;
34 import android.view.View;
35 import android.widget.EditText;
36 import android.text.TextWatcher;
37 import android.app.Dialog;
38 import android.widget.Button;
39 import android.text.Editable;
40
41 import com.android.settings.R;
42 import com.android.settings.SettingsPreferenceFragment;
43 import com.android.settings.search.Index;
44 import com.android.settings.search.SearchIndexableRaw;
45
46 import java.util.HashMap;
47
48 /**
49  * This preference fragment presents the user with all of the profiles
50  * for a particular device, and allows them to be individually connected
51  * (or disconnected).
52  */
53 public final class DeviceProfilesSettings extends SettingsPreferenceFragment
54         implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener {
55     private static final String TAG = "DeviceProfilesSettings";
56
57     private static final String KEY_PROFILE_CONTAINER = "profile_container";
58     private static final String KEY_UNPAIR = "unpair";
59     private static final String KEY_PBAP_SERVER = "PBAP Server";
60
61     private CachedBluetoothDevice mCachedDevice;
62     private LocalBluetoothManager mManager;
63     private LocalBluetoothProfileManager mProfileManager;
64
65     private PreferenceGroup mProfileContainer;
66     private EditTextPreference mDeviceNamePref;
67
68     private final HashMap<LocalBluetoothProfile, CheckBoxPreference> mAutoConnectPrefs
69             = new HashMap<LocalBluetoothProfile, CheckBoxPreference>();
70
71     private AlertDialog mDisconnectDialog;
72     private boolean mProfileGroupIsRemoved;
73
74     @Override
75     public void onCreate(Bundle savedInstanceState) {
76         super.onCreate(savedInstanceState);
77
78         addPreferencesFromResource(R.xml.bluetooth_device_advanced);
79         getPreferenceScreen().setOrderingAsAdded(false);
80         mProfileContainer = (PreferenceGroup) findPreference(KEY_PROFILE_CONTAINER);
81         mProfileContainer.setLayoutResource(R.layout.bluetooth_preference_category);
82
83         mManager = LocalBluetoothManager.getInstance(getActivity());
84         CachedBluetoothDeviceManager deviceManager =
85                 mManager.getCachedDeviceManager();
86         mProfileManager = mManager.getProfileManager();
87     }
88
89     @Override
90     public void onDestroy() {
91         super.onDestroy();
92         if (mDisconnectDialog != null) {
93             mDisconnectDialog.dismiss();
94             mDisconnectDialog = null;
95         }
96         if (mCachedDevice != null) {
97             mCachedDevice.unregisterCallback(this);
98         }
99     }
100
101     @Override
102     public void onSaveInstanceState(Bundle outState) {
103         super.onSaveInstanceState(outState);
104     }
105
106     @Override
107     public void onResume() {
108         super.onResume();
109
110         mManager.setForegroundActivity(getActivity());
111         if (mCachedDevice != null) {
112             mCachedDevice.registerCallback(this);
113             if (mCachedDevice.getBondState() == BluetoothDevice.BOND_NONE) {
114                 finish();
115                 return;
116             }
117             refresh();
118         }
119     }
120
121     @Override
122     public void onPause() {
123         super.onPause();
124
125         if (mCachedDevice != null) {
126             mCachedDevice.unregisterCallback(this);
127         }
128
129         mManager.setForegroundActivity(null);
130     }
131
132     public void setDevice(CachedBluetoothDevice cachedDevice) {
133         mCachedDevice = cachedDevice;
134
135         if (isResumed()) {
136             mCachedDevice.registerCallback(this);
137             addPreferencesForProfiles();
138             refresh();
139         }
140     }
141
142     private void addPreferencesForProfiles() {
143         mProfileContainer.removeAll();
144         for (LocalBluetoothProfile profile : mCachedDevice.getConnectableProfiles()) {
145             Preference pref = createProfilePreference(profile);
146             mProfileContainer.addPreference(pref);
147         }
148
149         final int pbapPermission = mCachedDevice.getPhonebookPermissionChoice();
150         // Only provide PBAP cabability if the client device has requested PBAP.
151         if (pbapPermission != CachedBluetoothDevice.ACCESS_UNKNOWN) {
152             final PbapServerProfile psp = mManager.getProfileManager().getPbapProfile();
153             CheckBoxPreference pbapPref = createProfilePreference(psp);
154             mProfileContainer.addPreference(pbapPref);
155         }
156
157         final MapProfile mapProfile = mManager.getProfileManager().getMapProfile();
158         final int mapPermission = mCachedDevice.getMessagePermissionChoice();
159         if (mapPermission != CachedBluetoothDevice.ACCESS_UNKNOWN) {
160             CheckBoxPreference mapPreference = createProfilePreference(mapProfile);
161             mProfileContainer.addPreference(mapPreference);
162         }
163
164         showOrHideProfileGroup();
165     }
166
167     private void showOrHideProfileGroup() {
168         int numProfiles = mProfileContainer.getPreferenceCount();
169         if (!mProfileGroupIsRemoved && numProfiles == 0) {
170             getPreferenceScreen().removePreference(mProfileContainer);
171             mProfileGroupIsRemoved = true;
172         } else if (mProfileGroupIsRemoved && numProfiles != 0) {
173             getPreferenceScreen().addPreference(mProfileContainer);
174             mProfileGroupIsRemoved = false;
175         }
176     }
177
178     /**
179      * Creates a checkbox preference for the particular profile. The key will be
180      * the profile's name.
181      *
182      * @param profile The profile for which the preference controls.
183      * @return A preference that allows the user to choose whether this profile
184      *         will be connected to.
185      */
186     private CheckBoxPreference createProfilePreference(LocalBluetoothProfile profile) {
187         CheckBoxPreference pref = new CheckBoxPreference(getActivity());
188         pref.setLayoutResource(R.layout.preference_start_widget);
189         pref.setKey(profile.toString());
190         pref.setTitle(profile.getNameResource(mCachedDevice.getDevice()));
191         pref.setPersistent(false);
192         pref.setOrder(getProfilePreferenceIndex(profile.getOrdinal()));
193         pref.setOnPreferenceChangeListener(this);
194
195         int iconResource = profile.getDrawableResource(mCachedDevice.getBtClass());
196         if (iconResource != 0) {
197             pref.setIcon(getResources().getDrawable(iconResource));
198         }
199
200         refreshProfilePreference(pref, profile);
201
202         return pref;
203     }
204
205     public boolean onPreferenceChange(Preference preference, Object newValue) {
206         if (preference == mDeviceNamePref) {
207             mCachedDevice.setName((String) newValue);
208         } else if (preference instanceof CheckBoxPreference) {
209             LocalBluetoothProfile prof = getProfileOf(preference);
210             onProfileClicked(prof, (CheckBoxPreference) preference);
211             return false;   // checkbox will update from onDeviceAttributesChanged() callback
212         } else {
213             return false;
214         }
215
216         return true;
217     }
218
219     private void onProfileClicked(LocalBluetoothProfile profile, CheckBoxPreference profilePref) {
220         BluetoothDevice device = mCachedDevice.getDevice();
221
222         if (profilePref.getKey().equals(KEY_PBAP_SERVER)) {
223             final int newPermission = mCachedDevice.getPhonebookPermissionChoice()
224                 == CachedBluetoothDevice.ACCESS_ALLOWED ? CachedBluetoothDevice.ACCESS_REJECTED
225                 : CachedBluetoothDevice.ACCESS_ALLOWED;
226             mCachedDevice.setPhonebookPermissionChoice(newPermission);
227             profilePref.setChecked(newPermission == CachedBluetoothDevice.ACCESS_ALLOWED);
228             return;
229         }
230
231         int status = profile.getConnectionStatus(device);
232         boolean isConnected =
233                 status == BluetoothProfile.STATE_CONNECTED;
234
235         if (profilePref.isChecked()) {
236             askDisconnect(mManager.getForegroundActivity(), profile);
237         } else {
238             if (profile instanceof MapProfile) {
239                 mCachedDevice.setMessagePermissionChoice(BluetoothDevice.ACCESS_ALLOWED);
240                 refreshProfilePreference(profilePref, profile);
241             }
242             if (profile.isPreferred(device)) {
243                 // profile is preferred but not connected: disable auto-connect
244                 profile.setPreferred(device, false);
245                 refreshProfilePreference(profilePref, profile);
246             } else {
247                 profile.setPreferred(device, true);
248                 mCachedDevice.connectProfile(profile);
249             }
250         }
251     }
252
253     private void askDisconnect(Context context,
254             final LocalBluetoothProfile profile) {
255         // local reference for callback
256         final CachedBluetoothDevice device = mCachedDevice;
257         String name = device.getName();
258         if (TextUtils.isEmpty(name)) {
259             name = context.getString(R.string.bluetooth_device);
260         }
261
262         String profileName = context.getString(profile.getNameResource(device.getDevice()));
263
264         String title = context.getString(R.string.bluetooth_disable_profile_title);
265         String message = context.getString(R.string.bluetooth_disable_profile_message,
266                 profileName, name);
267
268         DialogInterface.OnClickListener disconnectListener =
269                 new DialogInterface.OnClickListener() {
270             public void onClick(DialogInterface dialog, int which) {
271                 device.disconnect(profile);
272                 profile.setPreferred(device.getDevice(), false);
273                 if (profile instanceof MapProfile) {
274                     device.setMessagePermissionChoice(BluetoothDevice.ACCESS_REJECTED);
275                     refreshProfilePreference(
276                             (CheckBoxPreference)findPreference(profile.toString()), profile);
277                 }
278             }
279         };
280
281         mDisconnectDialog = Utils.showDisconnectDialog(context,
282                 mDisconnectDialog, disconnectListener, title, Html.fromHtml(message));
283     }
284
285     @Override
286     public void onDeviceAttributesChanged() {
287         refresh();
288     }
289
290     private void refresh() {
291         final EditText deviceNameField = (EditText) getView().findViewById(R.id.name);
292         if (deviceNameField != null) {
293             deviceNameField.setText(mCachedDevice.getName());
294         }
295
296         refreshProfiles();
297     }
298
299     private void refreshProfiles() {
300         for (LocalBluetoothProfile profile : mCachedDevice.getConnectableProfiles()) {
301             CheckBoxPreference profilePref = (CheckBoxPreference)findPreference(profile.toString());
302             if (profilePref == null) {
303                 profilePref = createProfilePreference(profile);
304                 mProfileContainer.addPreference(profilePref);
305             } else {
306                 refreshProfilePreference(profilePref, profile);
307             }
308         }
309         for (LocalBluetoothProfile profile : mCachedDevice.getRemovedProfiles()) {
310             Preference profilePref = findPreference(profile.toString());
311             if (profilePref != null) {
312                 Log.d(TAG, "Removing " + profile.toString() + " from profile list");
313                 mProfileContainer.removePreference(profilePref);
314             }
315         }
316
317         showOrHideProfileGroup();
318     }
319
320     private void refreshProfilePreference(CheckBoxPreference profilePref,
321             LocalBluetoothProfile profile) {
322         BluetoothDevice device = mCachedDevice.getDevice();
323
324         // Gray out checkbox while connecting and disconnecting.
325         profilePref.setEnabled(!mCachedDevice.isBusy());
326
327         if (profile instanceof MapProfile) {
328             profilePref.setChecked(mCachedDevice.getMessagePermissionChoice()
329                     == CachedBluetoothDevice.ACCESS_ALLOWED);
330         } else if (profile instanceof PbapServerProfile) {
331             // Handle PBAP specially.
332             profilePref.setChecked(mCachedDevice.getPhonebookPermissionChoice()
333                     == CachedBluetoothDevice.ACCESS_ALLOWED);
334         } else {
335             profilePref.setChecked(profile.isPreferred(device));
336         }
337     }
338
339     private LocalBluetoothProfile getProfileOf(Preference pref) {
340         if (!(pref instanceof CheckBoxPreference)) {
341             return null;
342         }
343         String key = pref.getKey();
344         if (TextUtils.isEmpty(key)) return null;
345
346         try {
347             return mProfileManager.getProfileByName(pref.getKey());
348         } catch (IllegalArgumentException ignored) {
349             return null;
350         }
351     }
352
353     private int getProfilePreferenceIndex(int profIndex) {
354         return mProfileContainer.getOrder() + profIndex * 10;
355     }
356 }