1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
/*
* 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 <set>
#include <string>
#include <vector>
#include <base/callback_forward.h>
#include "avrcp_common.h"
#include "raw_address.h"
namespace bluetooth {
namespace avrcp {
struct SongInfo {
std::string media_id; // This gets converted to a UID in the native service
std::set<AttributeEntry> attributes;
};
enum PlayState : uint8_t {
STOPPED = 0x00,
PLAYING,
PAUSED,
FWD_SEEK,
REV_SEEK,
ERROR = 0xFF,
};
struct PlayStatus {
uint32_t position;
uint32_t duration;
PlayState state;
};
struct MediaPlayerInfo {
uint16_t id;
std::string name;
bool browsing_supported;
};
struct FolderInfo {
std::string media_id;
bool is_playable;
std::string name;
};
// TODO (apanicke): Convert this to a union
struct ListItem {
enum : uint8_t {
FOLDER,
SONG,
} type;
FolderInfo folder;
SongInfo song;
};
class MediaCallbacks {
public:
virtual void SendMediaUpdate(bool track_changed, bool play_state,
bool queue) = 0;
virtual void SendFolderUpdate(bool available_players, bool addressed_players,
bool uids_changed) = 0;
virtual void SendActiveDeviceChanged(const RawAddress& address) = 0;
virtual ~MediaCallbacks() = default;
};
// The classes below are used by the JNI and are loaded dynamically with the
// Bluetooth library. All classes must be pure virtual otherwise a compiler
// error occurs when trying to link the function implementation.
// MediaInterface defines the class that the AVRCP Service uses in order
// communicate with the media layer. The media layer will define its own
// implementation of this object and register it with the service using
// Avrcp::ServiceInterface::Init(). At this point the AVRCP Service will
// call RegisterUpdateCallbacks() to provide an handle to use to send
// notifications about changes in the Media Interface.
//
// NOTES: The current implementation has the native service handle all the
// thread switching. It will call the interface functions on the btif/jni
// thread and the callback will post its results to the bta thread.
// In the future the interface the JNI registered with the
// service should post all its tasks to the JNI thread itself so that the native
// service isn't aware of the thread the interface functions need to be called
// on. It can then supply callbacks that post results to the correct thread
// allowing the threading model to be totally encapsulated and allow correct
// behavior in case the threading model changes on either side.
class MediaInterface {
public:
virtual void SendKeyEvent(uint8_t key, KeyState state) = 0;
using SongInfoCallback = base::Callback<void(SongInfo)>;
virtual void GetSongInfo(SongInfoCallback info_cb) = 0;
using PlayStatusCallback = base::Callback<void(PlayStatus)>;
virtual void GetPlayStatus(PlayStatusCallback status_cb) = 0;
// Contains the current queue and the media ID of the currently playing item
// in the queue
using NowPlayingCallback =
base::Callback<void(std::string, std::vector<SongInfo>)>;
virtual void GetNowPlayingList(NowPlayingCallback now_playing_cb) = 0;
// TODO (apanicke): Use a map with the ID as the key instead of vector
// in follow up cleanup patches. This allows simplification of the
// MediaPlayerInfo object
using MediaListCallback =
base::Callback<void(uint16_t curr_player, std::vector<MediaPlayerInfo>)>;
virtual void GetMediaPlayerList(MediaListCallback list_cb) = 0;
using FolderItemsCallback = base::Callback<void(std::vector<ListItem>)>;
virtual void GetFolderItems(uint16_t player_id, std::string media_id,
FolderItemsCallback folder_cb) = 0;
using SetBrowsedPlayerCallback = base::Callback<void(
bool success, std::string root_id, uint32_t num_items)>;
virtual void SetBrowsedPlayer(uint16_t player_id,
SetBrowsedPlayerCallback browse_cb) = 0;
virtual void PlayItem(uint16_t player_id, bool now_playing,
std::string media_id) = 0;
virtual void SetActiveDevice(const RawAddress& address) = 0;
virtual void RegisterUpdateCallback(MediaCallbacks* callback) = 0;
virtual void UnregisterUpdateCallback(MediaCallbacks* callback) = 0;
MediaInterface() = default;
virtual ~MediaInterface() = default;
};
class VolumeInterface {
public:
// TODO (apanicke): Investigate the best value type for volume. Right now it
// is a value from 0-127 because thats what AVRCP uses.
using VolumeChangedCb = base::Callback<void(int8_t volume)>;
// Indicate that a device has been connected that does not support absolute
// volume.
virtual void DeviceConnected(const RawAddress& bdaddr) = 0;
// Indicate that a device has been connected that does support absolute
// volume. The callback will be immediately called with the current volume
// which will be sent to the device.
virtual void DeviceConnected(const RawAddress& bdaddr,
VolumeChangedCb cb) = 0;
// Indicate that a device has been disconnected from AVRCP. Will unregister
// any callbacks if absolute volume is supported.
virtual void DeviceDisconnected(const RawAddress& bdaddr) = 0;
virtual void SetVolume(int8_t volume) = 0;
virtual ~VolumeInterface() = default;
};
class ServiceInterface {
public:
// mediaInterface can not be null. If volumeInterface is null then Absolute
// Volume is disabled.
virtual void Init(MediaInterface* mediaInterface,
VolumeInterface* volumeInterface) = 0;
virtual void RegisterBipServer(int psm) = 0;
virtual void UnregisterBipServer() = 0;
virtual bool ConnectDevice(const RawAddress& bdaddr) = 0;
virtual bool DisconnectDevice(const RawAddress& bdaddr) = 0;
virtual void SetBipClientStatus(const RawAddress& bdaddr, bool connected) = 0;
virtual bool Cleanup() = 0;
protected:
virtual ~ServiceInterface() = default;
};
} // namespace avrcp
} // namespace bluetooth
|