blob: 280d32058effad7b0c1eaa90205c8c0ccc83431a [file] [log] [blame]
Kevin Rocard72e50e22017-05-05 14:02:55 -07001/*
2* Copyright (C) 2016 The Android Open Source Project
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
Mikhail Naganov10548292016-10-31 10:39:47 -070016
17#define LOG_TAG "DeviceHAL"
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -080018//#define LOG_NDEBUG 0
Mikhail Naganov10548292016-10-31 10:39:47 -070019
Mikhail Naganov10548292016-10-31 10:39:47 -070020#include <memory.h>
21#include <string.h>
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -070022#include <algorithm>
23#include <mutex>
24#include <vector>
Mikhail Naganov10548292016-10-31 10:39:47 -070025
Yifan Hongf9d30342016-11-30 13:45:34 -080026#include <android/log.h>
Mikhail Naganov10548292016-10-31 10:39:47 -070027
28#include "Conversions.h"
29#include "Device.h"
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -080030#include "HidlUtils.h"
Mikhail Naganov10548292016-10-31 10:39:47 -070031#include "StreamIn.h"
32#include "StreamOut.h"
Kevin Rocard4c030022017-05-08 17:08:11 -070033#include "Util.h"
Mikhail Naganov10548292016-10-31 10:39:47 -070034
35namespace android {
36namespace hardware {
37namespace audio {
38namespace V2_0 {
39namespace implementation {
40
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -070041namespace {
42
43class Diagnostics {
44 public:
45 static Diagnostics& getInstance() {
46 std::lock_guard<std::mutex> _(mLock);
47 if (mInstance == nullptr) {
48 mInstance = new Diagnostics;
49 }
50 return *mInstance;
51 }
52
53 void registerDevice(Device* dev) {
54 std::lock_guard<std::mutex> _(mLock);
55 mDevices.push_back(wp<Device>(dev));
56 }
57
58 void checkForErasedHalCblk(const Device* dev) {
59 if (dev->version() != 0) return; // all OK
60
61 std::ostringstream ss;
62 ss << "Zero HAL CB for " << dev->type() << ":" << std::hex
63 << dev->device() << "; Others: ";
64 {
65 std::lock_guard<std::mutex> _(mLock);
66 for (auto wp : mDevices) {
67 sp<Device> other{wp.promote()};
68 if (other.get() == nullptr || other.get() == dev) continue;
69 ss << other->type() << ":" << other->version() << ":"
70 << std::hex << other->device() << "; ";
71 }
72 }
73 ALOGE("%s", ss.str().c_str());
74 }
75
76 private:
77 Diagnostics() {}
78
79 static std::mutex mLock;
80 static Diagnostics* mInstance;
81 std::vector<wp<Device>> mDevices;
82};
83
84std::mutex Diagnostics::mLock;
85Diagnostics* Diagnostics::mInstance{nullptr};
86
87} // namespace
88
89Device::Device(audio_hw_device_t* device, const char* type)
90 : mDevice{device}, mType{type} {
91 Diagnostics::getInstance().registerDevice(this);
Mikhail Naganov86685f52017-05-03 16:39:28 +000092}
Mikhail Naganov10548292016-10-31 10:39:47 -070093
94Device::~Device() {
95 int status = audio_hw_device_close(mDevice);
Kevin Rocard72e50e22017-05-05 14:02:55 -070096 ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice,
97 strerror(-status));
Mikhail Naganov10548292016-10-31 10:39:47 -070098 mDevice = nullptr;
99}
100
Mikhail Naganov10548292016-10-31 10:39:47 -0700101Result Device::analyzeStatus(const char* funcName, int status) {
102 if (status != 0) {
103 ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
104 }
105 switch (status) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700106 case 0:
107 return Result::OK;
108 case -EINVAL:
109 return Result::INVALID_ARGUMENTS;
110 case -ENODATA:
111 return Result::INVALID_STATE;
112 case -ENODEV:
113 return Result::NOT_INITIALIZED;
114 case -ENOSYS:
115 return Result::NOT_SUPPORTED;
116 default:
117 return Result::INVALID_STATE;
Mikhail Naganov10548292016-10-31 10:39:47 -0700118 }
119}
120
Mikhail Naganov936279e2017-03-29 09:31:18 -0700121void Device::closeInputStream(audio_stream_in_t* stream) {
122 mDevice->close_input_stream(mDevice, stream);
123}
124
125void Device::closeOutputStream(audio_stream_out_t* stream) {
126 mDevice->close_output_stream(mDevice, stream);
127}
128
Mikhail Naganov86685f52017-05-03 16:39:28 +0000129char* Device::halGetParameters(const char* keys) {
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -0700130 Diagnostics::getInstance().checkForErasedHalCblk(this);
Mikhail Naganov86685f52017-05-03 16:39:28 +0000131 return mDevice->get_parameters(mDevice, keys);
Mikhail Naganov10548292016-10-31 10:39:47 -0700132}
133
Mikhail Naganov86685f52017-05-03 16:39:28 +0000134int Device::halSetParameters(const char* keysAndValues) {
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -0700135 Diagnostics::getInstance().checkForErasedHalCblk(this);
Mikhail Naganov86685f52017-05-03 16:39:28 +0000136 return mDevice->set_parameters(mDevice, keysAndValues);
Mikhail Naganov10548292016-10-31 10:39:47 -0700137}
138
139// Methods from ::android::hardware::audio::V2_0::IDevice follow.
Kevin Rocard72e50e22017-05-05 14:02:55 -0700140Return<Result> Device::initCheck() {
Mikhail Naganov10548292016-10-31 10:39:47 -0700141 return analyzeStatus("init_check", mDevice->init_check(mDevice));
142}
143
Kevin Rocard72e50e22017-05-05 14:02:55 -0700144Return<Result> Device::setMasterVolume(float volume) {
Kevin Rocard4c030022017-05-08 17:08:11 -0700145 if (mDevice->set_master_volume == NULL) {
146 return Result::NOT_SUPPORTED;
Mikhail Naganov10548292016-10-31 10:39:47 -0700147 }
Kevin Rocard4c030022017-05-08 17:08:11 -0700148 if (!isGainNormalized(volume)) {
149 ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
150 return Result::INVALID_ARGUMENTS;
151 }
152 return analyzeStatus("set_master_volume",
153 mDevice->set_master_volume(mDevice, volume));
Mikhail Naganov10548292016-10-31 10:39:47 -0700154}
155
Kevin Rocard72e50e22017-05-05 14:02:55 -0700156Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700157 Result retval(Result::NOT_SUPPORTED);
158 float volume = 0;
159 if (mDevice->get_master_volume != NULL) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700160 retval = analyzeStatus("get_master_volume",
161 mDevice->get_master_volume(mDevice, &volume));
Mikhail Naganov10548292016-10-31 10:39:47 -0700162 }
163 _hidl_cb(retval, volume);
164 return Void();
165}
166
Kevin Rocard72e50e22017-05-05 14:02:55 -0700167Return<Result> Device::setMicMute(bool mute) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700168 return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
169}
170
Kevin Rocard72e50e22017-05-05 14:02:55 -0700171Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700172 bool mute = false;
Kevin Rocard72e50e22017-05-05 14:02:55 -0700173 Result retval =
174 analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
Mikhail Naganov10548292016-10-31 10:39:47 -0700175 _hidl_cb(retval, mute);
176 return Void();
177}
178
Kevin Rocard72e50e22017-05-05 14:02:55 -0700179Return<Result> Device::setMasterMute(bool mute) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700180 Result retval(Result::NOT_SUPPORTED);
181 if (mDevice->set_master_mute != NULL) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700182 retval = analyzeStatus("set_master_mute",
183 mDevice->set_master_mute(mDevice, mute));
Mikhail Naganov10548292016-10-31 10:39:47 -0700184 }
185 return retval;
186}
187
Kevin Rocard72e50e22017-05-05 14:02:55 -0700188Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700189 Result retval(Result::NOT_SUPPORTED);
190 bool mute = false;
191 if (mDevice->get_master_mute != NULL) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700192 retval = analyzeStatus("get_master_mute",
193 mDevice->get_master_mute(mDevice, &mute));
Mikhail Naganov10548292016-10-31 10:39:47 -0700194 }
195 _hidl_cb(retval, mute);
196 return Void();
197}
198
Kevin Rocard72e50e22017-05-05 14:02:55 -0700199Return<void> Device::getInputBufferSize(const AudioConfig& config,
200 getInputBufferSize_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700201 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800202 HidlUtils::audioConfigToHal(config, &halConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700203 size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
204 Result retval(Result::INVALID_ARGUMENTS);
205 uint64_t bufferSize = 0;
206 if (halBufferSize != 0) {
207 retval = Result::OK;
208 bufferSize = halBufferSize;
209 }
210 _hidl_cb(retval, bufferSize);
211 return Void();
212}
213
Kevin Rocard72e50e22017-05-05 14:02:55 -0700214Return<void> Device::openOutputStream(int32_t ioHandle,
215 const DeviceAddress& device,
216 const AudioConfig& config,
217 AudioOutputFlag flags,
218 openOutputStream_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700219 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800220 HidlUtils::audioConfigToHal(config, &halConfig);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700221 audio_stream_out_t* halStream;
222 ALOGV(
223 "open_output_stream handle: %d devices: %x flags: %#x "
224 "srate: %d format %#x channels %x address %s",
225 ioHandle, static_cast<audio_devices_t>(device.device),
226 static_cast<audio_output_flags_t>(flags), halConfig.sample_rate,
227 halConfig.format, halConfig.channel_mask,
228 deviceAddressToHal(device).c_str());
Mikhail Naganov10548292016-10-31 10:39:47 -0700229 int status = mDevice->open_output_stream(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700230 mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
231 static_cast<audio_output_flags_t>(flags), &halConfig, &halStream,
232 deviceAddressToHal(device).c_str());
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800233 ALOGV("open_output_stream status %d stream %p", status, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700234 sp<IStreamOut> streamOut;
235 if (status == OK) {
Mikhail Naganov936279e2017-03-29 09:31:18 -0700236 streamOut = new StreamOut(this, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700237 }
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800238 AudioConfig suggestedConfig;
239 HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700240 _hidl_cb(analyzeStatus("open_output_stream", status), streamOut,
241 suggestedConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700242 return Void();
243}
244
Kevin Rocard72e50e22017-05-05 14:02:55 -0700245Return<void> Device::openInputStream(int32_t ioHandle,
246 const DeviceAddress& device,
247 const AudioConfig& config,
248 AudioInputFlag flags, AudioSource source,
249 openInputStream_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700250 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800251 HidlUtils::audioConfigToHal(config, &halConfig);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700252 audio_stream_in_t* halStream;
253 ALOGV(
254 "open_input_stream handle: %d devices: %x flags: %#x "
255 "srate: %d format %#x channels %x address %s source %d",
256 ioHandle, static_cast<audio_devices_t>(device.device),
257 static_cast<audio_input_flags_t>(flags), halConfig.sample_rate,
258 halConfig.format, halConfig.channel_mask,
259 deviceAddressToHal(device).c_str(),
260 static_cast<audio_source_t>(source));
Mikhail Naganov10548292016-10-31 10:39:47 -0700261 int status = mDevice->open_input_stream(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700262 mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
263 &halConfig, &halStream, static_cast<audio_input_flags_t>(flags),
264 deviceAddressToHal(device).c_str(),
265 static_cast<audio_source_t>(source));
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800266 ALOGV("open_input_stream status %d stream %p", status, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700267 sp<IStreamIn> streamIn;
268 if (status == OK) {
Mikhail Naganov936279e2017-03-29 09:31:18 -0700269 streamIn = new StreamIn(this, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700270 }
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800271 AudioConfig suggestedConfig;
272 HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700273 _hidl_cb(analyzeStatus("open_input_stream", status), streamIn,
274 suggestedConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700275 return Void();
276}
277
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800278Return<bool> Device::supportsAudioPatches() {
279 return version() >= AUDIO_DEVICE_API_VERSION_3_0;
280}
281
Kevin Rocard72e50e22017-05-05 14:02:55 -0700282Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
283 const hidl_vec<AudioPortConfig>& sinks,
284 createAudioPatch_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700285 Result retval(Result::NOT_SUPPORTED);
286 AudioPatchHandle patch = 0;
287 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700288 std::unique_ptr<audio_port_config[]> halSources(
289 HidlUtils::audioPortConfigsToHal(sources));
290 std::unique_ptr<audio_port_config[]> halSinks(
291 HidlUtils::audioPortConfigsToHal(sinks));
Derek Chenab24ecd2017-04-03 19:00:50 -0400292 audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
Mikhail Naganov10548292016-10-31 10:39:47 -0700293 retval = analyzeStatus(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700294 "create_audio_patch",
295 mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
296 sinks.size(), &halSinks[0], &halPatch));
Mikhail Naganov10548292016-10-31 10:39:47 -0700297 if (retval == Result::OK) {
298 patch = static_cast<AudioPatchHandle>(halPatch);
299 }
300 }
301 _hidl_cb(retval, patch);
302 return Void();
303}
304
Kevin Rocard72e50e22017-05-05 14:02:55 -0700305Return<Result> Device::releaseAudioPatch(int32_t patch) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700306 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
307 return analyzeStatus(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700308 "release_audio_patch",
309 mDevice->release_audio_patch(
310 mDevice, static_cast<audio_patch_handle_t>(patch)));
Mikhail Naganov10548292016-10-31 10:39:47 -0700311 }
312 return Result::NOT_SUPPORTED;
313}
314
Kevin Rocard72e50e22017-05-05 14:02:55 -0700315Return<void> Device::getAudioPort(const AudioPort& port,
316 getAudioPort_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700317 audio_port halPort;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800318 HidlUtils::audioPortToHal(port, &halPort);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700319 Result retval = analyzeStatus("get_audio_port",
320 mDevice->get_audio_port(mDevice, &halPort));
Mikhail Naganov10548292016-10-31 10:39:47 -0700321 AudioPort resultPort = port;
322 if (retval == Result::OK) {
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800323 HidlUtils::audioPortFromHal(halPort, &resultPort);
Mikhail Naganov10548292016-10-31 10:39:47 -0700324 }
325 _hidl_cb(retval, resultPort);
326 return Void();
327}
328
Kevin Rocard72e50e22017-05-05 14:02:55 -0700329Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700330 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
331 struct audio_port_config halPortConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800332 HidlUtils::audioPortConfigToHal(config, &halPortConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700333 return analyzeStatus(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700334 "set_audio_port_config",
335 mDevice->set_audio_port_config(mDevice, &halPortConfig));
Mikhail Naganov10548292016-10-31 10:39:47 -0700336 }
337 return Result::NOT_SUPPORTED;
338}
339
Kevin Rocard72e50e22017-05-05 14:02:55 -0700340Return<AudioHwSync> Device::getHwAvSync() {
Mikhail Naganov10548292016-10-31 10:39:47 -0700341 int halHwAvSync;
Mikhail Naganov86685f52017-05-03 16:39:28 +0000342 Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
Mikhail Naganov10548292016-10-31 10:39:47 -0700343 return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
344}
345
Kevin Rocard72e50e22017-05-05 14:02:55 -0700346Return<Result> Device::setScreenState(bool turnedOn) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000347 return setParam(AudioParameter::keyScreenState, turnedOn);
Mikhail Naganov10548292016-10-31 10:39:47 -0700348}
349
Kevin Rocard72e50e22017-05-05 14:02:55 -0700350Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys,
351 getParameters_cb _hidl_cb) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000352 getParametersImpl(keys, _hidl_cb);
Mikhail Naganov10548292016-10-31 10:39:47 -0700353 return Void();
354}
355
Kevin Rocard72e50e22017-05-05 14:02:55 -0700356Return<Result> Device::setParameters(
357 const hidl_vec<ParameterValue>& parameters) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000358 return setParametersImpl(parameters);
Mikhail Naganov10548292016-10-31 10:39:47 -0700359}
360
Kevin Rocard72e50e22017-05-05 14:02:55 -0700361Return<void> Device::debugDump(const hidl_handle& fd) {
Mikhail Naganov3e6fe752017-04-24 10:44:08 -0700362 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700363 analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
364 }
365 return Void();
366}
367
368} // namespace implementation
369} // namespace V2_0
370} // namespace audio
371} // namespace hardware
372} // namespace android