/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.bluetooth; import android.bluetooth.BluetoothDevice; import android.content.Intent; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceGroup; import android.text.TextUtils; import android.util.Log; import com.android.settings.R; import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; /** * ConnectSpecificProfilesActivity presents the user with all of the profiles * for a particular device, and allows him to choose which should be connected * (or disconnected). */ public class ConnectSpecificProfilesActivity extends PreferenceActivity implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener { private static final String TAG = "ConnectSpecificProfilesActivity"; private static final String KEY_ONLINE_MODE = "online_mode"; private static final String KEY_TITLE = "title"; private static final String KEY_PROFILE_CONTAINER = "profile_container"; public static final String EXTRA_DEVICE = "device"; private LocalBluetoothManager mManager; private CachedBluetoothDevice mCachedDevice; private PreferenceGroup mProfileContainer; private CheckBoxPreference mOnlineModePreference; /** * The current mode of this activity and its checkboxes (either online mode * or offline mode). In online mode, user interactions with the profile * checkboxes will also toggle the profile's connectivity. In offline mode, * they will not, and only the preferred state will be saved for the * profile. */ private boolean mOnlineMode; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); BluetoothDevice device; if (savedInstanceState != null) { device = savedInstanceState.getParcelable(EXTRA_DEVICE); } else { Intent intent = getIntent(); device = intent.getParcelableExtra(EXTRA_DEVICE); } if (device == null) { Log.w(TAG, "Activity started without a remote Bluetooth device"); finish(); } mManager = LocalBluetoothManager.getInstance(this); mCachedDevice = mManager.getCachedDeviceManager().findDevice(device); if (mCachedDevice == null) { Log.w(TAG, "Device not found, cannot connect to it"); finish(); } addPreferencesFromResource(R.xml.bluetooth_device_advanced); mProfileContainer = (PreferenceGroup) findPreference(KEY_PROFILE_CONTAINER); // Set the title of the screen findPreference(KEY_TITLE).setTitle( getString(R.string.bluetooth_device_advanced_title, mCachedDevice.getName())); // Listen for check/uncheck of the online mode checkbox mOnlineModePreference = (CheckBoxPreference) findPreference(KEY_ONLINE_MODE); mOnlineModePreference.setOnPreferenceChangeListener(this); // Add a preference for each profile addPreferencesForProfiles(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(EXTRA_DEVICE, mCachedDevice.getDevice()); } @Override protected void onResume() { super.onResume(); mManager.setForegroundActivity(this); mCachedDevice.registerCallback(this); refresh(); } @Override protected void onPause() { super.onPause(); mCachedDevice.unregisterCallback(this); mManager.setForegroundActivity(null); } private void addPreferencesForProfiles() { for (Profile profile : mCachedDevice.getConnectableProfiles()) { Preference pref = createProfilePreference(profile); mProfileContainer.addPreference(pref); } } /** * Creates a checkbox preference for the particular profile. The key will be * the profile's name. * * @param profile The profile for which the preference controls. * @return A preference that allows the user to choose whether this profile * will be connected to. */ private CheckBoxPreference createProfilePreference(Profile profile) { CheckBoxPreference pref = new CheckBoxPreference(this); pref.setKey(profile.toString()); pref.setTitle(profile.localizedString); pref.setPersistent(false); pref.setOnPreferenceChangeListener(this); LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager .getProfileManager(mManager, profile); /** * Gray out checkbox while connecting and disconnecting */ pref.setEnabled(!mCachedDevice.isBusy()); refreshProfilePreference(pref, profile); return pref; } public boolean onPreferenceChange(Preference preference, Object newValue) { String key = preference.getKey(); if (TextUtils.isEmpty(key) || newValue == null) return true; if (key.equals(KEY_ONLINE_MODE)) { onOnlineModeCheckedStateChanged((Boolean) newValue); } else { Profile profile = getProfileOf(preference); if (profile == null) return false; onProfileCheckedStateChanged(profile, (Boolean) newValue); } return true; } private void onOnlineModeCheckedStateChanged(boolean checked) { setOnlineMode(checked, true); } private void onProfileCheckedStateChanged(Profile profile, boolean checked) { LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager .getProfileManager(mManager, profile); profileManager.setPreferred(mCachedDevice.getDevice(), checked); if (mOnlineMode) { if (checked) { mCachedDevice.connect(profile); } else { mCachedDevice.disconnect(profile); } } } public void onDeviceAttributesChanged(CachedBluetoothDevice cachedDevice) { refresh(); } private void refresh() { // We are in 'online mode' if we are connected, connecting, or disconnecting setOnlineMode(mCachedDevice.isConnected() || mCachedDevice.isBusy(), false); refreshProfiles(); } /** * Switches between online/offline mode. * * @param onlineMode Whether to be in online mode, or offline mode. * @param takeAction Whether to take action (i.e., connect or disconnect) * based on the new online mode. */ private void setOnlineMode(boolean onlineMode, boolean takeAction) { mOnlineMode = onlineMode; if (takeAction) { if (onlineMode) { mCachedDevice.connect(); } else { mCachedDevice.disconnect(); } } refreshOnlineModePreference(); } private void refreshOnlineModePreference() { mOnlineModePreference.setChecked(mOnlineMode); /* Gray out checkbox while connecting and disconnecting */ mOnlineModePreference.setEnabled(!mCachedDevice.isBusy()); /** * If the device is online, show status. Otherwise, show a summary that * describes what the checkbox does. */ mOnlineModePreference.setSummary(mOnlineMode ? mCachedDevice.getSummary() : R.string.bluetooth_device_advanced_online_mode_summary); } private void refreshProfiles() { for (Profile profile : mCachedDevice.getConnectableProfiles()) { CheckBoxPreference profilePref = (CheckBoxPreference) findPreference(profile.toString()); if (profilePref == null) { profilePref = createProfilePreference(profile); mProfileContainer.addPreference(profilePref); } else { refreshProfilePreference(profilePref, profile); } } } private void refreshProfilePreference(CheckBoxPreference profilePref, Profile profile) { BluetoothDevice device = mCachedDevice.getDevice(); LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager .getProfileManager(mManager, profile); int connectionStatus = profileManager.getConnectionStatus(device); /* * Gray out checkbox while connecting and disconnecting */ profilePref.setEnabled(!mCachedDevice.isBusy()); profilePref.setSummary(getProfileSummary(profileManager, profile, device, connectionStatus, mOnlineMode)); profilePref.setChecked(profileManager.isPreferred(device)); } private Profile getProfileOf(Preference pref) { if (!(pref instanceof CheckBoxPreference)) return null; String key = pref.getKey(); if (TextUtils.isEmpty(key)) return null; try { return Profile.valueOf(pref.getKey()); } catch (IllegalArgumentException e) { return null; } } private static int getProfileSummary(LocalBluetoothProfileManager profileManager, Profile profile, BluetoothDevice device, int connectionStatus, boolean onlineMode) { if (!onlineMode || connectionStatus == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) { return getProfileSummaryForSettingPreference(profile); } else { return profileManager.getSummary(device); } } /** * Gets the summary that describes when checked, it will become a preferred profile. * * @param profile The profile to get the summary for. * @return The summary. */ private static final int getProfileSummaryForSettingPreference(Profile profile) { switch (profile) { case A2DP: return R.string.bluetooth_a2dp_profile_summary_use_for; case HEADSET: return R.string.bluetooth_headset_profile_summary_use_for; default: return 0; } } }