/*
* Copyright 2018 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.
*/
#pragma once
#include <base/bind.h>
#include <base/memory/weak_ptr.h>
#include <map>
#include <memory>
#include "avrcp_internal.h"
#include "packet/avrcp/avrcp_packet.h"
#include "packet/base/packet.h"
#include "profile/avrcp/device.h"
#include "raw_address.h"
namespace bluetooth {
namespace avrcp {
// TODO: Remove the singleton design structure for this class.
// AvrcpTargetService is already a singleton and can manage the lifetime of this
// object. multiple singleton objects can lead to code that is hard to test and
// have hard to debug lifetimes.
// TODO (apanicke): Use a device factory instead of just the constructor in
// order to create device objects. This will allow us to create specific device
// classes that can provide interop fixes for certain badly behaving devices.
/**
* ConnectionHandler handles SDP, connecting to remote AVRCP devices
* and multiplexing/delivering messages to devices.
*/
class ConnectionHandler {
public:
/**
* This callback is used to return a new device after a connection attempt.
* A reference to the new Avrcp device is located in the shared_ptr.
* If there was an issue during connection the pointer value will be null.
*/
using ConnectionCallback = base::Callback<void(std::shared_ptr<Device>)>;
/**
* Initializes the singleton instance and sets up SDP. Also Opens the
* AVRCP Acceptor to receive connection requests from a remote device.
*
* Params:
* callback - A callback that gets called any time a new AVRCP Device
* is connected. Will return nullpointer if a device fails
* to connect via ConnectDevice();
*
* TODO: Add message loop to determine which thread events are posted to
*/
static bool Initialize(const ConnectionCallback& callback,
AvrcpInterface* avrcp, SdpInterface* sdp,
VolumeInterface* vol);
/**
* Clears the singleton and tears down SDP
*/
static bool CleanUp();
/**
* Get the singleton instance of Connection Handler
*/
static ConnectionHandler* Get();
/**
* Attempt to connect AVRCP on a device. The callback will be called with
* either a smart pointer pointing to the connected AVRCP device or null
* if the connection failed.
*
* The order of operations for this function is as follows.
* 1. Perform SDP on remote device
* 2. Connect the AVCTP Channel
* 2. (Optional) If supported connect the AVCTP Browse channel
* 4. Call the provided callback with the new
*
* Params:
* bdaddr - Bluetooth address of device to connect to
* callback - The function that gets called when a connection succeeds or
* fails. The pointer being cleared implies that the connection
* failed.
*
* Returns:
* true if the connection attempt starts, false if there are no resources to
* connect AVRCP
*/
virtual bool ConnectDevice(const RawAddress& bdaddr);
/**
* Disconnects AVRCP from a device that was successfully connected too using
* ConnectionHandler::ConnectDevice
*
* Returns:
* true if the AVRCP was successfully disconnected for the device or false
* if the device was already disconnected or in an invalid state
*/
virtual bool DisconnectDevice(const RawAddress& bdaddr);
virtual std::vector<std::shared_ptr<Device>> GetListOfDevices() const;
/**
* Provide a custom ConnectionHandler that will be returned by Get().
* Initialize and CleanUp should not be called as the owner of the handler
* determines its lifetime.
*/
static void InitForTesting(ConnectionHandler* handler);
private:
AvrcpInterface* avrc_;
SdpInterface* sdp_;
VolumeInterface* vol_;
ConnectionCallback connection_cb_;
std::map<uint8_t, std::shared_ptr<Device>> device_map_;
// TODO (apanicke): Replace the features with a class that has individual
// fields.
std::map<RawAddress, uint16_t> feature_map_;
static ConnectionHandler* instance_;
using SdpCallback = base::Callback<void(uint16_t status, uint16_t version,
uint16_t features)>;
virtual bool SdpLookup(const RawAddress& bdaddr, SdpCallback cb);
void SdpCb(const RawAddress& bdaddr, SdpCallback cb,
tSDP_DISCOVERY_DB* disc_db, uint16_t status);
virtual bool AvrcpConnect(bool initiator, const RawAddress& bdaddr);
// Callbacks when connecting to a device
void InitiatorControlCb(uint8_t handle, uint8_t event, uint16_t result,
const RawAddress* peer_addr);
void AcceptorControlCb(uint8_t handle, uint8_t event, uint16_t result,
const RawAddress* peer_addr);
void MessageCb(uint8_t handle, uint8_t label, uint8_t opcode,
tAVRC_MSG* p_msg);
ConnectionHandler() : weak_ptr_factory_(this){};
virtual ~ConnectionHandler() = default;
// Callback for when sending a response to a device
void SendMessage(uint8_t handle, uint8_t label, bool browse,
std::unique_ptr<::bluetooth::PacketBuilder> message);
base::WeakPtrFactory<ConnectionHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ConnectionHandler);
};
} // namespace avrcp
} // namespace bluetooth