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

Commit 95ba6a21 authored by Alice Kuo's avatar Alice Kuo
Browse files

Fix the integration issue for HAL 2.2

Bug: 150670922
Bug: 197297498
Test: A2DP & LE aduio stream works well with HIDL 2.1/2.2
Change-Id: I64113dd4a229874b2d17ae71d088abafd8197cfd
parent be7f81f5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ int main(int /* argc */, char* /* argv */ []) {
        },
        {
            "Bluetooth Audio API",
            "android.hardware.bluetooth.audio@2.2::IBluetoothAudioProvidersFactory",
            "android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory",
            "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory",
        },
+18 −0
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package android.hardware.bluetooth.audio@2.2;

import IBluetoothAudioProvider;
import @2.1::IBluetoothAudioProvidersFactory;
import @2.0::Status;
import @2.1::SessionType;

/**
 * This factory allows a HAL implementation to be split into multiple
@@ -30,4 +33,19 @@ import @2.1::IBluetoothAudioProvidersFactory;
 * for return value must be invoked synchronously before the API call returns.
 */
interface IBluetoothAudioProvidersFactory extends @2.1::IBluetoothAudioProvidersFactory {
    /**
     * Opens an audio provider for a session type. To close the provider, it is
     * necessary to release references to the returned provider object.
     *
     * @param sessionType The session type (e.g.
     *    LE_AUDIO_SOFTWARE_ENCODING_DATAPATH).
     *
     * @return status One of the following
     *    SUCCESS if the Audio HAL successfully opens the provider with the
     *        given session type
     *    FAILURE if the Audio HAL cannot open the provider
     * @return provider The provider of the specified session type
     */
    openProvider_2_2(SessionType sessionType)
        generates (Status status, IBluetoothAudioProvider provider);
};
+43 −0
Original line number Diff line number Diff line
@@ -122,6 +122,49 @@ Return<void> BluetoothAudioProvidersFactory::openProvider_2_1(
  return Void();
}

Return<void> BluetoothAudioProvidersFactory::openProvider_2_2(
    const V2_1::SessionType sessionType, openProvider_2_2_cb _hidl_cb) {
  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
  BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
  BluetoothAudioProvider* provider = nullptr;

  switch (sessionType) {
    case V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
      provider = &a2dp_software_provider_instance_;
      break;
    case V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
      provider = &a2dp_offload_provider_instance_;
      break;
    case V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
      provider = &hearing_aid_provider_instance_;
      break;
    case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
      provider = &leaudio_output_provider_instance_;
      break;
    case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
      provider = &leaudio_offload_output_provider_instance_;
      break;
    case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
      provider = &leaudio_input_provider_instance_;
      break;
    case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
      provider = &leaudio_offload_input_provider_instance_;
      break;
    default:
      status = BluetoothAudioStatus::FAILURE;
  }

  if (provider == nullptr || !provider->isValid(sessionType)) {
    provider = nullptr;
    status = BluetoothAudioStatus::FAILURE;
    LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
               << ", status=" << toString(status);
  }

  _hidl_cb(status, provider);
  return Void();
}

Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities(
    const V2_0::SessionType sessionType, getProviderCapabilities_cb _hidl_cb) {
  hidl_vec<V2_0::AudioCapabilities> audio_capabilities =
+3 −0
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@ class BluetoothAudioProvidersFactory : public IBluetoothAudioProvidersFactory {
  Return<void> openProvider_2_1(const V2_1::SessionType sessionType,
                                openProvider_2_1_cb _hidl_cb) override;

  Return<void> openProvider_2_2(const V2_1::SessionType sessionType,
                                openProvider_2_2_cb _hidl_cb) override;

  Return<void> getProviderCapabilities_2_1(
      const V2_1::SessionType sessionType,
      getProviderCapabilities_2_1_cb _hidl_cb) override;
+160 −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 "BluetoothAudioSession_2_2.h"

namespace android {
namespace bluetooth {
namespace audio {

class BluetoothAudioSessionControl_2_2 {
  using SessionType_2_1 =
      ::android::hardware::bluetooth::audio::V2_1::SessionType;
  using AudioConfiguration_2_2 =
      ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration;

 public:
  // The control API helps to check if session is ready or not
  // @return: true if the Bluetooth stack has started th specified session
  static bool IsSessionReady(const SessionType_2_1& session_type) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->IsSessionReady();
    }
    return false;
  }

  // The control API helps the bluetooth_audio module to register
  // PortStatusCallbacks
  // @return: cookie - the assigned number to this bluetooth_audio output
  static uint16_t RegisterControlResultCback(
      const SessionType_2_1& session_type, const PortStatusCallbacks& cbacks) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->GetAudioSession()->RegisterStatusCback(cbacks);
    }
    return kObserversCookieUndefined;
  }

  // The control API helps the bluetooth_audio module to unregister
  // PortStatusCallbacks
  // @param: cookie - indicates which bluetooth_audio output is
  static void UnregisterControlResultCback(const SessionType_2_1& session_type,
                                           uint16_t cookie) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      session_ptr->GetAudioSession()->UnregisterStatusCback(cookie);
    }
  }

  // The control API for the bluetooth_audio module to get current
  // AudioConfiguration
  static const AudioConfiguration_2_2 GetAudioConfig(
      const SessionType_2_1& session_type) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->GetAudioConfig();
    } else if (session_type ==
               SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
      return BluetoothAudioSession_2_2::kInvalidOffloadAudioConfiguration;
    } else {
      return BluetoothAudioSession_2_2::kInvalidSoftwareAudioConfiguration;
    }
  }

  // Those control APIs for the bluetooth_audio module to start / suspend / stop
  // stream, to check position, and to update metadata.
  static bool StartStream(const SessionType_2_1& session_type) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->GetAudioSession()->StartStream();
    }
    return false;
  }

  static bool SuspendStream(const SessionType_2_1& session_type) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->GetAudioSession()->SuspendStream();
    }
    return false;
  }

  static void StopStream(const SessionType_2_1& session_type) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      session_ptr->GetAudioSession()->StopStream();
    }
  }

  static bool GetPresentationPosition(const SessionType_2_1& session_type,
                                      uint64_t* remote_delay_report_ns,
                                      uint64_t* total_bytes_readed,
                                      timespec* data_position) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->GetAudioSession()->GetPresentationPosition(
          remote_delay_report_ns, total_bytes_readed, data_position);
    }
    return false;
  }

  static void UpdateTracksMetadata(
      const SessionType_2_1& session_type,
      const struct source_metadata* source_metadata) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      session_ptr->GetAudioSession()->UpdateTracksMetadata(source_metadata);
    }
  }

  // The control API writes stream to FMQ
  static size_t OutWritePcmData(const SessionType_2_1& session_type,
                                const void* buffer, size_t bytes) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->GetAudioSession()->OutWritePcmData(buffer, bytes);
    }
    return 0;
  }

  // The control API reads stream from FMQ
  static size_t InReadPcmData(const SessionType_2_1& session_type, void* buffer,
                              size_t bytes) {
    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
    if (session_ptr != nullptr) {
      return session_ptr->GetAudioSession()->InReadPcmData(buffer, bytes);
    }
    return 0;
  }
};

}  // namespace audio
}  // namespace bluetooth
}  // namespace android
Loading