• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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.settingslib.bluetooth;
18 
19 import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL;
20 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
21 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
22 
23 import android.bluetooth.BluetoothAdapter;
24 import android.bluetooth.BluetoothClass;
25 import android.bluetooth.BluetoothDevice;
26 import android.bluetooth.BluetoothHeadset;
27 import android.bluetooth.BluetoothProfile;
28 import android.bluetooth.BluetoothUuid;
29 import android.content.Context;
30 import android.os.ParcelUuid;
31 import android.util.Log;
32 
33 import com.android.settingslib.R;
34 
35 import java.util.ArrayList;
36 import java.util.List;
37 
38 /**
39  * HeadsetProfile handles Bluetooth HFP and Headset profiles.
40  */
41 public class HeadsetProfile implements LocalBluetoothProfile {
42     private static final String TAG = "HeadsetProfile";
43 
44     private BluetoothHeadset mService;
45     private boolean mIsProfileReady;
46 
47     private final CachedBluetoothDeviceManager mDeviceManager;
48     private final LocalBluetoothProfileManager mProfileManager;
49     private final BluetoothAdapter mBluetoothAdapter;
50 
51     static final ParcelUuid[] UUIDS = {
52         BluetoothUuid.HSP,
53         BluetoothUuid.HFP,
54     };
55 
56     static final String NAME = "HEADSET";
57 
58     // Order of this profile in device profiles list
59     private static final int ORDINAL = 0;
60 
61     // These callbacks run on the main thread.
62     private final class HeadsetServiceListener
63             implements BluetoothProfile.ServiceListener {
64 
onServiceConnected(int profile, BluetoothProfile proxy)65         public void onServiceConnected(int profile, BluetoothProfile proxy) {
66             mService = (BluetoothHeadset) proxy;
67             // We just bound to the service, so refresh the UI for any connected HFP devices.
68             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
69             while (!deviceList.isEmpty()) {
70                 BluetoothDevice nextDevice = deviceList.remove(0);
71                 CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
72                 // we may add a new device here, but generally this should not happen
73                 if (device == null) {
74                     Log.w(TAG, "HeadsetProfile found new device: " + nextDevice);
75                     device = mDeviceManager.addDevice(nextDevice);
76                 }
77                 device.onProfileStateChanged(HeadsetProfile.this,
78                         BluetoothProfile.STATE_CONNECTED);
79                 device.refresh();
80             }
81             mIsProfileReady=true;
82             mProfileManager.callServiceConnectedListeners();
83         }
84 
onServiceDisconnected(int profile)85         public void onServiceDisconnected(int profile) {
86             mProfileManager.callServiceDisconnectedListeners();
87             mIsProfileReady=false;
88         }
89     }
90 
isProfileReady()91     public boolean isProfileReady() {
92         return mIsProfileReady;
93     }
94 
95     @Override
getProfileId()96     public int getProfileId() {
97         return BluetoothProfile.HEADSET;
98     }
99 
HeadsetProfile(Context context, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager)100     HeadsetProfile(Context context, CachedBluetoothDeviceManager deviceManager,
101             LocalBluetoothProfileManager profileManager) {
102         mDeviceManager = deviceManager;
103         mProfileManager = profileManager;
104         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
105         mBluetoothAdapter.getProfileProxy(context, new HeadsetServiceListener(),
106                 BluetoothProfile.HEADSET);
107     }
108 
accessProfileEnabled()109     public boolean accessProfileEnabled() {
110         return true;
111     }
112 
isAutoConnectable()113     public boolean isAutoConnectable() {
114         return true;
115     }
116 
getConnectionStatus(BluetoothDevice device)117     public int getConnectionStatus(BluetoothDevice device) {
118         if (mService == null) {
119             return BluetoothProfile.STATE_DISCONNECTED;
120         }
121         return mService.getConnectionState(device);
122     }
123 
setActiveDevice(BluetoothDevice device)124     public boolean setActiveDevice(BluetoothDevice device) {
125         if (mBluetoothAdapter == null) {
126             return false;
127         }
128 
129         return device == null
130                 ? mBluetoothAdapter.removeActiveDevice(ACTIVE_DEVICE_PHONE_CALL)
131                 : mBluetoothAdapter.setActiveDevice(device, ACTIVE_DEVICE_PHONE_CALL);
132     }
133 
getActiveDevice()134     public BluetoothDevice getActiveDevice() {
135         if (mService == null) {
136             return null;
137         }
138         return mService.getActiveDevice();
139     }
140 
isAudioOn()141     public boolean isAudioOn() {
142         if (mService == null) {
143             return false;
144         }
145         return mService.isAudioOn();
146     }
147 
getAudioState(BluetoothDevice device)148     public int getAudioState(BluetoothDevice device) {
149         if (mService == null) {
150             return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
151         }
152         return mService.getAudioState(device);
153     }
154 
155     @Override
isEnabled(BluetoothDevice device)156     public boolean isEnabled(BluetoothDevice device) {
157         if (mService == null) {
158             return false;
159         }
160         return mService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN;
161     }
162 
163     @Override
getConnectionPolicy(BluetoothDevice device)164     public int getConnectionPolicy(BluetoothDevice device) {
165         if (mService == null) {
166             return CONNECTION_POLICY_FORBIDDEN;
167         }
168         return mService.getConnectionPolicy(device);
169     }
170 
171     @Override
setEnabled(BluetoothDevice device, boolean enabled)172     public boolean setEnabled(BluetoothDevice device, boolean enabled) {
173         boolean isEnabled = false;
174         if (mService == null) {
175             return false;
176         }
177         if (enabled) {
178             if (mService.getConnectionPolicy(device) < CONNECTION_POLICY_ALLOWED) {
179                 isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
180             }
181         } else {
182             isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_FORBIDDEN);
183         }
184 
185         return isEnabled;
186     }
187 
getConnectedDevices()188     public List<BluetoothDevice> getConnectedDevices() {
189         if (mService == null) {
190             return new ArrayList<BluetoothDevice>(0);
191         }
192         return mService.getDevicesMatchingConnectionStates(
193               new int[] {BluetoothProfile.STATE_CONNECTED,
194                          BluetoothProfile.STATE_CONNECTING,
195                          BluetoothProfile.STATE_DISCONNECTING});
196     }
197 
toString()198     public String toString() {
199         return NAME;
200     }
201 
getOrdinal()202     public int getOrdinal() {
203         return ORDINAL;
204     }
205 
getNameResource(BluetoothDevice device)206     public int getNameResource(BluetoothDevice device) {
207         return R.string.bluetooth_profile_headset;
208     }
209 
getSummaryResourceForDevice(BluetoothDevice device)210     public int getSummaryResourceForDevice(BluetoothDevice device) {
211         int state = getConnectionStatus(device);
212         switch (state) {
213             case BluetoothProfile.STATE_DISCONNECTED:
214                 return R.string.bluetooth_headset_profile_summary_use_for;
215 
216             case BluetoothProfile.STATE_CONNECTED:
217                 return R.string.bluetooth_headset_profile_summary_connected;
218 
219             default:
220                 return BluetoothUtils.getConnectionStateSummary(state);
221         }
222     }
223 
getDrawableResource(BluetoothClass btClass)224     public int getDrawableResource(BluetoothClass btClass) {
225         return com.android.internal.R.drawable.ic_bt_headset_hfp;
226     }
227 
finalize()228     protected void finalize() {
229         Log.d(TAG, "finalize()");
230         if (mService != null) {
231             try {
232                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HEADSET,
233                                                                        mService);
234                 mService = null;
235             }catch (Throwable t) {
236                 Log.w(TAG, "Error cleaning up HID proxy", t);
237             }
238         }
239     }
240 }
241