C++程序  |  308行  |  11.64 KB

/*
 * Copyright (C) 2016 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 <list>
#include <map>
#include <memory>

#include "common/libs/fs/shared_fd.h"
#include "common/libs/threads/cuttlefish_thread.h"
#include "common/vsoc/lib/audio_data_region_view.h"
#include "common/vsoc/lib/vsoc_audio_message.h"
#include "guest/hals/audio/audio_hal.h"
#include "guest/hals/audio/vsoc_audio_input_stream.h"
#include "guest/libs/platform_support/api_level_fixes.h"

namespace cvd {

class GceAudioInputStream;
class GceAudioOutputStream;

class GceAudio : public audio_hw_device {
 public:
  // This common code manipulates the parameters of input and output streams.
  static int SetStreamParameters(struct audio_stream *, const char *);

  ~GceAudio();

  // Non-HAL methods that are part of the GCE implementation.
  // Most of these are used by the input and output streams.

  // Returns true if the microphone is muted. Used by input streams.
  bool IsMicrophoneMuted() {
    cvd::LockGuard<cvd::Mutex> guard(lock_);
    return mic_muted_;
  }

  // Send a message to the connected streamer.
  // Returns:
  //   0 if there is no streamer.
  //   >0 if the message was sent.
  //   -1 if there was an error.
  ssize_t SendMsg(const msghdr&, int flags);

  // Sends a stream update to the connected streamer.
  // Stream updates have no frames. Use SendMsg if the message has frames.
  //   0 if there is no streamer.
  //   >0 if the message was sent.
  //   -1 if there was an error.
  ssize_t SendStreamUpdate(
      const gce_audio_message& stream_info, int flags);

  // Callbacks for the Android audio_module HAL interface.
  // Most of the comments below are copied from
  // libhardware/include/hardware/audio.h
  //
  // Where the is a conflict the comments there apply.
  // By default these methods return 0 on success -<errno> for failure.

  // Opens the device.
  static int Open(const hw_module_t* module, const char* name,
                  hw_device_t** device);

  // Closes the device, closing any open input streams and output streams.
  int Close();

  // Closes the input stream, throwing away any data in the buffer.
  void CloseInputStream(audio_stream_in* stream);

  // Closes the output stream without waiting for the buffer to clear.
  void CloseOutputStream(audio_stream_out* stream);

  // Creates an audio patch between several source and sink ports.
  // The handle is allocated by the HAL and should be unique for this
  // audio HAL module.
  // TODO(ghartman): Implement this as part of HAL 3.0
  //int CreateAudioPatch(unsigned int num_sources,
  //                     const struct audio_port_config *sources,
  //                     unsigned int num_sinks,
  //                     const struct audio_port_config *sinks,
  //                     audio_patch_handle_t *handle);

  // dumps the state of the audio hardware to the given fd.
  // This information can be retrieved using the dumpsys utility.
  int Dump(int fd) const;

  // Fills the list of supported attributes for a given audio port.
  // As input, "port" contains the information (type, role, address etc...)
  // needed by the HAL to identify the port.
  // As output, "port" contains possible attributes (sampling rates, formats,
  // channel masks, gain controllers...) for this port.
  // TODO(ghartman): Implement this as part of HAL 3.0
  // int GetAudioPort(struct audio_port *port);

  // Sets audio port configuration
  // TODO(ghartman): Implement this as part of HAL 3.0
  // int SetAudioPortConfig(const struct audio_port_config *config);

  size_t GetInputBufferSize(const audio_config*) const;

  // Gets the current master volume value for the HAL, if the HAL supports
  // master volume control.  AudioFlinger will query this value from the
  // primary audio HAL when the service starts and use the value for setting
  // the initial master volume across all HALs.  HALs which do not support
  // this method may leave it set to NULL.
  int GetMasterVolume(float* /*volume*/);

  // Get the current master mute status for the HAL, if the HAL supports
  // master mute control.  AudioFlinger will query this value from the primary
  // audio HAL when the service starts and use the value for setting the
  // initial master mute across all HALs.  HALs which do not support this
  // method may leave it set to NULL.
  int GetMasterMute(bool* muted);

  // Gets the audio mute status for the microphone.
  int GetMicMute(bool* state) const;

  // Retrieves the global audio parameters.
  // TODO(ghartman): Implement this.
  char* GetParameters(const char* keys) const;

  // Enumerates what devices are supported by each audio_hw_device
  // implementation.
  // Return value is a bitmask of 1 or more values of audio_devices_t
  // used by audio flinger.
  // NOTE: audio HAL implementations starting with
  // AUDIO_DEVICE_API_VERSION_2_0 do not implement this function.
  // AUDIO_DEVICE_API_VERSION_2_0 was the current version as of JB-MR1
  // All supported devices should be listed in audio_policy.conf
  // file and the audio policy manager must choose the appropriate
  // audio module based on information in this file.
  uint32_t GetSupportedDevices() const;

  // Checks to see if the audio hardware interface has been initialized.
  // Always returns 0 to indicate success, but -ENODEV is also allowed to
  // indicate failure.
  int InitCheck() const;

  // Creates an additional hardware input stream.
  // Additional parameters were added in the 3.0 version of the HAL.
  // These defaults make it easier to implement a cross-branch device.
  int OpenInputStream(
      audio_io_handle_t handle,
      audio_devices_t devices, audio_config *config,
      audio_stream_in **stream_in,
      audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
      const char* address = 0,
      audio_source_t source = AUDIO_SOURCE_DEFAULT);

  // Creates an additional output stream.
  // The "address" parameter qualifies the "devices" audio device type if
  // needed. On GCE we ignore it for now because we simulate a single SoC
  // hw devices.
  //
  // The format format depends on the device type:
  //   Bluetooth devices use the MAC address of the device in the form
  //     "00:11:22:AA:BB:CC"
  // USB devices use the ALSA card and device numbers in the form
  //     "card=X;device=Y"
  // Other devices may use a number or any other string.
  int OpenOutputStream(
      audio_io_handle_t handle,
      audio_devices_t devices, audio_output_flags_t flags,
      audio_config* config, audio_stream_out** stream_out,
      const char* address = 0);

  // Releases an audio patch.
  // TODO(ghartman): Implement this as part of HAL 3.0
  //int ReleaseAudioPatch(audio_patch_handle_t handle);

  // Sets the audio mute status for all audio activities.  If any value other
  // than 0 is returned, the software mixer will emulate this capability.
  // The GCE implementation always returns 0.
  int SetMasterMute(bool muted);

  // Sets the audio volume for all audio activities other than voice call.
  // Range between 0.0 and 1.0. If any value other than 0 is returned,
  // the software mixer will emulate this capability.
  // The GCE implementation always returns 0.
  int SetMasterVolume(float volume);

  // Sets the audio mute status for the microphone.
  int SetMicMute(bool state);

  // set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
  // is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
  // playing, and AUDIO_MODE_IN_CALL when a call is in progress.
  int SetMode(audio_mode_t mode);

  // Sets the global audio parameters.
  // TODO(ghartman): Create a sensible implementation.
  int SetParameters(const char* kvpairs);

  // Sets the audio volume of a voice call. Range is between 0.0 and 1.0
  int SetVoiceVolume(float volume);


 private:
  // HAL 3.0 modifies the signatures of OpenInputStream and OpenOutputStream.
  // We don't want to fork the implementation, and we don't want #ifdefs all
  // over the code. The current implementation defines OpenInputStream and
  // OpenOutputStream with default values for the paramteres that were added,
  // and then generates a HAL-specific wrapper to be used in the function
  // table.
#if defined(AUDIO_DEVICE_API_VERSION_3_0)
  typedef int OpenInputStreamHAL_t(
      audio_io_handle_t, audio_devices_t, audio_config*, audio_stream_in**,
      audio_input_flags_t, const char*, audio_source_t);

  int OpenInputStreamCurrentHAL(
      audio_io_handle_t a, audio_devices_t b, audio_config* c,
      audio_stream_in** d, audio_input_flags_t e, const char* f,
      audio_source_t g) {
    return OpenInputStream(a, b, c, d, e, f, g);
  }

  typedef int OpenOutputStreamHAL_t(
      audio_io_handle_t, audio_devices_t, audio_output_flags_t,
      audio_config*, audio_stream_out**,
      const char*);

  int OpenOutputStreamCurrentHAL(
      audio_io_handle_t a, audio_devices_t b, audio_output_flags_t c,
      audio_config* d, audio_stream_out** e,
      const char* f) {
    return OpenOutputStream(a, b, c, d, e, f);
  }
#else
  typedef int OpenInputStreamHAL_t(
      audio_io_handle_t, audio_devices_t, audio_config*, audio_stream_in**);

  int OpenInputStreamCurrentHAL(
      audio_io_handle_t a, audio_devices_t b, audio_config* c,
      audio_stream_in** d) {
    return OpenInputStream(a, b, c, d);
  }

  typedef int OpenOutputStreamHAL_t(
      audio_io_handle_t, audio_devices_t, audio_output_flags_t,
      audio_config*, audio_stream_out**);

  int OpenOutputStreamCurrentHAL(
      audio_io_handle_t a, audio_devices_t b, audio_output_flags_t c,
      audio_config* d, audio_stream_out** e) {
    return OpenOutputStream(a, b, c, d, e);
  }
#endif

  //TODO(ghartman): Update this when we support 3.0.
#if defined(AUDIO_DEVICE_API_VERSION_2_0)
  static const unsigned int version_ = AUDIO_DEVICE_API_VERSION_2_0;
#else
  static const unsigned int version_ = AUDIO_DEVICE_API_VERSION_1_0;
#endif

  using AudioDataRegionView = vsoc::audio_data::AudioDataRegionView;
  AudioDataRegionView* audio_data_rv_{};
  std::unique_ptr<vsoc::RegionWorker> audio_worker_;

  // Lock to protect the data below.
  mutable cvd::Mutex lock_;
  // State that is managed at the device level.
  float voice_volume_;
  float master_volume_;
  bool master_muted_;
  bool mic_muted_;
  audio_mode_t mode_;
  // There can be multiple input and output streams. This field is used
  // to assign each one a unique identifier.
  // TODO(ghartman): This can wrap after 2^32 streams. Ideally we should check
  // the output_list_ to ensure that the stream number hasn't been assigned.
  // However, streams don't really appear and disapper that often.
  // We use the same counter for both input and output streams to make things
  // a little easier on the client.
  uint32_t next_stream_number_;
  // List of the currently active output streams.
  // Used to clean things up Close()
  std::list<GceAudioOutputStream *> output_list_;
  // List of the currently active input streams.
  // Used to clean things up Close()
  typedef std::map<uint32_t, GceAudioInputStream *> input_map_t;
  input_map_t input_map_;

  GceAudio() :
      audio_hw_device(),
      voice_volume_(0.0),
      master_volume_(0.0),
      master_muted_(false),
      mic_muted_(false),
      mode_(AUDIO_MODE_NORMAL),
      next_stream_number_(1) { }
};

}