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.R; 20 import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; 21 22 import android.content.Intent; 23 import android.os.Bundle; 24 import android.preference.CheckBoxPreference; 25 import android.preference.Preference; 26 import android.preference.PreferenceActivity; 27 import android.preference.PreferenceGroup; 28 import android.text.TextUtils; 29 import android.util.Log; 30 31 /** 32 * ConnectSpecificProfilesActivity presents the user with all of the profiles 33 * for a particular device, and allows him to choose which should be connected 34 * (or disconnected). 35 */ 36 public class ConnectSpecificProfilesActivity extends PreferenceActivity 37 implements LocalBluetoothDevice.Callback, Preference.OnPreferenceChangeListener { 38 private static final String TAG = "ConnectSpecificProfilesActivity"; 39 40 private static final String KEY_ONLINE_MODE = "online_mode"; 41 private static final String KEY_TITLE = "title"; 42 private static final String KEY_PROFILE_CONTAINER = "profile_container"; 43 44 public static final String EXTRA_ADDRESS = "address"; 45 46 private LocalBluetoothManager mManager; 47 private LocalBluetoothDevice mDevice; 48 49 private PreferenceGroup mProfileContainer; 50 private CheckBoxPreference mOnlineModePreference; 51 52 /** 53 * The current mode of this activity and its checkboxes (either online mode 54 * or offline mode). In online mode, user interactions with the profile 55 * checkboxes will also toggle the profile's connectivity. In offline mode, 56 * they will not, and only the preferred state will be saved for the 57 * profile. 58 */ 59 private boolean mOnlineMode; 60 61 @Override onCreate(Bundle savedInstanceState)62 protected void onCreate(Bundle savedInstanceState) { 63 super.onCreate(savedInstanceState); 64 65 String address; 66 if (savedInstanceState != null) { 67 address = savedInstanceState.getString(EXTRA_ADDRESS); 68 } else { 69 Intent intent = getIntent(); 70 address = intent.getStringExtra(EXTRA_ADDRESS); 71 } 72 73 if (TextUtils.isEmpty(address)) { 74 Log.w(TAG, "Activity started without address"); 75 finish(); 76 } 77 78 mManager = LocalBluetoothManager.getInstance(this); 79 mDevice = mManager.getLocalDeviceManager().findDevice(address); 80 if (mDevice == null) { 81 Log.w(TAG, "Device not found, cannot connect to it"); 82 finish(); 83 } 84 85 addPreferencesFromResource(R.xml.bluetooth_device_advanced); 86 mProfileContainer = (PreferenceGroup) findPreference(KEY_PROFILE_CONTAINER); 87 88 // Set the title of the screen 89 findPreference(KEY_TITLE).setTitle( 90 getString(R.string.bluetooth_device_advanced_title, mDevice.getName())); 91 92 // Listen for check/uncheck of the online mode checkbox 93 mOnlineModePreference = (CheckBoxPreference) findPreference(KEY_ONLINE_MODE); 94 mOnlineModePreference.setOnPreferenceChangeListener(this); 95 96 // Add a preference for each profile 97 addPreferencesForProfiles(); 98 } 99 100 @Override onSaveInstanceState(Bundle outState)101 protected void onSaveInstanceState(Bundle outState) { 102 super.onSaveInstanceState(outState); 103 104 outState.putString(EXTRA_ADDRESS, mDevice.getAddress()); 105 } 106 107 @Override onResume()108 protected void onResume() { 109 super.onResume(); 110 111 mManager.setForegroundActivity(this); 112 mDevice.registerCallback(this); 113 114 refresh(); 115 } 116 117 @Override onPause()118 protected void onPause() { 119 super.onPause(); 120 121 mDevice.unregisterCallback(this); 122 mManager.setForegroundActivity(null); 123 } 124 addPreferencesForProfiles()125 private void addPreferencesForProfiles() { 126 for (Profile profile : mDevice.getProfiles()) { 127 Preference pref = createProfilePreference(profile); 128 mProfileContainer.addPreference(pref); 129 } 130 } 131 132 /** 133 * Creates a checkbox preference for the particular profile. The key will be 134 * the profile's name. 135 * 136 * @param profile The profile for which the preference controls. 137 * @return A preference that allows the user to choose whether this profile 138 * will be connected to. 139 */ createProfilePreference(Profile profile)140 private CheckBoxPreference createProfilePreference(Profile profile) { 141 CheckBoxPreference pref = new CheckBoxPreference(this); 142 pref.setKey(profile.toString()); 143 pref.setTitle(profile.localizedString); 144 pref.setPersistent(false); 145 pref.setOnPreferenceChangeListener(this); 146 147 refreshProfilePreference(pref, profile); 148 149 return pref; 150 } 151 onPreferenceChange(Preference preference, Object newValue)152 public boolean onPreferenceChange(Preference preference, Object newValue) { 153 String key = preference.getKey(); 154 if (TextUtils.isEmpty(key) || newValue == null) return true; 155 156 if (key.equals(KEY_ONLINE_MODE)) { 157 onOnlineModeCheckedStateChanged((Boolean) newValue); 158 159 } else { 160 Profile profile = getProfileOf(preference); 161 if (profile == null) return false; 162 onProfileCheckedStateChanged(profile, (Boolean) newValue); 163 } 164 165 return true; 166 } 167 onOnlineModeCheckedStateChanged(boolean checked)168 private void onOnlineModeCheckedStateChanged(boolean checked) { 169 setOnlineMode(checked, true); 170 } 171 onProfileCheckedStateChanged(Profile profile, boolean checked)172 private void onProfileCheckedStateChanged(Profile profile, boolean checked) { 173 if (mOnlineMode) { 174 if (checked) { 175 mDevice.connect(profile); 176 } else { 177 mDevice.disconnect(profile); 178 } 179 } 180 181 LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager 182 .getProfileManager(mManager, profile); 183 profileManager.setPreferred(mDevice.getAddress(), checked); 184 } 185 onDeviceAttributesChanged(LocalBluetoothDevice device)186 public void onDeviceAttributesChanged(LocalBluetoothDevice device) { 187 refresh(); 188 } 189 refresh()190 private void refresh() { 191 // We are in 'online mode' if we are connected, connecting, or disconnecting 192 setOnlineMode(mDevice.isConnected() || mDevice.isBusy(), false); 193 refreshProfiles(); 194 } 195 196 /** 197 * Switches between online/offline mode. 198 * 199 * @param onlineMode Whether to be in online mode, or offline mode. 200 * @param takeAction Whether to take action (i.e., connect or disconnect) 201 * based on the new online mode. 202 */ setOnlineMode(boolean onlineMode, boolean takeAction)203 private void setOnlineMode(boolean onlineMode, boolean takeAction) { 204 mOnlineMode = onlineMode; 205 206 if (takeAction) { 207 if (onlineMode) { 208 mDevice.connect(); 209 } else { 210 mDevice.disconnect(); 211 } 212 } 213 214 refreshOnlineModePreference(); 215 } 216 refreshOnlineModePreference()217 private void refreshOnlineModePreference() { 218 mOnlineModePreference.setChecked(mOnlineMode); 219 220 /* Gray out checkbox while connecting and disconnecting */ 221 mOnlineModePreference.setEnabled(!mDevice.isBusy()); 222 223 /** 224 * If the device is online, show status. Otherwise, show a summary that 225 * describes what the checkbox does. 226 */ 227 mOnlineModePreference.setSummary(mOnlineMode ? mDevice.getSummary() 228 : R.string.bluetooth_device_advanced_online_mode_summary); 229 } 230 refreshProfiles()231 private void refreshProfiles() { 232 for (Profile profile : mDevice.getProfiles()) { 233 CheckBoxPreference profilePref = 234 (CheckBoxPreference) findPreference(profile.toString()); 235 if (profilePref == null) { 236 profilePref = createProfilePreference(profile); 237 mProfileContainer.addPreference(profilePref); 238 } else { 239 refreshProfilePreference(profilePref, profile); 240 } 241 } 242 } 243 refreshProfilePreference(CheckBoxPreference profilePref, Profile profile)244 private void refreshProfilePreference(CheckBoxPreference profilePref, Profile profile) { 245 String address = mDevice.getAddress(); 246 LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager 247 .getProfileManager(mManager, profile); 248 249 int connectionStatus = profileManager.getConnectionStatus(address); 250 251 /* Gray out checkbox while connecting and disconnecting */ 252 profilePref.setEnabled(!mDevice.isBusy()); 253 254 profilePref.setSummary(getProfileSummary(profileManager, profile, address, 255 connectionStatus, mOnlineMode)); 256 257 profilePref.setChecked(profileManager.isPreferred(address)); 258 } 259 getProfileOf(Preference pref)260 private Profile getProfileOf(Preference pref) { 261 if (!(pref instanceof CheckBoxPreference)) return null; 262 String key = pref.getKey(); 263 if (TextUtils.isEmpty(key)) return null; 264 265 try { 266 return Profile.valueOf(pref.getKey()); 267 } catch (IllegalArgumentException e) { 268 return null; 269 } 270 } 271 getProfileSummary(LocalBluetoothProfileManager profileManager, Profile profile, String address, int connectionStatus, boolean onlineMode)272 private static int getProfileSummary(LocalBluetoothProfileManager profileManager, 273 Profile profile, String address, int connectionStatus, boolean onlineMode) { 274 if (!onlineMode || connectionStatus == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) { 275 return getProfileSummaryForSettingPreference(profile); 276 } else { 277 return profileManager.getSummary(address); 278 } 279 } 280 281 /** 282 * Gets the summary that describes when checked, it will become a preferred profile. 283 * 284 * @param profile The profile to get the summary for. 285 * @return The summary. 286 */ getProfileSummaryForSettingPreference(Profile profile)287 private static final int getProfileSummaryForSettingPreference(Profile profile) { 288 switch (profile) { 289 case A2DP: 290 return R.string.bluetooth_a2dp_profile_summary_use_for; 291 case HEADSET: 292 return R.string.bluetooth_headset_profile_summary_use_for; 293 default: 294 return 0; 295 } 296 } 297 298 } 299