DeviceProfilesSettings.java revision e79f990490de49b39097433707c2bae6d8238330
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 17package com.android.settings.bluetooth; 18 19import com.android.settings.R; 20import com.android.settings.SettingsPreferenceFragment; 21import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; 22 23import android.bluetooth.BluetoothDevice; 24import android.os.Bundle; 25import android.preference.CheckBoxPreference; 26import android.preference.EditTextPreference; 27import android.preference.Preference; 28import android.preference.PreferenceGroup; 29import android.preference.PreferenceScreen; 30import android.text.TextUtils; 31import android.util.Log; 32import android.view.View; 33 34import java.util.HashMap; 35 36/** 37 * This preference fragment presents the user with all of the profiles 38 * for a particular device, and allows them to be individually connected 39 * (or disconnected). 40 */ 41public class DeviceProfilesSettings extends SettingsPreferenceFragment 42 implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener, 43 View.OnClickListener { 44 private static final String TAG = "DeviceProfilesSettings"; 45 46 private static final String KEY_TITLE = "title"; 47 private static final String KEY_RENAME_DEVICE = "rename_device"; 48 private static final String KEY_PROFILE_CONTAINER = "profile_container"; 49 private static final String KEY_UNPAIR = "unpair"; 50 private static final String KEY_ALLOW_INCOMING = "allow_incoming"; 51 52 private static final String AUTO_CONNECT_KEY_SUFFIX = "X"; 53 54 public static final String EXTRA_DEVICE = "device"; 55 56 private LocalBluetoothManager mManager; 57 private CachedBluetoothDevice mCachedDevice; 58 59 private PreferenceGroup mProfileContainer; 60 private CheckBoxPreference mAllowIncomingPref; 61 private EditTextPreference mDeviceNamePref; 62 private HashMap<String,CheckBoxPreference> mAutoConnectPrefs 63 = new HashMap<String,CheckBoxPreference>(); 64 65 @Override 66 public void onCreate(Bundle savedInstanceState) { 67 super.onCreate(savedInstanceState); 68 69 BluetoothDevice device; 70 if (savedInstanceState != null) { 71 device = savedInstanceState.getParcelable(EXTRA_DEVICE); 72 } else { 73 Bundle args = getArguments(); 74 device = args.getParcelable(EXTRA_DEVICE); 75 } 76 77 if (device == null) { 78 Log.w(TAG, "Activity started without a remote Bluetooth device"); 79 finish(); 80 } 81 82 mManager = LocalBluetoothManager.getInstance(getActivity()); 83 mCachedDevice = mManager.getCachedDeviceManager().findDevice(device); 84 if (mCachedDevice == null) { 85 Log.w(TAG, "Device not found, cannot connect to it"); 86 finish(); 87 } 88 89 addPreferencesFromResource(R.xml.bluetooth_device_advanced); 90 getPreferenceScreen().setOrderingAsAdded(false); 91 92 mProfileContainer = (PreferenceGroup) findPreference(KEY_PROFILE_CONTAINER); 93 mAllowIncomingPref = (CheckBoxPreference) findPreference(KEY_ALLOW_INCOMING); 94 mAllowIncomingPref.setChecked(isIncomingFileTransfersAllowed()); 95 96 mDeviceNamePref = (EditTextPreference) findPreference(KEY_RENAME_DEVICE); 97 mDeviceNamePref.setSummary(mCachedDevice.getName()); 98 mDeviceNamePref.setText(mCachedDevice.getName()); 99 100 // Set the title of the screen 101 findPreference(KEY_TITLE).setTitle(getResources() 102 .getString(R.string.bluetooth_device_advanced_title, mCachedDevice.getName())); 103 104 // Add a preference for each profile 105 addPreferencesForProfiles(); 106 } 107 108 @Override 109 public void onSaveInstanceState(Bundle outState) { 110 super.onSaveInstanceState(outState); 111 112 outState.putParcelable(EXTRA_DEVICE, mCachedDevice.getDevice()); 113 } 114 115 @Override 116 public void onResume() { 117 super.onResume(); 118 119 mManager.setForegroundActivity(getActivity()); 120 mCachedDevice.registerCallback(this); 121 122 refresh(); 123 } 124 125 @Override 126 public void onPause() { 127 super.onPause(); 128 129 mCachedDevice.unregisterCallback(this); 130 mManager.setForegroundActivity(null); 131 } 132 133 private void addPreferencesForProfiles() { 134 for (Profile profile : mCachedDevice.getConnectableProfiles()) { 135 Preference pref = createProfilePreference(profile); 136 mProfileContainer.addPreference(pref); 137 } 138 } 139 140 /** 141 * Creates a checkbox preference for the particular profile. The key will be 142 * the profile's name. 143 * 144 * @param profile The profile for which the preference controls. 145 * @return A preference that allows the user to choose whether this profile 146 * will be connected to. 147 */ 148 private Preference createProfilePreference(Profile profile) { 149 BluetoothProfilePreference pref = new BluetoothProfilePreference(getActivity(), profile); 150 pref.setKey(profile.toString()); 151 pref.setTitle(profile.localizedString); 152 pref.setExpanded(false); 153 pref.setPersistent(false); 154 pref.setOrder(getProfilePreferenceIndex(profile)); 155 pref.setOnExpandClickListener(this); 156 157 /** 158 * Gray out profile while connecting and disconnecting 159 */ 160 pref.setEnabled(!mCachedDevice.isBusy()); 161 162 refreshProfilePreference(pref, profile); 163 164 return pref; 165 } 166 167 @Override 168 public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { 169 String key = preference.getKey(); 170 if (preference instanceof BluetoothProfilePreference) { 171 onProfileClicked(Profile.valueOf(key)); 172 return true; 173 } else if (key.equals(KEY_UNPAIR)) { 174 unpairDevice(); 175 finish(); 176 return true; 177 } 178 179 return false; 180 } 181 182 public boolean onPreferenceChange(Preference preference, Object newValue) { 183 if (preference == mAllowIncomingPref) { 184 setIncomingFileTransfersAllowed(mAllowIncomingPref.isChecked()); 185 } else if (preference == mDeviceNamePref) { 186 // TODO: Verify and check for error conditions 187 mCachedDevice.setName(mDeviceNamePref.getText()); 188 } else { 189 return false; 190 } 191 192 return true; 193 } 194 195 private void onProfileClicked(Profile profile) { 196 BluetoothDevice device = mCachedDevice.getDevice(); 197 LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager 198 .getProfileManager(mManager, profile); 199 200 int status = profileManager.getConnectionStatus(device); 201 boolean isConnected = 202 SettingsBtStatus.isConnectionStatusConnected(status); 203 204 // TODO: only change the preference on disconnect if user confirms 205 // TODO: add method to change priority of individual profiles 206 // profileManager.setPreferred(device, !isConnected); 207 208 if (isConnected) { 209 mCachedDevice.askDisconnect(profile); 210 } else { 211 mCachedDevice.connect(profile); 212 } 213 } 214 215 public void onDeviceAttributesChanged(CachedBluetoothDevice cachedDevice) { 216 refresh(); 217 } 218 219 private void refresh() { 220 refreshProfiles(); 221 } 222 223 private void refreshProfiles() { 224 for (Profile profile : mCachedDevice.getConnectableProfiles()) { 225 Preference profilePref = findPreference(profile.toString()); 226 if (profilePref == null) { 227 profilePref = createProfilePreference(profile); 228 mProfileContainer.addPreference(profilePref); 229 } else { 230 refreshProfilePreference(profilePref, profile); 231 } 232 } 233 } 234 235 private void refreshProfilePreference(Preference profilePref, Profile profile) { 236 BluetoothDevice device = mCachedDevice.getDevice(); 237 LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager 238 .getProfileManager(mManager, profile); 239 240 int connectionStatus = profileManager.getConnectionStatus(device); 241 242 /* 243 * Gray out checkbox while connecting and disconnecting 244 */ 245 profilePref.setEnabled(!mCachedDevice.isBusy()); 246 profilePref.setSummary(getProfileSummary(profileManager, profile, device, 247 connectionStatus, isDeviceOnline())); 248 // TODO: 249 //profilePref.setChecked(profileManager.isPreferred(device)); 250 } 251 252 private Profile getProfileOf(Preference pref) { 253 if (!(pref instanceof CheckBoxPreference)) return null; 254 String key = pref.getKey(); 255 if (TextUtils.isEmpty(key)) return null; 256 257 try { 258 return Profile.valueOf(pref.getKey()); 259 } catch (IllegalArgumentException e) { 260 return null; 261 } 262 } 263 264 private static int getProfileSummary(LocalBluetoothProfileManager profileManager, 265 Profile profile, BluetoothDevice device, int connectionStatus, boolean onlineMode) { 266 if (!onlineMode || connectionStatus == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) { 267 return getProfileSummaryForSettingPreference(profile); 268 } else { 269 return profileManager.getSummary(device); 270 } 271 } 272 273 /** 274 * Gets the summary that describes when checked, it will become a preferred profile. 275 * 276 * @param profile The profile to get the summary for. 277 * @return The summary. 278 */ 279 private static final int getProfileSummaryForSettingPreference(Profile profile) { 280 switch (profile) { 281 case A2DP: 282 return R.string.bluetooth_a2dp_profile_summary_use_for; 283 case HEADSET: 284 return R.string.bluetooth_headset_profile_summary_use_for; 285 case HID: 286 return R.string.bluetooth_hid_profile_summary_use_for; 287 default: 288 return 0; 289 } 290 } 291 292 public void onClick(View v) { 293 if (v.getTag() instanceof Profile) { 294 Profile prof = (Profile) v.getTag(); 295 CheckBoxPreference autoConnectPref = mAutoConnectPrefs.get(prof.toString()); 296 if (autoConnectPref == null) { 297 autoConnectPref = new CheckBoxPreference(getActivity()); 298 autoConnectPref.setKey(prof.toString() + AUTO_CONNECT_KEY_SUFFIX); 299 autoConnectPref.setTitle(getCheckBoxTitle(prof)); 300 autoConnectPref.setOrder(getProfilePreferenceIndex(prof) + 1); 301 autoConnectPref.setChecked(getAutoConnect(prof)); 302 mAutoConnectPrefs.put(prof.name(), autoConnectPref); 303 } 304 BluetoothProfilePreference profilePref = 305 (BluetoothProfilePreference) findPreference(prof.toString()); 306 if (profilePref != null) { 307 if (profilePref.isExpanded()) { 308 mProfileContainer.addPreference(autoConnectPref); 309 } else { 310 mProfileContainer.removePreference(autoConnectPref); 311 } 312 } 313 } 314 } 315 316 private int getProfilePreferenceIndex(Profile prof) { 317 return mProfileContainer.getOrder() + prof.ordinal() * 10; 318 } 319 320 private void unpairDevice() { 321 mCachedDevice.unpair(); 322 } 323 324 private boolean isDeviceOnline() { 325 // TODO: Verify 326 return mCachedDevice.isConnected() || mCachedDevice.isBusy(); 327 } 328 329 private void setIncomingFileTransfersAllowed(boolean allow) { 330 // TODO: 331 Log.d(TAG, "Set allow incoming = " + allow); 332 } 333 334 private boolean isIncomingFileTransfersAllowed() { 335 // TODO: 336 return true; 337 } 338 339 private String getCheckBoxTitle(Profile prof) { 340 // TODO: Use resources and base it on profile if necessary 341 return "Auto connect"; 342 } 343 344 private boolean getAutoConnect(Profile prof) { 345 // TODO: Get the auto connect toggle state for the profile 346 return true; 347 } 348} 349