Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f72aaef authored by Ajay Panicker's avatar Ajay Panicker Committed by android-build-merger
Browse files

Merge "Add the AVRCP Device class for the AVRCP Refactor" am: 147beb32 am: ebdb3916

am: 3f42997b

Change-Id: I0355b01e47ae00eab39635327da3027307cb4908
parents c02e50bd 3f42997b
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
cc_library_headers {
    name: "avrcp_headers",
    include_dirs: ["packages/modules/Bluetooth/system/internal_include"],
    export_include_dirs: ["./hardware/avrcp/"],
    header_libs: ["internal_include_headers"],
    export_header_lib_headers: ["internal_include_headers"],
    vendor_available: true,
    host_supported: true,
}

cc_library_headers {
    name: "libbluetooth_headers",
    header_libs: [
+188 −0
Original line number Diff line number Diff line
/*
 * 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 <map>
#include <string>

#include <base/bind.h>

#include "avrcp_common.h"
#include "avrcp_logging_helper.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::map<Attribute, std::string> 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);
  virtual void SendFolderUpdate(bool available_players, bool addressed_players,
                                bool uids_changed);
  virtual void SendActiveDeviceChanged(const RawAddress& address);
  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, uint8_t status) = 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 bool ConnectDevice(const RawAddress& bdaddr) = 0;
  virtual bool DisconnectDevice(const RawAddress& bdaddr) = 0;
  virtual bool Cleanup() = 0;

 protected:
  virtual ~ServiceInterface() = default;
};

}  // namespace avrcp
}  // namespace bluetooth
 No newline at end of file
+4 −3
Original line number Diff line number Diff line
@@ -16,16 +16,17 @@

#pragma once

#include <base/sys_byteorder.h>

#include <map>

// This file contains the different AVRCP Constants
#include <base/sys_byteorder.h>

namespace bluetooth {
namespace avrcp {

constexpr uint32_t BLUETOOTH_COMPANY_ID = 0x001958;

constexpr uint8_t MAX_TRANSACTION_LABEL = 0xF;

enum class CType : uint8_t {
  CONTROL = 0x0,
  STATUS = 0x1,
+14 −23
Original line number Diff line number Diff line
@@ -23,17 +23,7 @@
#include <type_traits>

#include "avrcp_common.h"

// We have our own definition of loghex to avoid dependencies
namespace {
template <typename T>
std::string loghex(T x) {
  std::stringstream tmp;
  tmp << "0x" << std::internal << std::hex << std::setfill('0')
      << std::setw(sizeof(T) * 2) << (unsigned int)x;
  return tmp.str();
}
}  // namespace
#include "bt_trace.h"

namespace bluetooth {
namespace avrcp {
@@ -53,7 +43,7 @@ inline std::string CTypeText(const CType& type) {
    CASE_RETURN_TEXT(CType::CHANGED);
    CASE_RETURN_TEXT(CType::INTERIM);
    default:
      return "Unknown CType: " + loghex(type);
      return "Unknown CType: " + loghex((uint8_t)type);
  }
}

@@ -68,7 +58,7 @@ inline std::string OpcodeText(const Opcode& opcode) {
    CASE_RETURN_TEXT(Opcode::SUBUNIT_INFO);
    CASE_RETURN_TEXT(Opcode::PASS_THROUGH);
    default:
      return "Unknown Opcode: " + loghex(opcode);
      return "Unknown Opcode: " + loghex((uint8_t)opcode);
  }
}

@@ -83,10 +73,11 @@ inline std::string CommandPduText(const CommandPdu& pdu) {
    CASE_RETURN_TEXT(CommandPdu::GET_ELEMENT_ATTRIBUTES);
    CASE_RETURN_TEXT(CommandPdu::GET_PLAY_STATUS);
    CASE_RETURN_TEXT(CommandPdu::REGISTER_NOTIFICATION);
    CASE_RETURN_TEXT(CommandPdu::SET_ABSOLUTE_VOLUME);
    CASE_RETURN_TEXT(CommandPdu::SET_ADDRESSED_PLAYER);
    CASE_RETURN_TEXT(CommandPdu::PLAY_ITEM);
    default:
      return "Unknown Command PDU: " + loghex(pdu);
      return "Unknown Command PDU: " + loghex((uint8_t)pdu);
  }
}

@@ -98,7 +89,7 @@ inline std::string PacketTypeText(const PacketType& type) {
  switch (type) {
    CASE_RETURN_TEXT(PacketType::SINGLE);
    default:
      return "Unknown Packet Type: " + loghex(type);
      return "Unknown Packet Type: " + loghex((uint8_t)type);
  }
}

@@ -111,7 +102,7 @@ inline std::string CapabilityText(const Capability& cap) {
    CASE_RETURN_TEXT(Capability::COMPANY_ID);
    CASE_RETURN_TEXT(Capability::EVENTS_SUPPORTED);
    default:
      return "Unknown Capability: " + loghex(cap);
      return "Unknown Capability: " + loghex((uint8_t)cap);
  }
}

@@ -131,7 +122,7 @@ inline std::string EventText(const Event& event) {
    CASE_RETURN_TEXT(Event::UIDS_CHANGED);
    CASE_RETURN_TEXT(Event::VOLUME_CHANGED);
    default:
      return "Unknown Event: " + loghex(event);
      return "Unknown Event: " + loghex((uint8_t)event);
  }
}

@@ -150,7 +141,7 @@ inline std::string AttributeText(const Attribute& attr) {
    CASE_RETURN_TEXT(Attribute::PLAYING_TIME);
    CASE_RETURN_TEXT(Attribute::DEFAULT_COVER_ART);
    default:
      return "Unknown Attribute Value: " + loghex(attr);
      return "Unknown Attribute Value: " + loghex((uint32_t)attr);
  }
}

@@ -184,7 +175,7 @@ inline std::string StatusText(const Status& status) {
    CASE_RETURN_TEXT(Status::NO_AVAILABLE_PLAYERS);
    CASE_RETURN_TEXT(Status::ADDRESSED_PLAYER_CHANGED);
    default:
      return "Unknown Status: " + loghex(status);
      return "Unknown Status: " + loghex((uint8_t)status);
  }
}

@@ -199,7 +190,7 @@ inline std::string BrowsePduText(const BrowsePdu& pdu) {
    CASE_RETURN_TEXT(BrowsePdu::CHANGE_PATH);
    CASE_RETURN_TEXT(BrowsePdu::GET_ITEM_ATTRIBUTES);
    default:
      return "Unknown Browse Pdu: " + loghex(pdu);
      return "Unknown Browse PDU: " + loghex((uint8_t)pdu);
  }
}

@@ -214,7 +205,7 @@ inline std::string ScopeText(const Scope& scope) {
    CASE_RETURN_TEXT(Scope::SEARCH);
    CASE_RETURN_TEXT(Scope::NOW_PLAYING);
    default:
      return "Unknown Scope: " + loghex(scope);
      return "Unknown Scope: " + loghex((uint8_t)scope);
  }
}

@@ -227,7 +218,7 @@ inline std::string DirectionText(const Direction& dir) {
    CASE_RETURN_TEXT(Direction::UP);
    CASE_RETURN_TEXT(Direction::DOWN);
    default:
      return "Unknown Direction: " + loghex(dir);
      return "Unknown Direction: " + loghex((uint8_t)dir);
  }
}

+6 −0
Original line number Diff line number Diff line
cc_library_headers {
    name: "internal_include_headers",
    export_include_dirs: ["./"],
    vendor_available: true,
    host_supported: true,
}
 No newline at end of file
Loading