17ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/*
27ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Copyright (C) 2011 The Android Open Source Project
37ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
47ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
57ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * you may not use this file except in compliance with the License.
67ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * You may obtain a copy of the License at
77ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
87ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
97ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Unless required by applicable law or agreed to in writing, software
117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * See the License for the specific language governing permissions and
147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * limitations under the License.
157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */
167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkpackage com.android.settingslib.bluetooth;
187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothA2dp;
201bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwalimport android.bluetooth.BluetoothA2dpSink;
217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothDevice;
227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothHeadset;
23f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwalimport android.bluetooth.BluetoothHeadsetClient;
247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothMap;
25631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.bluetooth.BluetoothMapClient;
267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothInputDevice;
277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothPan;
28563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzoimport android.bluetooth.BluetoothPbapClient;
297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothProfile;
307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothUuid;
317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.Context;
327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.Intent;
337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.os.ParcelUuid;
347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.util.Log;
357aeb3f54408a7bd0c1ca3020bca32900b2091b1dAndrew Sappersteinimport com.android.internal.R;
367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.ArrayList;
377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.Collection;
387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.HashMap;
397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.Map;
407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/**
427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * objects for the available Bluetooth profiles.
447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */
45374d259815b801010cafd3c63aa0f1afb75a7fa6Antony Sargentpublic class LocalBluetoothProfileManager {
467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final String TAG = "LocalBluetoothProfileManager";
477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final boolean DEBUG = Utils.D;
487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Singleton instance. */
497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static LocalBluetoothProfileManager sInstance;
507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * An interface for notifying BluetoothHeadset IPC clients when they have
537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * been connected to the BluetoothHeadset service.
547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Only used by com.android.settings.bluetooth.DockService.
557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public interface ServiceListener {
577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        /**
587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * Called to notify the client when this proxy object has been
597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * connected to the BluetoothHeadset service. Clients must wait for
607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * this callback before making IPC calls on the BluetoothHeadset
617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * service.
627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         */
637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        void onServiceConnected();
647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        /**
667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * Called to notify the client that this proxy object has been
677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * disconnected from the BluetoothHeadset service. Clients must not
687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * make IPC calls on the BluetoothHeadset service after this callback.
697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * This callback will currently only occur if the application hosting
707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         * the BluetoothHeadset service, but may be called more often in future.
717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk         */
727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        void onServiceDisconnected();
737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final Context mContext;
767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final LocalBluetoothAdapter mLocalAdapter;
777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final CachedBluetoothDeviceManager mDeviceManager;
787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final BluetoothEventManager mEventManager;
797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private A2dpProfile mA2dpProfile;
811bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    private A2dpSinkProfile mA2dpSinkProfile;
827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private HeadsetProfile mHeadsetProfile;
83f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal    private HfpClientProfile mHfpClientProfile;
847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private MapProfile mMapProfile;
85631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo    private MapClientProfile mMapClientProfile;
867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final HidProfile mHidProfile;
877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private OppProfile mOppProfile;
887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final PanProfile mPanProfile;
89563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    private PbapClientProfile mPbapClientProfile;
907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final PbapServerProfile mPbapProfile;
91563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    private final boolean mUsePbapPce;
92631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo    private final boolean mUseMapClient;
937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Mapping from profile name, e.g. "HEADSET" to profile object.
967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final Map<String, LocalBluetoothProfile>
987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mProfileNameMap = new HashMap<String, LocalBluetoothProfile>();
997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    LocalBluetoothProfileManager(Context context,
1017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            LocalBluetoothAdapter adapter,
1027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            CachedBluetoothDeviceManager deviceManager,
1037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            BluetoothEventManager eventManager) {
1047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mContext = context;
1057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mLocalAdapter = adapter;
1077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mDeviceManager = deviceManager;
1087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mEventManager = eventManager;
109563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        mUsePbapPce = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
110631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        // MAP Client is typically used in the same situations as PBAP Client
111631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        mUseMapClient = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
1127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // pass this reference to adapter and event manager (circular dependency)
1137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mLocalAdapter.setProfileManager(this);
1147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mEventManager.setProfileManager(this);
1157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        ParcelUuid[] uuids = adapter.getUuids();
1177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // uuids may be null if Bluetooth is turned off
1197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (uuids != null) {
1207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            updateLocalProfiles(uuids);
1217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // Always add HID and PAN profiles
1247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mHidProfile = new HidProfile(context, mLocalAdapter, mDeviceManager, this);
1257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        addProfile(mHidProfile, HidProfile.NAME,
1267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
1277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mPanProfile = new PanProfile(context);
1297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        addPanProfile(mPanProfile, PanProfile.NAME,
1307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
1317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if(DEBUG) Log.d(TAG, "Adding local MAP profile");
133631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        if (mUseMapClient) {
134631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
135631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            addProfile(mMapClientProfile, MapClientProfile.NAME,
136631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo                BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
137631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        } else {
138631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            mMapProfile = new MapProfile(mContext, mLocalAdapter, mDeviceManager, this);
139631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            addProfile(mMapProfile, MapProfile.NAME,
140631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo                    BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
141631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        }
1427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk       //Create PBAP server profile, but do not add it to list of profiles
1447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk       // as we do not need to monitor the profile as part of profile list
1457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mPbapProfile = new PbapServerProfile(context);
1467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
1487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
1517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Initialize or update the local profile objects. If a UUID was previously
1527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * present but has been removed, we print a warning but don't remove the
1537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * profile object as it might be referenced elsewhere, or the UUID might
1547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * come back and we don't want multiple copies of the profile objects.
1557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param uuids
1567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
1577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    void updateLocalProfiles(ParcelUuid[] uuids) {
1581bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        // A2DP SRC
1597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource)) {
1607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (mA2dpProfile == null) {
1611bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                if(DEBUG) Log.d(TAG, "Adding local A2DP SRC profile");
1627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this);
1637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                addProfile(mA2dpProfile, A2dpProfile.NAME,
1647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                        BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
1657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        } else if (mA2dpProfile != null) {
1677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing.");
1687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
170f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        // A2DP SINK
1711bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
1721bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            if (mA2dpSinkProfile == null) {
1731bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                if(DEBUG) Log.d(TAG, "Adding local A2DP Sink profile");
1741bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                mA2dpSinkProfile = new A2dpSinkProfile(mContext, mLocalAdapter, mDeviceManager, this);
1751bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                addProfile(mA2dpSinkProfile, A2dpSinkProfile.NAME,
1761bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                        BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
1771bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            }
1781bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        } else if (mA2dpSinkProfile != null) {
1791bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            Log.w(TAG, "Warning: A2DP Sink profile was previously added but the UUID is now missing.");
1801bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        }
1811bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal
1827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // Headset / Handsfree
1837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) ||
1847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) {
1857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (mHeadsetProfile == null) {
1867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (DEBUG) Log.d(TAG, "Adding local HEADSET profile");
1877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter,
1887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                        mDeviceManager, this);
1897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                addProfile(mHeadsetProfile, HeadsetProfile.NAME,
1907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                        BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
1917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        } else if (mHeadsetProfile != null) {
1937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
1947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
196f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        // Headset HF
197f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) {
198f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal            if (mHfpClientProfile == null) {
199f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal                if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
200f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal                mHfpClientProfile =
201f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal                    new HfpClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
202f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal                addProfile(mHfpClientProfile, HfpClientProfile.NAME,
203f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal                        BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
204f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal            }
205f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        } else if (mHfpClientProfile != null) {
206f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal            Log.w(TAG,
207f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal                "Warning: Hfp Client profile was previously added but the UUID is now missing.");
208f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        } else {
209f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal            Log.d(TAG, "Handsfree Uuid not found.");
210f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        }
211f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal
212631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        // Message Access Profile Client
213631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.MNS)) {
214631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            if (mMapClientProfile == null) {
215631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo                if(DEBUG) Log.d(TAG, "Adding local Map Client profile");
216631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo                mMapClientProfile =
217631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo                        new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
218631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo                addProfile(mMapClientProfile, MapClientProfile.NAME,
219631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo                        BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
220631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            }
221631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        } else if (mMapClientProfile != null) {
222631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            Log.w(TAG,
223631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo                    "Warning: MAP Client profile was previously added but the UUID is now missing.");
224631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        } else {
225631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            Log.d(TAG, "MAP Client Uuid not found.");
226631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        }
227631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo
2287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // OPP
2297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
2307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (mOppProfile == null) {
2317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if(DEBUG) Log.d(TAG, "Adding local OPP profile");
2327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                mOppProfile = new OppProfile();
2337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                // Note: no event handler for OPP, only name map.
2347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                mProfileNameMap.put(OppProfile.NAME, mOppProfile);
2357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
2367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        } else if (mOppProfile != null) {
2377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            Log.w(TAG, "Warning: OPP profile was previously added but the UUID is now missing.");
2387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
239563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo
240563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        //PBAP Client
241563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (mUsePbapPce) {
242563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            if (mPbapClientProfile == null) {
243563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                if(DEBUG) Log.d(TAG, "Adding local PBAP Client profile");
244563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                mPbapClientProfile = new PbapClientProfile(mContext, mLocalAdapter, mDeviceManager,
245563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                        this);
246563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                addProfile(mPbapClientProfile, PbapClientProfile.NAME,
247563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                        BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
248563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            }
249563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        } else if (mPbapClientProfile != null) {
250563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            Log.w(TAG,
251563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                "Warning: PBAP Client profile was previously added but the UUID is now missing.");
252563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        }
253563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo
2547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mEventManager.registerProfileIntentReceiver();
2557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
256563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        // There is no local SDP record for HID and Settings app doesn't control PBAP Server.
2577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
2587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
2597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final Collection<ServiceListener> mServiceListeners =
2607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            new ArrayList<ServiceListener>();
2617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
2627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private void addProfile(LocalBluetoothProfile profile,
2637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            String profileName, String stateChangedAction) {
2647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mEventManager.addProfileHandler(stateChangedAction, new StateChangedHandler(profile));
2657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mProfileNameMap.put(profileName, profile);
2667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
2677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
2687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private void addPanProfile(LocalBluetoothProfile profile,
2697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            String profileName, String stateChangedAction) {
2707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mEventManager.addProfileHandler(stateChangedAction,
2717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                new PanStateChangedHandler(profile));
2727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mProfileNameMap.put(profileName, profile);
2737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
2747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
2757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public LocalBluetoothProfile getProfileByName(String name) {
2767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mProfileNameMap.get(name);
2777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
2787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
2797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // Called from LocalBluetoothAdapter when state changes to ON
2807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    void setBluetoothStateOn() {
2817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        ParcelUuid[] uuids = mLocalAdapter.getUuids();
2827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (uuids != null) {
2837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            updateLocalProfiles(uuids);
2847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
2857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mEventManager.readPairedDevices();
2867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
2877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
2887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
2897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Generic handler for connection state change events for the specified profile.
2907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
2917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private class StateChangedHandler implements BluetoothEventManager.Handler {
2927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        final LocalBluetoothProfile mProfile;
2937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
2947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        StateChangedHandler(LocalBluetoothProfile profile) {
2957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mProfile = profile;
2967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
2977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
2987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
2997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
3007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (cachedDevice == null) {
3017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                Log.w(TAG, "StateChangedHandler found new device: " + device);
3027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                cachedDevice = mDeviceManager.addDevice(mLocalAdapter,
3037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                        LocalBluetoothProfileManager.this, device);
3047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
3057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
3067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
3077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (newState == BluetoothProfile.STATE_DISCONNECTED &&
3087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    oldState == BluetoothProfile.STATE_CONNECTING) {
3097ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                Log.i(TAG, "Failed to connect " + mProfile + " device");
3107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
3117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            cachedDevice.onProfileStateChanged(mProfile, newState);
3137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            cachedDevice.refresh();
3147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
3157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** State change handler for NAP and PANU profiles. */
3187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private class PanStateChangedHandler extends StateChangedHandler {
3197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        PanStateChangedHandler(LocalBluetoothProfile profile) {
3217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            super(profile);
3227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
3237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        @Override
3257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
3267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            PanProfile panProfile = (PanProfile) mProfile;
3277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            int role = intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, 0);
3287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            panProfile.setLocalRole(device, role);
3297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            super.onReceive(context, intent, device);
3307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
3317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // called from DockService
3347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public void addServiceListener(ServiceListener l) {
3357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mServiceListeners.add(l);
3367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // called from DockService
3397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public void removeServiceListener(ServiceListener l) {
3407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mServiceListeners.remove(l);
3417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // not synchronized: use only from UI thread! (TODO: verify)
3447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    void callServiceConnectedListeners() {
3457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        for (ServiceListener l : mServiceListeners) {
3467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            l.onServiceConnected();
3477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
3487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // not synchronized: use only from UI thread! (TODO: verify)
3517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    void callServiceDisconnectedListeners() {
3527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        for (ServiceListener listener : mServiceListeners) {
3537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            listener.onServiceDisconnected();
3547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
3557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // This is called by DockService, so check Headset and A2DP.
3587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public synchronized boolean isManagerReady() {
3597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // Getting just the headset profile is fine for now. Will need to deal with A2DP
3607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // and others if they aren't always in a ready state.
3617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        LocalBluetoothProfile profile = mHeadsetProfile;
3627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (profile != null) {
3637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return profile.isProfileReady();
3647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
3657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        profile = mA2dpProfile;
3667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (profile != null) {
3677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return profile.isProfileReady();
3687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
3691bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        profile = mA2dpSinkProfile;
3701bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (profile != null) {
3711bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            return profile.isProfileReady();
3721bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        }
3737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return false;
3747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
3767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public A2dpProfile getA2dpProfile() {
3777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mA2dpProfile;
3787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
380f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal    public A2dpSinkProfile getA2dpSinkProfile() {
381f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        if ((mA2dpSinkProfile != null) && (mA2dpSinkProfile.isProfileReady())) {
382f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal            return mA2dpSinkProfile;
383f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        } else {
3841bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            return null;
385f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        }
3861bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    }
3871bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal
3887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public HeadsetProfile getHeadsetProfile() {
3897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mHeadsetProfile;
3907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
3917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
392f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal    public HfpClientProfile getHfpClientProfile() {
393f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        if ((mHfpClientProfile != null) && (mHfpClientProfile.isProfileReady())) {
394f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal            return mHfpClientProfile;
395f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        } else {
396f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal          return null;
397f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal        }
398f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal    }
399f8a1c9121dae665ec9dc29484f89adfb5f3f0886Sanket Agarwal
400563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    public PbapClientProfile getPbapClientProfile() {
401563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        return mPbapClientProfile;
402563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    }
403563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo
4047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public PbapServerProfile getPbapProfile(){
4057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mPbapProfile;
4067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
4077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
4087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public MapProfile getMapProfile(){
4097ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mMapProfile;
4107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
4117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
412631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo    public MapClientProfile getMapClientProfile() {
413631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        return mMapClientProfile;
414631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo    }
415631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo
4167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
4177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Fill in a list of LocalBluetoothProfile objects that are supported by
4187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * the local device and the remote device.
4197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     *
4207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param uuids of the remote device
4217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param localUuids UUIDs of the local device
4227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param profiles The list of profiles to fill
4237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param removedProfiles list of profiles that were removed
4247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
4257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    synchronized void updateProfiles(ParcelUuid[] uuids, ParcelUuid[] localUuids,
4267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            Collection<LocalBluetoothProfile> profiles,
4277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            Collection<LocalBluetoothProfile> removedProfiles,
4287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            boolean isPanNapConnected, BluetoothDevice device) {
4297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // Copy previous profile list into removedProfiles
4307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        removedProfiles.clear();
4317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        removedProfiles.addAll(profiles);
43299fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo        if (DEBUG) {
43399fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo            Log.d(TAG,"Current Profiles" + profiles.toString());
43499fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo        }
4357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        profiles.clear();
4367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
4377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (uuids == null) {
4387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return;
4397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
4407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
4417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (mHeadsetProfile != null) {
4427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if ((BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.HSP_AG) &&
4437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP)) ||
4447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    (BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree_AG) &&
4457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                            BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree))) {
4467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                profiles.add(mHeadsetProfile);
4477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                removedProfiles.remove(mHeadsetProfile);
4487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
4497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
4507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
45199fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo        if ((mHfpClientProfile != null) &&
45299fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo                BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) &&
45399fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo                BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree)) {
45499fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo            profiles.add(mHfpClientProfile);
45599fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo            removedProfiles.remove(mHfpClientProfile);
45699fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo        }
45799fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo
4587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) &&
4597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mA2dpProfile != null) {
4607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            profiles.add(mA2dpProfile);
4617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            removedProfiles.remove(mA2dpProfile);
4627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
4637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
4641bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (BluetoothUuid.containsAnyUuid(uuids, A2dpSinkProfile.SRC_UUIDS) &&
4651bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                mA2dpSinkProfile != null) {
4661bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                profiles.add(mA2dpSinkProfile);
4671bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                removedProfiles.remove(mA2dpSinkProfile);
46899fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo        }
4691bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal
4707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush) &&
4717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mOppProfile != null) {
4727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            profiles.add(mOppProfile);
4737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            removedProfiles.remove(mOppProfile);
4747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
4757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
4767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid) ||
4777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk             BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) &&
4787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mHidProfile != null) {
4797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            profiles.add(mHidProfile);
4807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            removedProfiles.remove(mHidProfile);
4817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
4827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
4837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if(isPanNapConnected)
4847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if(DEBUG) Log.d(TAG, "Valid PAN-NAP connection exists.");
4857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP) &&
4867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mPanProfile != null) || isPanNapConnected) {
4877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            profiles.add(mPanProfile);
4887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            removedProfiles.remove(mPanProfile);
4897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
4907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
4917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if ((mMapProfile != null) &&
4927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            (mMapProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) {
4937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            profiles.add(mMapProfile);
4947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            removedProfiles.remove(mMapProfile);
4957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mMapProfile.setPreferred(device, true);
4967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
4977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
498631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        if (mMapClientProfile != null) {
499631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            profiles.add(mMapClientProfile);
500631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo            removedProfiles.remove(mMapClientProfile);
501631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo        }
502631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo
503563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (mUsePbapPce) {
504563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            profiles.add(mPbapClientProfile);
505563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            removedProfiles.remove(mPbapClientProfile);
506563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            profiles.remove(mPbapProfile);
507563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            removedProfiles.add(mPbapProfile);
508563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        }
50999fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo
51099fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo        if (DEBUG) {
51199fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo            Log.d(TAG,"New Profiles" + profiles.toString());
51299fecc0dd7e1c2db0f4b173a69e2b3a96fef12ffJoseph Pirozzo        }
513563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    }
5147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk}
515