/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.telecom.bluetooth; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.telecom.Log; import com.android.server.telecom.BluetoothAdapterProxy; import com.android.server.telecom.BluetoothHeadsetProxy; import com.android.server.telecom.TelecomSystem; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; public class BluetoothDeviceManager { private final BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = new BluetoothProfile.ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { Log.startSession("BMSL.oSC"); try { synchronized (mLock) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadsetService = new BluetoothHeadsetProxy((BluetoothHeadset) proxy); Log.i(this, "- Got BluetoothHeadset: " + mBluetoothHeadsetService); } else { Log.w(this, "Connected to non-headset bluetooth service." + " Not changing bluetooth headset."); } } } finally { Log.endSession(); } } @Override public void onServiceDisconnected(int profile) { Log.startSession("BMSL.oSD"); try { synchronized (mLock) { mBluetoothHeadsetService = null; Log.i(BluetoothDeviceManager.this, "Lost BluetoothHeadset service. " + "Removing all tracked devices."); List devicesToRemove = new LinkedList<>( mConnectedDevicesByAddress.values()); mConnectedDevicesByAddress.clear(); for (BluetoothDevice device : devicesToRemove) { mBluetoothRouteManager.onDeviceLost(device.getAddress()); } } } finally { Log.endSession(); } } }; private final LinkedHashMap mConnectedDevicesByAddress = new LinkedHashMap<>(); private final TelecomSystem.SyncRoot mLock; private BluetoothRouteManager mBluetoothRouteManager; private BluetoothHeadsetProxy mBluetoothHeadsetService; public BluetoothDeviceManager(Context context, BluetoothAdapterProxy bluetoothAdapter, TelecomSystem.SyncRoot lock) { mLock = lock; if (bluetoothAdapter != null) { bluetoothAdapter.getProfileProxy(context, mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); } } public void setBluetoothRouteManager(BluetoothRouteManager brm) { mBluetoothRouteManager = brm; } public int getNumConnectedDevices() { return mConnectedDevicesByAddress.size(); } public Collection getConnectedDevices() { return mConnectedDevicesByAddress.values(); } public String getMostRecentlyConnectedDevice(String excludeAddress) { String result = null; synchronized (mLock) { for (String addr : mConnectedDevicesByAddress.keySet()) { if (!Objects.equals(addr, excludeAddress)) { result = addr; } } } return result; } public BluetoothHeadsetProxy getHeadsetService() { return mBluetoothHeadsetService; } public void setHeadsetServiceForTesting(BluetoothHeadsetProxy bluetoothHeadset) { mBluetoothHeadsetService = bluetoothHeadset; } public BluetoothDevice getDeviceFromAddress(String address) { return mConnectedDevicesByAddress.get(address); } void onDeviceConnected(BluetoothDevice device) { synchronized (mLock) { if (!mConnectedDevicesByAddress.containsKey(device.getAddress())) { mConnectedDevicesByAddress.put(device.getAddress(), device); mBluetoothRouteManager.onDeviceAdded(device.getAddress()); } } } void onDeviceDisconnected(BluetoothDevice device) { synchronized (mLock) { if (mConnectedDevicesByAddress.containsKey(device.getAddress())) { mConnectedDevicesByAddress.remove(device.getAddress()); mBluetoothRouteManager.onDeviceLost(device.getAddress()); } } } }