Ajay Panicker | 28da6c9 | 2018-02-27 20:51:47 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #pragma once |
| 18 | |
| 19 | #include <base/bind.h> |
Ajay Panicker | 9909165 | 2018-04-19 15:17:16 -0700 | [diff] [blame] | 20 | #include <base/memory/weak_ptr.h> |
Ajay Panicker | 28da6c9 | 2018-02-27 20:51:47 -0800 | [diff] [blame] | 21 | #include <map> |
| 22 | #include <memory> |
| 23 | |
| 24 | #include "avrcp_internal.h" |
| 25 | #include "avrcp_packet.h" |
| 26 | #include "device.h" |
| 27 | #include "packet.h" |
| 28 | #include "raw_address.h" |
| 29 | |
| 30 | namespace bluetooth { |
| 31 | namespace avrcp { |
| 32 | |
| 33 | // TODO: Remove the singleton design structure for this class. |
| 34 | // AvrcpTargetService is already a singleton and can manage the lifetime of this |
| 35 | // object. multiple singleton objects can lead to code that is hard to test and |
| 36 | // have hard to debug lifetimes. |
| 37 | |
| 38 | // TODO (apanicke): Use a device factory instead of just the constructor in |
| 39 | // order to create device objects. This will allow us to create specific device |
| 40 | // classes that can provide interop fixes for certain badly behaving devices. |
| 41 | |
| 42 | /** |
| 43 | * ConnectionHandler handles SDP, connecting to remote AVRCP devices |
| 44 | * and multiplexing/delivering messages to devices. |
| 45 | */ |
| 46 | class ConnectionHandler { |
| 47 | public: |
| 48 | /** |
| 49 | * This callback is used to return a new device after a connection attempt. |
| 50 | * A reference to the new Avrcp device is located in the shared_ptr. |
| 51 | * If there was an issue during connection the pointer value will be null. |
| 52 | */ |
| 53 | using ConnectionCallback = base::Callback<void(std::shared_ptr<Device>)>; |
| 54 | |
| 55 | /** |
| 56 | * Initializes the singleton instance and sets up SDP. Also Opens the |
| 57 | * AVRCP Acceptor to receive connection requests from a remote device. |
| 58 | * |
| 59 | * Params: |
| 60 | * callback - A callback that gets called any time a new AVRCP Device |
| 61 | * is connected. Will return nullpointer if a device fails |
| 62 | * to connect via ConnectDevice(); |
| 63 | * |
| 64 | * TODO: Add message loop to determine which thread events are posted to |
| 65 | */ |
| 66 | static bool Initialize(const ConnectionCallback& callback, |
Ajay Panicker | d473dd0 | 2018-04-13 11:49:34 -0700 | [diff] [blame] | 67 | AvrcpInterface* avrcp, SdpInterface* sdp, |
| 68 | VolumeInterface* vol); |
Ajay Panicker | 28da6c9 | 2018-02-27 20:51:47 -0800 | [diff] [blame] | 69 | |
| 70 | /** |
| 71 | * Clears the singleton and tears down SDP |
| 72 | */ |
| 73 | static bool CleanUp(); |
| 74 | |
| 75 | /** |
| 76 | * Get the singleton instance of Connection Handler |
| 77 | */ |
| 78 | static ConnectionHandler* Get(); |
| 79 | |
| 80 | /** |
| 81 | * Attempt to connect AVRCP on a device. The callback will be called with |
| 82 | * either a smart pointer pointing to the connected AVRCP device or null |
| 83 | * if the connection failed. |
| 84 | * |
Ajay Panicker | 7bed53d | 2018-03-31 14:38:53 -0700 | [diff] [blame] | 85 | * The order of operations for this function is as follows. |
Ajay Panicker | 28da6c9 | 2018-02-27 20:51:47 -0800 | [diff] [blame] | 86 | * 1. Perform SDP on remote device |
| 87 | * 2. Connect the AVCTP Channel |
| 88 | * 2. (Optional) If supported connect the AVCTP Browse channel |
| 89 | * 4. Call the provided callback with the new |
| 90 | * |
| 91 | * Params: |
| 92 | * bdaddr - Bluetooth address of device to connect to |
| 93 | * callback - The function that gets called when a connection succeeds or |
| 94 | * fails. The pointer being cleared implies that the connection |
| 95 | * failed. |
| 96 | * |
| 97 | * Returns: |
| 98 | * true if the connection attempt starts, false if there are no resources to |
| 99 | * connect AVRCP |
| 100 | */ |
| 101 | virtual bool ConnectDevice(const RawAddress& bdaddr); |
| 102 | |
| 103 | /** |
| 104 | * Disconnects AVRCP from a device that was successfully connected too using |
| 105 | * ConnectionHandler::ConnectDevice |
| 106 | * |
| 107 | * Returns: |
| 108 | * true if the AVRCP was successfully disconnected for the device or false |
| 109 | * if the device was already disconnected or in an invalid state |
| 110 | */ |
| 111 | virtual bool DisconnectDevice(const RawAddress& bdaddr); |
| 112 | |
| 113 | virtual std::vector<std::shared_ptr<Device>> GetListOfDevices() const; |
| 114 | |
| 115 | /** |
| 116 | * Provide a custom ConnectionHandler that will be returned by Get(). |
| 117 | * Initialize and CleanUp should not be called as the owner of the handler |
| 118 | * determines its lifetime. |
| 119 | */ |
| 120 | static void InitForTesting(ConnectionHandler* handler); |
| 121 | |
| 122 | private: |
| 123 | AvrcpInterface* avrc_; |
| 124 | SdpInterface* sdp_; |
Ajay Panicker | d473dd0 | 2018-04-13 11:49:34 -0700 | [diff] [blame] | 125 | VolumeInterface* vol_; |
Ajay Panicker | 28da6c9 | 2018-02-27 20:51:47 -0800 | [diff] [blame] | 126 | |
| 127 | ConnectionCallback connection_cb_; |
| 128 | |
| 129 | std::map<uint8_t, std::shared_ptr<Device>> device_map_; |
| 130 | // TODO (apanicke): Replace the features with a class that has individual |
| 131 | // fields. |
| 132 | std::map<RawAddress, uint16_t> feature_map_; |
| 133 | |
| 134 | static ConnectionHandler* instance_; |
| 135 | |
| 136 | using SdpCallback = base::Callback<void(uint16_t status, uint16_t version, |
| 137 | uint16_t features)>; |
| 138 | virtual bool SdpLookup(const RawAddress& bdaddr, SdpCallback cb); |
| 139 | void SdpCb(const RawAddress& bdaddr, SdpCallback cb, |
| 140 | tSDP_DISCOVERY_DB* disc_db, uint16_t status); |
| 141 | |
| 142 | virtual bool AvrcpConnect(bool initiator, const RawAddress& bdaddr); |
| 143 | |
| 144 | // Callbacks when connecting to a device |
| 145 | void InitiatorControlCb(uint8_t handle, uint8_t event, uint16_t result, |
| 146 | const RawAddress* peer_addr); |
| 147 | void AcceptorControlCb(uint8_t handle, uint8_t event, uint16_t result, |
| 148 | const RawAddress* peer_addr); |
| 149 | void MessageCb(uint8_t handle, uint8_t label, uint8_t opcode, |
| 150 | tAVRC_MSG* p_msg); |
| 151 | |
Ajay Panicker | 9909165 | 2018-04-19 15:17:16 -0700 | [diff] [blame] | 152 | ConnectionHandler() : weak_ptr_factory_(this){}; |
Ajay Panicker | 28da6c9 | 2018-02-27 20:51:47 -0800 | [diff] [blame] | 153 | virtual ~ConnectionHandler() = default; |
| 154 | |
| 155 | // Callback for when sending a response to a device |
| 156 | void SendMessage(uint8_t handle, uint8_t label, bool browse, |
| 157 | std::unique_ptr<::bluetooth::PacketBuilder> message); |
Ajay Panicker | 9909165 | 2018-04-19 15:17:16 -0700 | [diff] [blame] | 158 | |
| 159 | base::WeakPtrFactory<ConnectionHandler> weak_ptr_factory_; |
Ajay Panicker | 28da6c9 | 2018-02-27 20:51:47 -0800 | [diff] [blame] | 160 | DISALLOW_COPY_AND_ASSIGN(ConnectionHandler); |
| 161 | }; |
| 162 | |
| 163 | } // namespace avrcp |
Ajay Panicker | 9909165 | 2018-04-19 15:17:16 -0700 | [diff] [blame] | 164 | } // namespace bluetooth |