OSDN Git Service

[Fingerprint] Remove learn more link if not provisioned. 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.Dialog;
21 import android.app.DialogFragment;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothProfile;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.os.Bundle;
27 import android.preference.CheckBoxPreference;
28 import android.preference.EditTextPreference;
29 import android.text.Html;
30 import android.text.TextUtils;
31 import android.util.Log;
32 import android.view.LayoutInflater;
33 import android.view.View;
34 import android.view.View.OnClickListener;
35 import android.view.ViewGroup;
36 import android.widget.CheckBox;
37 import android.widget.EditText;
38 import android.widget.TextView;
39
40 import com.android.settings.R;
41 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
42 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
43 import com.android.settingslib.bluetooth.LocalBluetoothManager;
44 import com.android.settingslib.bluetooth.LocalBluetoothProfile;
45 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
46 import com.android.settingslib.bluetooth.MapProfile;
47 import com.android.settingslib.bluetooth.PanProfile;
48 import com.android.settingslib.bluetooth.PbapServerProfile;
49
50 import java.util.HashMap;
51
52 public final class DeviceProfilesSettings extends DialogFragment implements
53         CachedBluetoothDevice.Callback, DialogInterface.OnClickListener, OnClickListener {
54     private static final String TAG = "DeviceProfilesSettings";
55
56     public static final String ARG_DEVICE_ADDRESS = "device_address";
57
58     private static final String KEY_PROFILE_CONTAINER = "profile_container";
59     private static final String KEY_UNPAIR = "unpair";
60     private static final String KEY_PBAP_SERVER = "PBAP Server";
61
62     private CachedBluetoothDevice mCachedDevice;
63     private LocalBluetoothManager mManager;
64     private LocalBluetoothProfileManager mProfileManager;
65
66     private ViewGroup mProfileContainer;
67     private TextView mProfileLabel;
68     private EditTextPreference mDeviceNamePref;
69
70     private final HashMap<LocalBluetoothProfile, CheckBoxPreference> mAutoConnectPrefs
71             = new HashMap<LocalBluetoothProfile, CheckBoxPreference>();
72
73     private AlertDialog mDisconnectDialog;
74     private boolean mProfileGroupIsRemoved;
75
76     private View mRootView;
77
78     @Override
79     public void onCreate(Bundle savedInstanceState) {
80         super.onCreate(savedInstanceState);
81
82         mManager = Utils.getLocalBtManager(getActivity());
83         CachedBluetoothDeviceManager deviceManager = mManager.getCachedDeviceManager();
84
85         String address = getArguments().getString(ARG_DEVICE_ADDRESS);
86         BluetoothDevice remoteDevice = mManager.getBluetoothAdapter().getRemoteDevice(address);
87
88         mCachedDevice = deviceManager.findDevice(remoteDevice);
89         if (mCachedDevice == null) {
90             mCachedDevice = deviceManager.addDevice(mManager.getBluetoothAdapter(),
91                     mManager.getProfileManager(), remoteDevice);
92         }
93         mProfileManager = mManager.getProfileManager();
94     }
95
96     @Override
97     public Dialog onCreateDialog(Bundle savedInstanceState) {
98         mRootView = LayoutInflater.from(getContext()).inflate(R.layout.device_profiles_settings,
99                 null);
100         mProfileContainer = (ViewGroup) mRootView.findViewById(R.id.profiles_section);
101         mProfileLabel = (TextView) mRootView.findViewById(R.id.profiles_label);
102         final EditText deviceName = (EditText) mRootView.findViewById(R.id.name);
103         deviceName.setText(mCachedDevice.getName(), TextView.BufferType.EDITABLE);
104         return new AlertDialog.Builder(getContext())
105                 .setView(mRootView)
106                 .setNegativeButton(R.string.forget, this)
107                 .setPositiveButton(R.string.okay, this)
108                 .setTitle(R.string.bluetooth_preference_paired_devices)
109                 .create();
110     }
111
112     @Override
113     public void onClick(DialogInterface dialog, int which) {
114         switch (which) {
115             case DialogInterface.BUTTON_POSITIVE:
116                 EditText deviceName = (EditText) mRootView.findViewById(R.id.name);
117                 mCachedDevice.setName(deviceName.getText().toString());
118                 break;
119             case DialogInterface.BUTTON_NEGATIVE:
120                 mCachedDevice.unpair();
121                 com.android.settings.bluetooth.Utils.updateSearchIndex(getContext(),
122                         BluetoothSettings.class.getName(), mCachedDevice.getName(),
123                         getString(R.string.bluetooth_settings),
124                         R.drawable.ic_settings_bluetooth, false);
125                 break;
126         }
127     }
128
129     @Override
130     public void onDestroy() {
131         super.onDestroy();
132         if (mDisconnectDialog != null) {
133             mDisconnectDialog.dismiss();
134             mDisconnectDialog = null;
135         }
136         if (mCachedDevice != null) {
137             mCachedDevice.unregisterCallback(this);
138         }
139     }
140
141     @Override
142     public void onSaveInstanceState(Bundle outState) {
143         super.onSaveInstanceState(outState);
144     }
145
146     @Override
147     public void onResume() {
148         super.onResume();
149
150         mManager.setForegroundActivity(getActivity());
151         if (mCachedDevice != null) {
152             mCachedDevice.registerCallback(this);
153             if (mCachedDevice.getBondState() == BluetoothDevice.BOND_NONE) {
154                 dismiss();
155                 return;
156             }
157             addPreferencesForProfiles();
158             refresh();
159         }
160     }
161
162     @Override
163     public void onPause() {
164         super.onPause();
165
166         if (mCachedDevice != null) {
167             mCachedDevice.unregisterCallback(this);
168         }
169
170         mManager.setForegroundActivity(null);
171     }
172
173     private void addPreferencesForProfiles() {
174         mProfileContainer.removeAllViews();
175         for (LocalBluetoothProfile profile : mCachedDevice.getConnectableProfiles()) {
176             CheckBox pref = createProfilePreference(profile);
177             mProfileContainer.addView(pref);
178         }
179
180         final int pbapPermission = mCachedDevice.getPhonebookPermissionChoice();
181         // Only provide PBAP cabability if the client device has requested PBAP.
182         if (pbapPermission != CachedBluetoothDevice.ACCESS_UNKNOWN) {
183             final PbapServerProfile psp = mManager.getProfileManager().getPbapProfile();
184             CheckBox pbapPref = createProfilePreference(psp);
185             mProfileContainer.addView(pbapPref);
186         }
187
188         final MapProfile mapProfile = mManager.getProfileManager().getMapProfile();
189         final int mapPermission = mCachedDevice.getMessagePermissionChoice();
190         if (mapPermission != CachedBluetoothDevice.ACCESS_UNKNOWN) {
191             CheckBox mapPreference = createProfilePreference(mapProfile);
192             mProfileContainer.addView(mapPreference);
193         }
194
195         showOrHideProfileGroup();
196     }
197
198     private void showOrHideProfileGroup() {
199         int numProfiles = mProfileContainer.getChildCount();
200         if (!mProfileGroupIsRemoved && numProfiles == 0) {
201             mProfileContainer.setVisibility(View.GONE);
202             mProfileLabel.setVisibility(View.GONE);
203             mProfileGroupIsRemoved = true;
204         } else if (mProfileGroupIsRemoved && numProfiles != 0) {
205             mProfileContainer.setVisibility(View.VISIBLE);
206             mProfileLabel.setVisibility(View.VISIBLE);
207             mProfileGroupIsRemoved = false;
208         }
209     }
210
211     /**
212      * Creates a checkbox preference for the particular profile. The key will be
213      * the profile's name.
214      *
215      * @param profile The profile for which the preference controls.
216      * @return A preference that allows the user to choose whether this profile
217      *         will be connected to.
218      */
219     private CheckBox createProfilePreference(LocalBluetoothProfile profile) {
220         CheckBox pref = new CheckBox(getActivity());
221         pref.setTag(profile.toString());
222         pref.setText(profile.getNameResource(mCachedDevice.getDevice()));
223         pref.setOnClickListener(this);
224
225         refreshProfilePreference(pref, profile);
226
227         return pref;
228     }
229
230     @Override
231     public void onClick(View v) {
232         if (v instanceof CheckBox) {
233             LocalBluetoothProfile prof = getProfileOf(v);
234             onProfileClicked(prof, (CheckBox) v);
235         }
236     }
237
238     private void onProfileClicked(LocalBluetoothProfile profile, CheckBox profilePref) {
239         BluetoothDevice device = mCachedDevice.getDevice();
240
241         if (KEY_PBAP_SERVER.equals(profilePref.getTag())) {
242             final int newPermission = mCachedDevice.getPhonebookPermissionChoice()
243                 == CachedBluetoothDevice.ACCESS_ALLOWED ? CachedBluetoothDevice.ACCESS_REJECTED
244                 : CachedBluetoothDevice.ACCESS_ALLOWED;
245             mCachedDevice.setPhonebookPermissionChoice(newPermission);
246             profilePref.setChecked(newPermission == CachedBluetoothDevice.ACCESS_ALLOWED);
247             return;
248         }
249
250         if (!profilePref.isChecked()) {
251             // Recheck it, until the dialog is done.
252             profilePref.setChecked(true);
253             askDisconnect(mManager.getForegroundActivity(), profile);
254         } else {
255             if (profile instanceof MapProfile) {
256                 mCachedDevice.setMessagePermissionChoice(BluetoothDevice.ACCESS_ALLOWED);
257             }
258             if (profile.isPreferred(device)) {
259                 // profile is preferred but not connected: disable auto-connect
260                 if (profile instanceof PanProfile) {
261                     mCachedDevice.connectProfile(profile);
262                 } else {
263                     profile.setPreferred(device, false);
264                 }
265             } else {
266                 profile.setPreferred(device, true);
267                 mCachedDevice.connectProfile(profile);
268             }
269             refreshProfilePreference(profilePref, profile);
270         }
271     }
272
273     private void askDisconnect(Context context,
274             final LocalBluetoothProfile profile) {
275         // local reference for callback
276         final CachedBluetoothDevice device = mCachedDevice;
277         String name = device.getName();
278         if (TextUtils.isEmpty(name)) {
279             name = context.getString(R.string.bluetooth_device);
280         }
281
282         String profileName = context.getString(profile.getNameResource(device.getDevice()));
283
284         String title = context.getString(R.string.bluetooth_disable_profile_title);
285         String message = context.getString(R.string.bluetooth_disable_profile_message,
286                 profileName, name);
287
288         DialogInterface.OnClickListener disconnectListener =
289                 new DialogInterface.OnClickListener() {
290             public void onClick(DialogInterface dialog, int which) {
291                 device.disconnect(profile);
292                 profile.setPreferred(device.getDevice(), false);
293                 if (profile instanceof MapProfile) {
294                     device.setMessagePermissionChoice(BluetoothDevice.ACCESS_REJECTED);
295                 }
296                 refreshProfilePreference(findProfile(profile.toString()), profile);
297             }
298         };
299
300         mDisconnectDialog = Utils.showDisconnectDialog(context,
301                 mDisconnectDialog, disconnectListener, title, Html.fromHtml(message));
302     }
303
304     @Override
305     public void onDeviceAttributesChanged() {
306         refresh();
307     }
308
309     private void refresh() {
310         final EditText deviceNameField = (EditText) mRootView.findViewById(R.id.name);
311         if (deviceNameField != null) {
312             deviceNameField.setText(mCachedDevice.getName());
313         }
314
315         refreshProfiles();
316     }
317
318     private void refreshProfiles() {
319         for (LocalBluetoothProfile profile : mCachedDevice.getConnectableProfiles()) {
320             CheckBox profilePref = findProfile(profile.toString());
321             if (profilePref == null) {
322                 profilePref = createProfilePreference(profile);
323                 mProfileContainer.addView(profilePref);
324             } else {
325                 refreshProfilePreference(profilePref, profile);
326             }
327         }
328         for (LocalBluetoothProfile profile : mCachedDevice.getRemovedProfiles()) {
329             CheckBox profilePref = findProfile(profile.toString());
330             if (profilePref != null) {
331                 Log.d(TAG, "Removing " + profile.toString() + " from profile list");
332                 mProfileContainer.removeView(profilePref);
333             }
334         }
335
336         showOrHideProfileGroup();
337     }
338
339     private CheckBox findProfile(String profile) {
340         return (CheckBox) mProfileContainer.findViewWithTag(profile);
341     }
342
343     private void refreshProfilePreference(CheckBox profilePref,
344             LocalBluetoothProfile profile) {
345         BluetoothDevice device = mCachedDevice.getDevice();
346
347         // Gray out checkbox while connecting and disconnecting.
348         profilePref.setEnabled(!mCachedDevice.isBusy());
349
350         if (profile instanceof MapProfile) {
351             profilePref.setChecked(mCachedDevice.getMessagePermissionChoice()
352                     == CachedBluetoothDevice.ACCESS_ALLOWED);
353
354         } else if (profile instanceof PbapServerProfile) {
355             profilePref.setChecked(mCachedDevice.getPhonebookPermissionChoice()
356                     == CachedBluetoothDevice.ACCESS_ALLOWED);
357
358         } else if (profile instanceof PanProfile) {
359             profilePref.setChecked(profile.getConnectionStatus(device) ==
360                     BluetoothProfile.STATE_CONNECTED);
361
362         } else {
363             profilePref.setChecked(profile.isPreferred(device));
364         }
365     }
366
367     private LocalBluetoothProfile getProfileOf(View v) {
368         if (!(v instanceof CheckBox)) {
369             return null;
370         }
371         String key = (String) v.getTag();
372         if (TextUtils.isEmpty(key)) return null;
373
374         try {
375             return mProfileManager.getProfileByName(key);
376         } catch (IllegalArgumentException ignored) {
377             return null;
378         }
379     }
380 }