1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/* 2436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Copyright (C) 2011 The Android Open Source Project 3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License. 6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at 7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and 14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License. 15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings.bluetooth; 18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 19afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.bluetooth.BluetoothA2dp; 20d63c0112251ab4e4e977545368dd703d875012a4Nick Pellyimport android.bluetooth.BluetoothDevice; 21afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.bluetooth.BluetoothHeadset; 225d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulzimport android.bluetooth.BluetoothMap; 23792d2132e408ded2b2d56646ba263808dd51fc31Adam Powellimport android.bluetooth.BluetoothInputDevice; 2432711b6752eb73324e1b10db975ac956888eda96Danica Changimport android.bluetooth.BluetoothPan; 250654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Battaimport android.bluetooth.BluetoothPbap; 265809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganeshimport android.bluetooth.BluetoothProfile; 272aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chanimport android.bluetooth.BluetoothUuid; 28436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.Context; 29436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.Intent; 303327f7887328c55ef2d837a8e2a07cea2070c744Michael Chanimport android.os.ParcelUuid; 31f2f3ceebbdf724e8904712a2a21cb0e677b7ea0dMichael Chanimport android.util.Log; 3200ec05985d6715daab7b15f105f0a9f3ada2ab83Swaminatha Balajiimport android.os.Handler; 3300ec05985d6715daab7b15f105f0a9f3ada2ab83Swaminatha Balajiimport android.os.Message; 34afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 35632a10f470d5086d18fab3eec89cef1d03e899c6Jake Hambyimport java.util.ArrayList; 36436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collection; 37afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.HashMap; 38afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.Map; 392ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balajiimport java.util.Set; 4000ec05985d6715daab7b15f105f0a9f3ada2ab83Swaminatha Balajiimport java.util.List; 41afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 42afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/** 43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile 44436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * objects for the available Bluetooth profiles. 45afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 46436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class LocalBluetoothProfileManager { 472aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan private static final String TAG = "LocalBluetoothProfileManager"; 485d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz private static final boolean DEBUG = Utils.D; 49436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** Singleton instance. */ 50436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static LocalBluetoothProfileManager sInstance; 5132711b6752eb73324e1b10db975ac956888eda96Danica Chang 5257d5585595810044e7727d4303214f69ff2d77d4Michael Chan /** 5357d5585595810044e7727d4303214f69ff2d77d4Michael Chan * An interface for notifying BluetoothHeadset IPC clients when they have 5457d5585595810044e7727d4303214f69ff2d77d4Michael Chan * been connected to the BluetoothHeadset service. 55436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Only used by {@link DockService}. 5657d5585595810044e7727d4303214f69ff2d77d4Michael Chan */ 5757d5585595810044e7727d4303214f69ff2d77d4Michael Chan public interface ServiceListener { 5857d5585595810044e7727d4303214f69ff2d77d4Michael Chan /** 5957d5585595810044e7727d4303214f69ff2d77d4Michael Chan * Called to notify the client when this proxy object has been 6057d5585595810044e7727d4303214f69ff2d77d4Michael Chan * connected to the BluetoothHeadset service. Clients must wait for 6157d5585595810044e7727d4303214f69ff2d77d4Michael Chan * this callback before making IPC calls on the BluetoothHeadset 6257d5585595810044e7727d4303214f69ff2d77d4Michael Chan * service. 6357d5585595810044e7727d4303214f69ff2d77d4Michael Chan */ 64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onServiceConnected(); 6557d5585595810044e7727d4303214f69ff2d77d4Michael Chan 6657d5585595810044e7727d4303214f69ff2d77d4Michael Chan /** 6757d5585595810044e7727d4303214f69ff2d77d4Michael Chan * Called to notify the client that this proxy object has been 6857d5585595810044e7727d4303214f69ff2d77d4Michael Chan * disconnected from the BluetoothHeadset service. Clients must not 6957d5585595810044e7727d4303214f69ff2d77d4Michael Chan * make IPC calls on the BluetoothHeadset service after this callback. 7057d5585595810044e7727d4303214f69ff2d77d4Michael Chan * This callback will currently only occur if the application hosting 7157d5585595810044e7727d4303214f69ff2d77d4Michael Chan * the BluetoothHeadset service, but may be called more often in future. 7257d5585595810044e7727d4303214f69ff2d77d4Michael Chan */ 73436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onServiceDisconnected(); 74f2f3ceebbdf724e8904712a2a21cb0e677b7ea0dMichael Chan } 752aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 76436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Context mContext; 77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final LocalBluetoothAdapter mLocalAdapter; 78436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final CachedBluetoothDeviceManager mDeviceManager; 79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final BluetoothEventManager mEventManager; 808c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh 81436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private A2dpProfile mA2dpProfile; 82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private HeadsetProfile mHeadsetProfile; 835d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz private MapProfile mMapProfile; 84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final HidProfile mHidProfile; 85436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private OppProfile mOppProfile; 86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final PanProfile mPanProfile; 870654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta private final PbapServerProfile mPbapProfile; 88b45e3c8fe9c08851800a6afa362d975944c0cd46Swaminatha Balaji 89afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 90436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Mapping from profile name, e.g. "HEADSET" to profile object. 91afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 92436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Map<String, LocalBluetoothProfile> 93436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileNameMap = new HashMap<String, LocalBluetoothProfile>(); 94afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 95436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothProfileManager(Context context, 96436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothAdapter adapter, 97436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDeviceManager deviceManager, 98436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothEventManager eventManager) { 99436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mContext = context; 100a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin 101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = adapter; 102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager = deviceManager; 103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mEventManager = eventManager; 104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // pass this reference to adapter and event manager (circular dependency) 105436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter.setProfileManager(this); 106436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mEventManager.setProfileManager(this); 107498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh 108436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ParcelUuid[] uuids = adapter.getUuids(); 109a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin 110436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // uuids may be null if Bluetooth is turned off 111436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (uuids != null) { 112436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby updateLocalProfiles(uuids); 113a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin } 114792d2132e408ded2b2d56646ba263808dd51fc31Adam Powell 115436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Always add HID and PAN profiles 11618c4317b93fce47109017efdab089dec4b01f790Jake Hamby mHidProfile = new HidProfile(context, mLocalAdapter, mDeviceManager, this); 117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addProfile(mHidProfile, HidProfile.NAME, 118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); 11932711b6752eb73324e1b10db975ac956888eda96Danica Chang 120436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mPanProfile = new PanProfile(context); 121c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby addPanProfile(mPanProfile, PanProfile.NAME, 122c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); 123c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 1245d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz if(DEBUG) Log.d(TAG, "Adding local MAP profile"); 1255d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz mMapProfile = new MapProfile(mContext, mLocalAdapter, 1265d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz mDeviceManager, this); 1275d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz addProfile(mMapProfile, MapProfile.NAME, 1285d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); 1295d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz 1300654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta //Create PBAP server profile, but do not add it to list of profiles 1310654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta // as we do not need to monitor the profile as part of profile list 1320654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta mPbapProfile = new PbapServerProfile(context); 1330654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta 1345d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete"); 135afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 136afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 137afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project /** 138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Initialize or update the local profile objects. If a UUID was previously 139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * present but has been removed, we print a warning but don't remove the 140436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * profile object as it might be referenced elsewhere, or the UUID might 141436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * come back and we don't want multiple copies of the profile objects. 142436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param uuids 143afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 144436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void updateLocalProfiles(ParcelUuid[] uuids) { 145436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // A2DP 146436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource)) { 147436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mA2dpProfile == null) { 1485d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz if(DEBUG) Log.d(TAG, "Adding local A2DP profile"); 14918c4317b93fce47109017efdab089dec4b01f790Jake Hamby mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this); 150436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addProfile(mA2dpProfile, A2dpProfile.NAME, 151436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); 152648bf5fd9e099cd677f7609afde831ac446deef0The Android Open Source Project } 153436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if (mA2dpProfile != null) { 154436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing."); 155436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 156436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 157436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Headset / Handsfree 158436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) || 159436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) { 160436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mHeadsetProfile == null) { 1615d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz if (DEBUG) Log.d(TAG, "Adding local HEADSET profile"); 162436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter, 163436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager, this); 164436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addProfile(mHeadsetProfile, HeadsetProfile.NAME, 165436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 1660bd445b974292dc3910b6bb85dcee7e7c378968fMichael Chan } 167436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if (mHeadsetProfile != null) { 168436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing."); 169afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 1702aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 171436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // OPP 172436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) { 173436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mOppProfile == null) { 1745d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz if(DEBUG) Log.d(TAG, "Adding local OPP profile"); 175436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mOppProfile = new OppProfile(); 176436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Note: no event handler for OPP, only name map. 177436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileNameMap.put(OppProfile.NAME, mOppProfile); 178afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 179436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if (mOppProfile != null) { 180436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.w(TAG, "Warning: OPP profile was previously added but the UUID is now missing."); 181afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 1826eb84ac6de9eeacc1e199d74310cf91f5a98daf2Jaikumar Ganesh mEventManager.registerProfileIntentReceiver(); 183afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 184436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // There is no local SDP record for HID and Settings app doesn't control PBAP 185afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 1862aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 187436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Collection<ServiceListener> mServiceListeners = 188436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<ServiceListener>(); 1892aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan 190436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void addProfile(LocalBluetoothProfile profile, 191436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby String profileName, String stateChangedAction) { 1926eb84ac6de9eeacc1e199d74310cf91f5a98daf2Jaikumar Ganesh mEventManager.addProfileHandler(stateChangedAction, new StateChangedHandler(profile)); 193436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileNameMap.put(profileName, profile); 194436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 195afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 196c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby private void addPanProfile(LocalBluetoothProfile profile, 197c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby String profileName, String stateChangedAction) { 198c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mEventManager.addProfileHandler(stateChangedAction, 199c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby new PanStateChangedHandler(profile)); 200c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mProfileNameMap.put(profileName, profile); 201c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 202c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 203436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothProfile getProfileByName(String name) { 204436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mProfileNameMap.get(name); 205436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 20648e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani 207436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Called from LocalBluetoothAdapter when state changes to ON 208436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setBluetoothStateOn() { 209436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ParcelUuid[] uuids = mLocalAdapter.getUuids(); 210436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (uuids != null) { 211436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby updateLocalProfiles(uuids); 21248e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani } 213436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mEventManager.readPairedDevices(); 214afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 215a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin 216a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin /** 217436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Generic handler for connection state change events for the specified profile. 218a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin */ 219436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class StateChangedHandler implements BluetoothEventManager.Handler { 220c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby final LocalBluetoothProfile mProfile; 221a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin 222436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby StateChangedHandler(LocalBluetoothProfile profile) { 223436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfile = profile; 224a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin } 225a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin 226436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, BluetoothDevice device) { 227436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 228436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice == null) { 229436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.w(TAG, "StateChangedHandler found new device: " + device); 230436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice = mDeviceManager.addDevice(mLocalAdapter, 231436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothProfileManager.this, device); 232a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin } 233436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0); 234436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0); 235436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (newState == BluetoothProfile.STATE_DISCONNECTED && 236436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby oldState == BluetoothProfile.STATE_CONNECTING) { 237436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.i(TAG, "Failed to connect " + mProfile + " device"); 238a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin } 23948e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani 240436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice.onProfileStateChanged(mProfile, newState); 241436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice.refresh(); 24248e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani } 243a41e2f94b792e44872be87f40fce182e6b39f4baYue Lixin } 244792d2132e408ded2b2d56646ba263808dd51fc31Adam Powell 245c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby /** State change handler for NAP and PANU profiles. */ 246c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby private class PanStateChangedHandler extends StateChangedHandler { 247c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 248c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby PanStateChangedHandler(LocalBluetoothProfile profile) { 249c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby super(profile); 250c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 251c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 252c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby @Override 253c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby public void onReceive(Context context, Intent intent, BluetoothDevice device) { 254c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby PanProfile panProfile = (PanProfile) mProfile; 255c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby int role = intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, 0); 256c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby panProfile.setLocalRole(device, role); 257c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby super.onReceive(context, intent, device); 258c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 259c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 260c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 261436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // called from DockService 262436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void addServiceListener(ServiceListener l) { 263436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mServiceListeners.add(l); 264436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 265792d2132e408ded2b2d56646ba263808dd51fc31Adam Powell 266436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // called from DockService 267436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void removeServiceListener(ServiceListener l) { 268436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mServiceListeners.remove(l); 269436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 270792d2132e408ded2b2d56646ba263808dd51fc31Adam Powell 271436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // not synchronized: use only from UI thread! (TODO: verify) 272436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void callServiceConnectedListeners() { 273436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (ServiceListener l : mServiceListeners) { 274436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby l.onServiceConnected(); 275792d2132e408ded2b2d56646ba263808dd51fc31Adam Powell } 276436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 27748e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani 278436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // not synchronized: use only from UI thread! (TODO: verify) 279436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void callServiceDisconnectedListeners() { 280436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (ServiceListener listener : mServiceListeners) { 281436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby listener.onServiceDisconnected(); 28248e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani } 283792d2132e408ded2b2d56646ba263808dd51fc31Adam Powell } 28432711b6752eb73324e1b10db975ac956888eda96Danica Chang 285436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // This is called by DockService, so check Headset and A2DP. 286436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public synchronized boolean isManagerReady() { 287436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Getting just the headset profile is fine for now. Will need to deal with A2DP 288436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // and others if they aren't always in a ready state. 289436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothProfile profile = mHeadsetProfile; 290436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile != null) { 291436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return profile.isProfileReady(); 2929ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh } 293436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profile = mA2dpProfile; 294436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile != null) { 295436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return profile.isProfileReady(); 2969ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh } 297436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 298436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 2999ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh 300436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby A2dpProfile getA2dpProfile() { 301436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mA2dpProfile; 302436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 30332711b6752eb73324e1b10db975ac956888eda96Danica Chang 304436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby HeadsetProfile getHeadsetProfile() { 305436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mHeadsetProfile; 306436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 30732711b6752eb73324e1b10db975ac956888eda96Danica Chang 3080654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta PbapServerProfile getPbapProfile(){ 3090654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta return mPbapProfile; 3100654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta } 3110654b71534411f4d93502f6ed8d8e864ef5b88efGanesh Ganapathi Batta 31200656b8e46e187e5fa63b8a80cd4f42367c1c924PauloftheWest MapProfile getMapProfile(){ 31300656b8e46e187e5fa63b8a80cd4f42367c1c924PauloftheWest return mMapProfile; 31400656b8e46e187e5fa63b8a80cd4f42367c1c924PauloftheWest } 31500656b8e46e187e5fa63b8a80cd4f42367c1c924PauloftheWest 316436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 317436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Fill in a list of LocalBluetoothProfile objects that are supported by 318436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * the local device and the remote device. 319436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 320436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param uuids of the remote device 321436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param localUuids UUIDs of the local device 322436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param profiles The list of profiles to fill 323c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby * @param removedProfiles list of profiles that were removed 324436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 325436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized void updateProfiles(ParcelUuid[] uuids, ParcelUuid[] localUuids, 326c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby Collection<LocalBluetoothProfile> profiles, 3276bce91bb9b14f82089f6ac90ca06f63a3aa3045cSyed Ibrahim M Collection<LocalBluetoothProfile> removedProfiles, 3281b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu boolean isPanNapConnected, BluetoothDevice device) { 329c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // Copy previous profile list into removedProfiles 330c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby removedProfiles.clear(); 331c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby removedProfiles.addAll(profiles); 332436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profiles.clear(); 33332711b6752eb73324e1b10db975ac956888eda96Danica Chang 334436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (uuids == null) { 335436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 33632711b6752eb73324e1b10db975ac956888eda96Danica Chang } 33732711b6752eb73324e1b10db975ac956888eda96Danica Chang 338436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mHeadsetProfile != null) { 339436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if ((BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.HSP_AG) && 340c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP)) || 341c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby (BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree_AG) && 342c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree))) { 343c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby profiles.add(mHeadsetProfile); 344c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby removedProfiles.remove(mHeadsetProfile); 34532711b6752eb73324e1b10db975ac956888eda96Danica Chang } 34632711b6752eb73324e1b10db975ac956888eda96Danica Chang } 34732711b6752eb73324e1b10db975ac956888eda96Danica Chang 348436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) && 349436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mA2dpProfile != null) { 350436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profiles.add(mA2dpProfile); 351c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby removedProfiles.remove(mA2dpProfile); 35232711b6752eb73324e1b10db975ac956888eda96Danica Chang } 35332711b6752eb73324e1b10db975ac956888eda96Danica Chang 354436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush) && 355436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mOppProfile != null) { 356436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profiles.add(mOppProfile); 357c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby removedProfiles.remove(mOppProfile); 35832711b6752eb73324e1b10db975ac956888eda96Danica Chang } 35932711b6752eb73324e1b10db975ac956888eda96Danica Chang 36079f3384eaa10d45270cb2f61a1314746da0e52ceAndre Eisenbach if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid) || 36179f3384eaa10d45270cb2f61a1314746da0e52ceAndre Eisenbach BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) && 362436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mHidProfile != null) { 363436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profiles.add(mHidProfile); 364c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby removedProfiles.remove(mHidProfile); 36532711b6752eb73324e1b10db975ac956888eda96Danica Chang } 36648e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani 3676bce91bb9b14f82089f6ac90ca06f63a3aa3045cSyed Ibrahim M if(isPanNapConnected) 3685d2595f05182910c1dd0ed1302bf59071b55ae79Kim Schulz if(DEBUG) Log.d(TAG, "Valid PAN-NAP connection exists."); 3696bce91bb9b14f82089f6ac90ca06f63a3aa3045cSyed Ibrahim M if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP) && 3706bce91bb9b14f82089f6ac90ca06f63a3aa3045cSyed Ibrahim M mPanProfile != null) || isPanNapConnected) { 371436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profiles.add(mPanProfile); 372c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby removedProfiles.remove(mPanProfile); 37348e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani } 3741b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu 3751b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu if ((mMapProfile != null) && 3761b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu (mMapProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) { 3771b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu profiles.add(mMapProfile); 3781b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu removedProfiles.remove(mMapProfile); 3791b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu mMapProfile.setPreferred(device, true); 3801b5bd091ebe4be7d714d19d5b35d8d7233a7713aZhihai Xu } 38132711b6752eb73324e1b10db975ac956888eda96Danica Chang } 38200ec05985d6715daab7b15f105f0a9f3ada2ab83Swaminatha Balaji 383afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project} 384