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