| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROMECAST_DEVICE_BLUETOOTH_LE_GATT_CLIENT_MANAGER_IMPL_H_ |
| #define CHROMECAST_DEVICE_BLUETOOTH_LE_GATT_CLIENT_MANAGER_IMPL_H_ |
| |
| #include <deque> |
| #include <map> |
| #include <set> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/observer_list_threadsafe.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/timer/timer.h" |
| #include "chromecast/device/bluetooth/le/ble_notification_logger.h" |
| #include "chromecast/device/bluetooth/le/gatt_client_manager.h" |
| #include "chromecast/device/bluetooth/shlib/gatt_client.h" |
| #include "chromecast/public/bluetooth/gatt.h" |
| |
| namespace chromecast { |
| namespace bluetooth { |
| |
| class RemoteDeviceImpl; |
| |
| class GattClientManagerImpl |
| : public GattClientManager, |
| public bluetooth_v2_shlib::Gatt::Client::Delegate { |
| public: |
| // If a Connect request takes longer than this amount of time, we will treat |
| // it as a failure. |
| static constexpr base::TimeDelta kConnectTimeout = base::Seconds(40); |
| // If a Disconnect request takes longer than this amount of time, we will |
| // treat it as a failure. |
| static constexpr base::TimeDelta kDisconnectTimeout = base::Seconds(10); |
| // If a ReadRemoteRssi request takes longer than this amount of time, we will |
| // treat it as a failure. |
| static constexpr base::TimeDelta kReadRemoteRssiTimeout = base::Seconds(10); |
| |
| explicit GattClientManagerImpl(bluetooth_v2_shlib::GattClient* gatt_client); |
| |
| GattClientManagerImpl(const GattClientManagerImpl&) = delete; |
| GattClientManagerImpl& operator=(const GattClientManagerImpl&) = delete; |
| |
| ~GattClientManagerImpl() override; |
| |
| void InitializeOnIoThread(); |
| |
| // GattClientManager implementation: |
| void Initialize( |
| scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) override; |
| void Finalize() override; |
| void AddObserver(Observer* o) override; |
| void RemoveObserver(Observer* o) override; |
| void GetDevice( |
| const bluetooth_v2_shlib::Addr& addr, |
| base::OnceCallback<void(scoped_refptr<RemoteDevice>)> cb) override; |
| scoped_refptr<RemoteDevice> GetDeviceSync( |
| const bluetooth_v2_shlib::Addr& addr) override; |
| void GetConnectedDevices(GetConnectDevicesCallback cb) override; |
| void GetNumConnected(base::OnceCallback<void(size_t)> cb) const override; |
| void NotifyConnect(const bluetooth_v2_shlib::Addr& addr) override; |
| void NotifyBonded(const bluetooth_v2_shlib::Addr& addr) override; |
| bool IsConnectedLeDevice(const bluetooth_v2_shlib::Addr& addr) override; |
| bool SetGattClientConnectable(bool connectable) override; |
| void DisconnectAll(StatusCallback cb) override; |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner() override; |
| |
| // Add a Connect or Disconnect request to the queue. |is_connect| is true for |
| // Connect request and false for Disconnect request. They can only be executed |
| // serially. |transport| need only be set if is_connect == true and you wish |
| // to force a BT Classic or LE connection. |
| void EnqueueConnectRequest( |
| const bluetooth_v2_shlib::Addr& addr, |
| bool is_connect, |
| bluetooth_v2_shlib::Gatt::Client::Transport transport = bluetooth_v2_shlib::Gatt::Client::Transport::kAuto); |
| |
| // Add a ReadRemoteRssi request to the queue. They can only be executed |
| // serially. |
| void EnqueueReadRemoteRssiRequest(const bluetooth_v2_shlib::Addr& addr); |
| |
| // TODO(bcf): Should be private and passed into objects which need it (e.g. |
| // RemoteDevice, RemoteCharacteristic). |
| bluetooth_v2_shlib::GattClient* gatt_client() const { return gatt_client_; } |
| |
| bool gatt_client_connectable() const { return gatt_client_connectable_; } |
| |
| private: |
| // bluetooth_v2_shlib::Gatt::Client::Delegate implementation: |
| void OnConnectChanged(const bluetooth_v2_shlib::Addr& addr, |
| bool status, |
| bool connected) override; |
| void OnBondChanged(const bluetooth_v2_shlib::Addr& addr, |
| bool status, |
| bool bonded) override; |
| void OnNotification(const bluetooth_v2_shlib::Addr& addr, |
| uint16_t handle, |
| const std::vector<uint8_t>& value) override; |
| void OnCharacteristicReadResponse(const bluetooth_v2_shlib::Addr& addr, |
| bool status, |
| uint16_t handle, |
| const std::vector<uint8_t>& value) override; |
| void OnCharacteristicWriteResponse(const bluetooth_v2_shlib::Addr& addr, |
| bool status, |
| uint16_t handle) override; |
| void OnDescriptorReadResponse(const bluetooth_v2_shlib::Addr& addr, |
| bool status, |
| uint16_t handle, |
| const std::vector<uint8_t>& value) override; |
| void OnDescriptorWriteResponse(const bluetooth_v2_shlib::Addr& addr, |
| bool status, |
| uint16_t handle) override; |
| void OnReadRemoteRssi(const bluetooth_v2_shlib::Addr& addr, |
| bool status, |
| int rssi) override; |
| void OnMtuChanged(const bluetooth_v2_shlib::Addr& addr, |
| bool status, |
| int mtu) override; |
| void OnGetServices( |
| const bluetooth_v2_shlib::Addr& addr, |
| const std::vector<bluetooth_v2_shlib::Gatt::Service>& services) override; |
| void OnServicesRemoved(const bluetooth_v2_shlib::Addr& addr, |
| uint16_t start_handle, |
| uint16_t end_handle) override; |
| void OnServicesAdded( |
| const bluetooth_v2_shlib::Addr& addr, |
| const std::vector<bluetooth_v2_shlib::Gatt::Service>& services) override; |
| |
| void RunQueuedConnectRequest(); |
| void RunQueuedReadRemoteRssiRequest(); |
| void DisconnectAllComplete(bool success); |
| |
| void OnConnectTimeout(const bluetooth_v2_shlib::Addr& addr); |
| void OnDisconnectTimeout(const bluetooth_v2_shlib::Addr& addr); |
| void OnReadRemoteRssiTimeout(const bluetooth_v2_shlib::Addr& addr); |
| |
| void FinalizeOnIoThread(); |
| |
| const raw_ptr<bluetooth_v2_shlib::GattClient> gatt_client_; |
| |
| scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_; |
| |
| // All bluetooth_v2_shlib calls are run on this task_runner. Following members |
| // must only be accessed on this task runner. |
| scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
| |
| // TODO(bcf): Need to delete on disconnect. |
| std::map<bluetooth_v2_shlib::Addr, scoped_refptr<RemoteDeviceImpl>> |
| addr_to_device_; |
| std::set<bluetooth_v2_shlib::Addr> connected_devices_; |
| |
| // Timer for pending Connect requests. If any Connect request times out, we |
| // will treat it as a failure. |
| base::OneShotTimer connect_timeout_timer_; |
| |
| // Timer for pending Disconnect requests. If any Disconnect request times out, |
| // we will treat it as a failure. |
| base::OneShotTimer disconnect_timeout_timer_; |
| |
| // Timer for pending ReadRemoteRssi requests. If any ReadRemoteRssi request |
| // times out, we will treat it as a failure. |
| base::OneShotTimer read_remote_rssi_timeout_timer_; |
| |
| // Queue for concurrent Connect/Disconnect requests. Each request is |
| // represented using a <addr, is_connect> pair. |is_connect| is true for |
| // Connect requests and false for Disconnect requests. |
| struct PendingRequest { |
| PendingRequest(const bluetooth_v2_shlib::Addr& addr, |
| bool is_connect, |
| bluetooth_v2_shlib::Gatt::Client::Transport transport); |
| ~PendingRequest(); |
| |
| bluetooth_v2_shlib::Addr addr; |
| bool is_connect; |
| bluetooth_v2_shlib::Gatt::Client::Transport transport; |
| }; |
| std::deque<PendingRequest> pending_connect_requests_; |
| |
| bool disconnect_all_pending_ = false; |
| |
| // True if we are allowed connect to a remote device. This value should be set |
| // false when device is in GATT server mode. |
| bool gatt_client_connectable_ = true; |
| |
| // Callback of DisconnectAll request. |
| StatusCallback disconnect_all_cb_; |
| |
| // Queue for concurrent ReadRemoteRssi requests. |
| std::deque<bluetooth_v2_shlib::Addr> pending_read_remote_rssi_requests_; |
| |
| BleNotificationLogger notification_logger_; |
| |
| base::WeakPtr<GattClientManagerImpl> weak_this_; |
| std::unique_ptr<base::WeakPtrFactory<GattClientManagerImpl>> weak_factory_; |
| }; |
| |
| } // namespace bluetooth |
| } // namespace chromecast |
| |
| #endif // CHROMECAST_DEVICE_BLUETOOTH_LE_GATT_CLIENT_MANAGER_IMPL_H_ |