• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
onServiceConnected(int profile, BluetoothProfile proxy)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 
onServiceDisconnected(int profile)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.
HeadsetProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager)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 
isConnectable()102     public boolean isConnectable() {
103         return true;
104     }
105 
isAutoConnectable()106     public boolean isAutoConnectable() {
107         return true;
108     }
109 
connect(BluetoothDevice device)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 
disconnect(BluetoothDevice device)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 
getConnectionStatus(BluetoothDevice device)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 
isPreferred(BluetoothDevice device)143     public boolean isPreferred(BluetoothDevice device) {
144         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
145     }
146 
getPreferred(BluetoothDevice device)147     public int getPreferred(BluetoothDevice device) {
148         return mService.getPriority(device);
149     }
150 
setPreferred(BluetoothDevice device, boolean preferred)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 
isProfileReady()161     public synchronized boolean isProfileReady() {
162         return mProfileReady;
163     }
164 
toString()165     public String toString() {
166         return NAME;
167     }
168 
getOrdinal()169     public int getOrdinal() {
170         return ORDINAL;
171     }
172 
getNameResource(BluetoothDevice device)173     public int getNameResource(BluetoothDevice device) {
174         return R.string.bluetooth_profile_headset;
175     }
176 
getSummaryResourceForDevice(BluetoothDevice device)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 
getDrawableResource(BluetoothClass btClass)191     public int getDrawableResource(BluetoothClass btClass) {
192         return R.drawable.ic_bt_headset_hfp;
193     }
194 }
195