Home | History | Annotate | Download | only in bluetooth
      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.bluetooth.BluetoothClass;
     20 import android.bluetooth.BluetoothDevice;
     21 import android.bluetooth.BluetoothHeadset;
     22 import android.bluetooth.BluetoothProfile;
     23 import android.bluetooth.BluetoothUuid;
     24 import android.content.Context;
     25 import android.os.ParcelUuid;
     26 import android.util.Log;
     27 
     28 import com.android.settings.R;
     29 
     30 import java.util.List;
     31 
     32 /**
     33  * HeadsetProfile handles Bluetooth HFP and Headset profiles.
     34  */
     35 final class HeadsetProfile implements LocalBluetoothProfile {
     36     private static final String TAG = "HeadsetProfile";
     37 
     38     private BluetoothHeadset mService;
     39     private boolean mProfileReady;
     40 
     41     private final LocalBluetoothAdapter mLocalAdapter;
     42     private final CachedBluetoothDeviceManager mDeviceManager;
     43     private final LocalBluetoothProfileManager mProfileManager;
     44 
     45     static final ParcelUuid[] UUIDS = {
     46         BluetoothUuid.HSP,
     47         BluetoothUuid.Handsfree,
     48     };
     49 
     50     static final String NAME = "HEADSET";
     51 
     52     // Order of this profile in device profiles list
     53     private static final int ORDINAL = 0;
     54 
     55     // These callbacks run on the main thread.
     56     private final class HeadsetServiceListener
     57             implements BluetoothProfile.ServiceListener {
     58 
     59         public void onServiceConnected(int profile, BluetoothProfile proxy) {
     60             mService = (BluetoothHeadset) proxy;
     61             mProfileReady = true;
     62             // We just bound to the service, so refresh the UI of the
     63             // headset device.
     64             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
     65             if (deviceList.isEmpty()) {
     66                 return;
     67             }
     68             BluetoothDevice firstDevice = deviceList.get(0);
     69             CachedBluetoothDevice device = mDeviceManager.findDevice(firstDevice);
     70             // we may add a new device here, but generally this should not happen
     71             if (device == null) {
     72                 Log.w(TAG, "HeadsetProfile found new device: " + firstDevice);
     73                 device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, firstDevice);
     74             }
     75             device.onProfileStateChanged(HeadsetProfile.this,
     76                     BluetoothProfile.STATE_CONNECTED);
     77 
     78             mProfileManager.callServiceConnectedListeners();
     79         }
     80 
     81         public void onServiceDisconnected(int profile) {
     82             mProfileReady = false;
     83             mService = null;
     84             mProfileManager.callServiceDisconnectedListeners();
     85         }
     86     }
     87 
     88     // TODO(): The calls must get queued if mService becomes null.
     89     // It can happen when the phone app crashes for some reason.
     90     // All callers should have service listeners. Dock Service is the only
     91     // one right now.
     92     HeadsetProfile(Context context, LocalBluetoothAdapter adapter,
     93             CachedBluetoothDeviceManager deviceManager,
     94             LocalBluetoothProfileManager profileManager) {
     95         mLocalAdapter = adapter;
     96         mDeviceManager = deviceManager;
     97         mProfileManager = profileManager;
     98         mLocalAdapter.getProfileProxy(context, new HeadsetServiceListener(),
     99                 BluetoothProfile.HEADSET);
    100     }
    101 
    102     public boolean isConnectable() {
    103         return true;
    104     }
    105 
    106     public boolean isAutoConnectable() {
    107         return true;
    108     }
    109 
    110     public boolean connect(BluetoothDevice device) {
    111         List<BluetoothDevice> sinks = mService.getConnectedDevices();
    112         if (sinks != null) {
    113             for (BluetoothDevice sink : sinks) {
    114                 mService.disconnect(sink);
    115             }
    116         }
    117         return mService.connect(device);
    118     }
    119 
    120     public boolean disconnect(BluetoothDevice device) {
    121         List<BluetoothDevice> deviceList = mService.getConnectedDevices();
    122         if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) {
    123             // Downgrade priority as user is disconnecting the headset.
    124             if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
    125                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    126             }
    127             return mService.disconnect(device);
    128         } else {
    129             return false;
    130         }
    131     }
    132 
    133     public int getConnectionStatus(BluetoothDevice device) {
    134         if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
    135 
    136         List<BluetoothDevice> deviceList = mService.getConnectedDevices();
    137 
    138         return !deviceList.isEmpty() && deviceList.get(0).equals(device)
    139                 ? mService.getConnectionState(device)
    140                 : BluetoothProfile.STATE_DISCONNECTED;
    141     }
    142 
    143     public boolean isPreferred(BluetoothDevice device) {
    144         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
    145     }
    146 
    147     public int getPreferred(BluetoothDevice device) {
    148         return mService.getPriority(device);
    149     }
    150 
    151     public void setPreferred(BluetoothDevice device, boolean preferred) {
    152         if (preferred) {
    153             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
    154                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    155             }
    156         } else {
    157             mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
    158         }
    159     }
    160 
    161     public synchronized boolean isProfileReady() {
    162         return mProfileReady;
    163     }
    164 
    165     public String toString() {
    166         return NAME;
    167     }
    168 
    169     public int getOrdinal() {
    170         return ORDINAL;
    171     }
    172 
    173     public int getNameResource(BluetoothDevice device) {
    174         return R.string.bluetooth_profile_headset;
    175     }
    176 
    177     public int getSummaryResourceForDevice(BluetoothDevice device) {
    178         int state = mService.getConnectionState(device);
    179         switch (state) {
    180             case BluetoothProfile.STATE_DISCONNECTED:
    181                 return R.string.bluetooth_headset_profile_summary_use_for;
    182 
    183             case BluetoothProfile.STATE_CONNECTED:
    184                 return R.string.bluetooth_headset_profile_summary_connected;
    185 
    186             default:
    187                 return Utils.getConnectionStateSummary(state);
    188         }
    189     }
    190 
    191     public int getDrawableResource(BluetoothClass btClass) {
    192         return R.drawable.ic_bt_headset_hfp;
    193     }
    194 }
    195