• 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 (mBluetoothAdapter == null) {
136             return null;
137         }
138         final List<BluetoothDevice> activeDevices = mBluetoothAdapter
139                 .getActiveDevices(BluetoothProfile.HEADSET);
140         return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
141     }
142 
getAudioState(BluetoothDevice device)143     public int getAudioState(BluetoothDevice device) {
144         if (mService == null) {
145             return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
146         }
147         return mService.getAudioState(device);
148     }
149 
150     @Override
isEnabled(BluetoothDevice device)151     public boolean isEnabled(BluetoothDevice device) {
152         if (mService == null) {
153             return false;
154         }
155         return mService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN;
156     }
157 
158     @Override
getConnectionPolicy(BluetoothDevice device)159     public int getConnectionPolicy(BluetoothDevice device) {
160         if (mService == null) {
161             return CONNECTION_POLICY_FORBIDDEN;
162         }
163         return mService.getConnectionPolicy(device);
164     }
165 
166     @Override
setEnabled(BluetoothDevice device, boolean enabled)167     public boolean setEnabled(BluetoothDevice device, boolean enabled) {
168         boolean isEnabled = false;
169         if (mService == null) {
170             return false;
171         }
172         if (enabled) {
173             if (mService.getConnectionPolicy(device) < CONNECTION_POLICY_ALLOWED) {
174                 isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
175             }
176         } else {
177             isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_FORBIDDEN);
178         }
179 
180         return isEnabled;
181     }
182 
getConnectedDevices()183     public List<BluetoothDevice> getConnectedDevices() {
184         if (mService == null) {
185             return new ArrayList<BluetoothDevice>(0);
186         }
187         return mService.getDevicesMatchingConnectionStates(
188               new int[] {BluetoothProfile.STATE_CONNECTED,
189                          BluetoothProfile.STATE_CONNECTING,
190                          BluetoothProfile.STATE_DISCONNECTING});
191     }
192 
toString()193     public String toString() {
194         return NAME;
195     }
196 
getOrdinal()197     public int getOrdinal() {
198         return ORDINAL;
199     }
200 
getNameResource(BluetoothDevice device)201     public int getNameResource(BluetoothDevice device) {
202         return R.string.bluetooth_profile_headset;
203     }
204 
getSummaryResourceForDevice(BluetoothDevice device)205     public int getSummaryResourceForDevice(BluetoothDevice device) {
206         int state = getConnectionStatus(device);
207         switch (state) {
208             case BluetoothProfile.STATE_DISCONNECTED:
209                 return R.string.bluetooth_headset_profile_summary_use_for;
210 
211             case BluetoothProfile.STATE_CONNECTED:
212                 return R.string.bluetooth_headset_profile_summary_connected;
213 
214             default:
215                 return BluetoothUtils.getConnectionStateSummary(state);
216         }
217     }
218 
getDrawableResource(BluetoothClass btClass)219     public int getDrawableResource(BluetoothClass btClass) {
220         return com.android.internal.R.drawable.ic_bt_headset_hfp;
221     }
222 
finalize()223     protected void finalize() {
224         Log.d(TAG, "finalize()");
225         if (mService != null) {
226             try {
227                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HEADSET,
228                                                                        mService);
229                 mService = null;
230             }catch (Throwable t) {
231                 Log.w(TAG, "Error cleaning up HID proxy", t);
232             }
233         }
234     }
235 }
236