| /* | 
 |  * Copyright (C) 2012 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.settingslib.bluetooth; | 
 |  | 
 | import android.bluetooth.BluetoothAdapter; | 
 | import android.bluetooth.BluetoothClass; | 
 | import android.bluetooth.BluetoothDevice; | 
 | import android.bluetooth.BluetoothHeadset; | 
 | import android.bluetooth.BluetoothProfile; | 
 | import android.bluetooth.BluetoothUuid; | 
 | import android.content.Context; | 
 | import android.os.ParcelUuid; | 
 | import android.util.Log; | 
 |  | 
 | import com.android.settingslib.R; | 
 |  | 
 | import java.util.ArrayList; | 
 | import java.util.List; | 
 |  | 
 | /** | 
 |  * HeadsetProfile handles Bluetooth HFP and Headset profiles. | 
 |  */ | 
 | public class HeadsetProfile implements LocalBluetoothProfile { | 
 |     private static final String TAG = "HeadsetProfile"; | 
 |     private static boolean V = true; | 
 |  | 
 |     private BluetoothHeadset mService; | 
 |     private boolean mIsProfileReady; | 
 |  | 
 |     private final LocalBluetoothAdapter mLocalAdapter; | 
 |     private final CachedBluetoothDeviceManager mDeviceManager; | 
 |     private final LocalBluetoothProfileManager mProfileManager; | 
 |  | 
 |     static final ParcelUuid[] UUIDS = { | 
 |         BluetoothUuid.HSP, | 
 |         BluetoothUuid.Handsfree, | 
 |     }; | 
 |  | 
 |     static final String NAME = "HEADSET"; | 
 |  | 
 |     // Order of this profile in device profiles list | 
 |     private static final int ORDINAL = 0; | 
 |  | 
 |     // These callbacks run on the main thread. | 
 |     private final class HeadsetServiceListener | 
 |             implements BluetoothProfile.ServiceListener { | 
 |  | 
 |         public void onServiceConnected(int profile, BluetoothProfile proxy) { | 
 |             if (V) Log.d(TAG,"Bluetooth service connected"); | 
 |             mService = (BluetoothHeadset) proxy; | 
 |             // We just bound to the service, so refresh the UI for any connected HFP devices. | 
 |             List<BluetoothDevice> deviceList = mService.getConnectedDevices(); | 
 |             while (!deviceList.isEmpty()) { | 
 |                 BluetoothDevice nextDevice = deviceList.remove(0); | 
 |                 CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice); | 
 |                 // we may add a new device here, but generally this should not happen | 
 |                 if (device == null) { | 
 |                     Log.w(TAG, "HeadsetProfile found new device: " + nextDevice); | 
 |                     device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice); | 
 |                 } | 
 |                 device.onProfileStateChanged(HeadsetProfile.this, | 
 |                         BluetoothProfile.STATE_CONNECTED); | 
 |                 device.refresh(); | 
 |             } | 
 |  | 
 |             mProfileManager.callServiceConnectedListeners(); | 
 |             mIsProfileReady=true; | 
 |         } | 
 |  | 
 |         public void onServiceDisconnected(int profile) { | 
 |             if (V) Log.d(TAG,"Bluetooth service disconnected"); | 
 |             mProfileManager.callServiceDisconnectedListeners(); | 
 |             mIsProfileReady=false; | 
 |         } | 
 |     } | 
 |  | 
 |     public boolean isProfileReady() { | 
 |         return mIsProfileReady; | 
 |     } | 
 |  | 
 |     HeadsetProfile(Context context, LocalBluetoothAdapter adapter, | 
 |             CachedBluetoothDeviceManager deviceManager, | 
 |             LocalBluetoothProfileManager profileManager) { | 
 |         mLocalAdapter = adapter; | 
 |         mDeviceManager = deviceManager; | 
 |         mProfileManager = profileManager; | 
 |         mLocalAdapter.getProfileProxy(context, new HeadsetServiceListener(), | 
 |                 BluetoothProfile.HEADSET); | 
 |     } | 
 |  | 
 |     public boolean isConnectable() { | 
 |         return true; | 
 |     } | 
 |  | 
 |     public boolean isAutoConnectable() { | 
 |         return true; | 
 |     } | 
 |  | 
 |     public boolean connect(BluetoothDevice device) { | 
 |         if (mService == null) return false; | 
 |         List<BluetoothDevice> sinks = mService.getConnectedDevices(); | 
 |         if (sinks != null) { | 
 |             for (BluetoothDevice sink : sinks) { | 
 |                 Log.d(TAG,"Not disconnecting device = " + sink); | 
 |             } | 
 |         } | 
 |         return mService.connect(device); | 
 |     } | 
 |  | 
 |     public boolean disconnect(BluetoothDevice device) { | 
 |         if (mService == null) return false; | 
 |         List<BluetoothDevice> deviceList = mService.getConnectedDevices(); | 
 |         if (!deviceList.isEmpty()) { | 
 |             for (BluetoothDevice dev : deviceList) { | 
 |                 if (dev.equals(device)) { | 
 |                     if (V) Log.d(TAG,"Downgrade priority as user" + | 
 |                                         "is disconnecting the headset"); | 
 |                     // Downgrade priority as user is disconnecting the headset. | 
 |                     if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) { | 
 |                         mService.setPriority(device, BluetoothProfile.PRIORITY_ON); | 
 |                     } | 
 |                     return mService.disconnect(device); | 
 |                 } | 
 |             } | 
 |         } | 
 |         return false; | 
 |     } | 
 |  | 
 |     public int getConnectionStatus(BluetoothDevice device) { | 
 |         if (mService == null) return BluetoothProfile.STATE_DISCONNECTED; | 
 |         List<BluetoothDevice> deviceList = mService.getConnectedDevices(); | 
 |         if (!deviceList.isEmpty()){ | 
 |             for (BluetoothDevice dev : deviceList) { | 
 |                 if (dev.equals(device)) { | 
 |                     return mService.getConnectionState(device); | 
 |                 } | 
 |             } | 
 |         } | 
 |         return BluetoothProfile.STATE_DISCONNECTED; | 
 |     } | 
 |  | 
 |     public boolean setActiveDevice(BluetoothDevice device) { | 
 |         if (mService == null) return false; | 
 |         return mService.setActiveDevice(device); | 
 |     } | 
 |  | 
 |     public BluetoothDevice getActiveDevice() { | 
 |         if (mService == null) return null; | 
 |         return mService.getActiveDevice(); | 
 |     } | 
 |  | 
 |     public boolean isAudioOn() { | 
 |         if (mService == null) return false; | 
 |         return mService.isAudioOn(); | 
 |     } | 
 |  | 
 |     public boolean isPreferred(BluetoothDevice device) { | 
 |         if (mService == null) return false; | 
 |         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; | 
 |     } | 
 |  | 
 |     public int getPreferred(BluetoothDevice device) { | 
 |         if (mService == null) return BluetoothProfile.PRIORITY_OFF; | 
 |         return mService.getPriority(device); | 
 |     } | 
 |  | 
 |     public void setPreferred(BluetoothDevice device, boolean preferred) { | 
 |         if (mService == null) return; | 
 |         if (preferred) { | 
 |             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { | 
 |                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON); | 
 |             } | 
 |         } else { | 
 |             mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); | 
 |         } | 
 |     } | 
 |  | 
 |     public List<BluetoothDevice> getConnectedDevices() { | 
 |         if (mService == null) return new ArrayList<BluetoothDevice>(0); | 
 |         return mService.getDevicesMatchingConnectionStates( | 
 |               new int[] {BluetoothProfile.STATE_CONNECTED, | 
 |                          BluetoothProfile.STATE_CONNECTING, | 
 |                          BluetoothProfile.STATE_DISCONNECTING}); | 
 |     } | 
 |  | 
 |     public String toString() { | 
 |         return NAME; | 
 |     } | 
 |  | 
 |     public int getOrdinal() { | 
 |         return ORDINAL; | 
 |     } | 
 |  | 
 |     public int getNameResource(BluetoothDevice device) { | 
 |         return R.string.bluetooth_profile_headset; | 
 |     } | 
 |  | 
 |     public int getSummaryResourceForDevice(BluetoothDevice device) { | 
 |         int state = getConnectionStatus(device); | 
 |         switch (state) { | 
 |             case BluetoothProfile.STATE_DISCONNECTED: | 
 |                 return R.string.bluetooth_headset_profile_summary_use_for; | 
 |  | 
 |             case BluetoothProfile.STATE_CONNECTED: | 
 |                 return R.string.bluetooth_headset_profile_summary_connected; | 
 |  | 
 |             default: | 
 |                 return Utils.getConnectionStateSummary(state); | 
 |         } | 
 |     } | 
 |  | 
 |     public int getDrawableResource(BluetoothClass btClass) { | 
 |         return R.drawable.ic_bt_headset_hfp; | 
 |     } | 
 |  | 
 |     protected void finalize() { | 
 |         if (V) Log.d(TAG, "finalize()"); | 
 |         if (mService != null) { | 
 |             try { | 
 |                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HEADSET, | 
 |                                                                        mService); | 
 |                 mService = null; | 
 |             }catch (Throwable t) { | 
 |                 Log.w(TAG, "Error cleaning up HID proxy", t); | 
 |             } | 
 |         } | 
 |     } | 
 | } |