blob: da792384eb5859a20af30ddc04e46c7a92ee756f [file] [log] [blame]
Mikhail Naganov10548292016-10-31 10:39:47 -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 */
16
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"
33
34namespace android {
35namespace hardware {
36namespace audio {
37namespace V2_0 {
38namespace implementation {
39
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -070040namespace {
41
42class Diagnostics {
43 public:
44 static Diagnostics& getInstance() {
45 std::lock_guard<std::mutex> _(mLock);
46 if (mInstance == nullptr) {
47 mInstance = new Diagnostics;
48 }
49 return *mInstance;
50 }
51
52 void registerDevice(Device* dev) {
53 std::lock_guard<std::mutex> _(mLock);
54 mDevices.push_back(wp<Device>(dev));
55 }
56
57 void checkForErasedHalCblk(const Device* dev) {
58 if (dev->version() != 0) return; // all OK
59
60 std::ostringstream ss;
61 ss << "Zero HAL CB for " << dev->type() << ":" << std::hex
62 << dev->device() << "; Others: ";
63 {
64 std::lock_guard<std::mutex> _(mLock);
65 for (auto wp : mDevices) {
66 sp<Device> other{wp.promote()};
67 if (other.get() == nullptr || other.get() == dev) continue;
68 ss << other->type() << ":" << other->version() << ":"
69 << std::hex << other->device() << "; ";
70 }
71 }
72 ALOGE("%s", ss.str().c_str());
73 }
74
75 private:
76 Diagnostics() {}
77
78 static std::mutex mLock;
79 static Diagnostics* mInstance;
80 std::vector<wp<Device>> mDevices;
81};
82
83std::mutex Diagnostics::mLock;
84Diagnostics* Diagnostics::mInstance{nullptr};
85
86} // namespace
87
88Device::Device(audio_hw_device_t* device, const char* type)
89 : mDevice{device}, mType{type} {
90 Diagnostics::getInstance().registerDevice(this);
Mikhail Naganov86685f52017-05-03 16:39:28 +000091}
Mikhail Naganov10548292016-10-31 10:39:47 -070092
93Device::~Device() {
94 int status = audio_hw_device_close(mDevice);
95 ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
96 mDevice = nullptr;
97}
98
Mikhail Naganov10548292016-10-31 10:39:47 -070099Result Device::analyzeStatus(const char* funcName, int status) {
100 if (status != 0) {
101 ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
102 }
103 switch (status) {
104 case 0: return Result::OK;
105 case -EINVAL: return Result::INVALID_ARGUMENTS;
106 case -ENODATA: return Result::INVALID_STATE;
107 case -ENODEV: return Result::NOT_INITIALIZED;
108 case -ENOSYS: return Result::NOT_SUPPORTED;
109 default: return Result::INVALID_STATE;
110 }
111}
112
Mikhail Naganov936279e2017-03-29 09:31:18 -0700113void Device::closeInputStream(audio_stream_in_t* stream) {
114 mDevice->close_input_stream(mDevice, stream);
115}
116
117void Device::closeOutputStream(audio_stream_out_t* stream) {
118 mDevice->close_output_stream(mDevice, stream);
119}
120
Mikhail Naganov86685f52017-05-03 16:39:28 +0000121char* Device::halGetParameters(const char* keys) {
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -0700122 Diagnostics::getInstance().checkForErasedHalCblk(this);
Mikhail Naganov86685f52017-05-03 16:39:28 +0000123 return mDevice->get_parameters(mDevice, keys);
Mikhail Naganov10548292016-10-31 10:39:47 -0700124}
125
Mikhail Naganov86685f52017-05-03 16:39:28 +0000126int Device::halSetParameters(const char* keysAndValues) {
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -0700127 Diagnostics::getInstance().checkForErasedHalCblk(this);
Mikhail Naganov86685f52017-05-03 16:39:28 +0000128 return mDevice->set_parameters(mDevice, keysAndValues);
Mikhail Naganov10548292016-10-31 10:39:47 -0700129}
130
131// Methods from ::android::hardware::audio::V2_0::IDevice follow.
132Return<Result> Device::initCheck() {
133 return analyzeStatus("init_check", mDevice->init_check(mDevice));
134}
135
136Return<Result> Device::setMasterVolume(float volume) {
137 Result retval(Result::NOT_SUPPORTED);
138 if (mDevice->set_master_volume != NULL) {
139 retval = analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
140 }
141 return retval;
142}
143
144Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
145 Result retval(Result::NOT_SUPPORTED);
146 float volume = 0;
147 if (mDevice->get_master_volume != NULL) {
148 retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
149 }
150 _hidl_cb(retval, volume);
151 return Void();
152}
153
154Return<Result> Device::setMicMute(bool mute) {
155 return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
156}
157
158Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
159 bool mute = false;
160 Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
161 _hidl_cb(retval, mute);
162 return Void();
163}
164
165Return<Result> Device::setMasterMute(bool mute) {
166 Result retval(Result::NOT_SUPPORTED);
167 if (mDevice->set_master_mute != NULL) {
168 retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
169 }
170 return retval;
171}
172
173Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
174 Result retval(Result::NOT_SUPPORTED);
175 bool mute = false;
176 if (mDevice->get_master_mute != NULL) {
177 retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
178 }
179 _hidl_cb(retval, mute);
180 return Void();
181}
182
183Return<void> Device::getInputBufferSize(
184 const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
185 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800186 HidlUtils::audioConfigToHal(config, &halConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700187 size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
188 Result retval(Result::INVALID_ARGUMENTS);
189 uint64_t bufferSize = 0;
190 if (halBufferSize != 0) {
191 retval = Result::OK;
192 bufferSize = halBufferSize;
193 }
194 _hidl_cb(retval, bufferSize);
195 return Void();
196}
197
198Return<void> Device::openOutputStream(
199 int32_t ioHandle,
200 const DeviceAddress& device,
201 const AudioConfig& config,
202 AudioOutputFlag flags,
203 openOutputStream_cb _hidl_cb) {
204 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800205 HidlUtils::audioConfigToHal(config, &halConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700206 audio_stream_out_t *halStream;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800207 ALOGV("open_output_stream handle: %d devices: %x flags: %#x "
208 "srate: %d format %#x channels %x address %s",
209 ioHandle,
210 static_cast<audio_devices_t>(device.device), static_cast<audio_output_flags_t>(flags),
211 halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
212 deviceAddressToHal(device).c_str());
Mikhail Naganov10548292016-10-31 10:39:47 -0700213 int status = mDevice->open_output_stream(
214 mDevice,
215 ioHandle,
216 static_cast<audio_devices_t>(device.device),
217 static_cast<audio_output_flags_t>(flags),
218 &halConfig,
219 &halStream,
220 deviceAddressToHal(device).c_str());
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800221 ALOGV("open_output_stream status %d stream %p", status, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700222 sp<IStreamOut> streamOut;
223 if (status == OK) {
Mikhail Naganov936279e2017-03-29 09:31:18 -0700224 streamOut = new StreamOut(this, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700225 }
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800226 AudioConfig suggestedConfig;
227 HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
228 _hidl_cb(analyzeStatus("open_output_stream", status), streamOut, suggestedConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700229 return Void();
230}
231
232Return<void> Device::openInputStream(
233 int32_t ioHandle,
234 const DeviceAddress& device,
235 const AudioConfig& config,
236 AudioInputFlag flags,
237 AudioSource source,
238 openInputStream_cb _hidl_cb) {
239 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800240 HidlUtils::audioConfigToHal(config, &halConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700241 audio_stream_in_t *halStream;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800242 ALOGV("open_input_stream handle: %d devices: %x flags: %#x "
243 "srate: %d format %#x channels %x address %s source %d",
244 ioHandle,
245 static_cast<audio_devices_t>(device.device), static_cast<audio_input_flags_t>(flags),
246 halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
247 deviceAddressToHal(device).c_str(), static_cast<audio_source_t>(source));
Mikhail Naganov10548292016-10-31 10:39:47 -0700248 int status = mDevice->open_input_stream(
249 mDevice,
250 ioHandle,
251 static_cast<audio_devices_t>(device.device),
252 &halConfig,
253 &halStream,
254 static_cast<audio_input_flags_t>(flags),
255 deviceAddressToHal(device).c_str(),
256 static_cast<audio_source_t>(source));
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800257 ALOGV("open_input_stream status %d stream %p", status, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700258 sp<IStreamIn> streamIn;
259 if (status == OK) {
Mikhail Naganov936279e2017-03-29 09:31:18 -0700260 streamIn = new StreamIn(this, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700261 }
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800262 AudioConfig suggestedConfig;
263 HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
264 _hidl_cb(analyzeStatus("open_input_stream", status), streamIn, suggestedConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700265 return Void();
266}
267
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800268Return<bool> Device::supportsAudioPatches() {
269 return version() >= AUDIO_DEVICE_API_VERSION_3_0;
270}
271
Mikhail Naganov10548292016-10-31 10:39:47 -0700272Return<void> Device::createAudioPatch(
273 const hidl_vec<AudioPortConfig>& sources,
274 const hidl_vec<AudioPortConfig>& sinks,
275 createAudioPatch_cb _hidl_cb) {
276 Result retval(Result::NOT_SUPPORTED);
277 AudioPatchHandle patch = 0;
278 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800279 std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
280 std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
Derek Chenab24ecd2017-04-03 19:00:50 -0400281 audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
Mikhail Naganov10548292016-10-31 10:39:47 -0700282 retval = analyzeStatus(
283 "create_audio_patch",
284 mDevice->create_audio_patch(
285 mDevice,
286 sources.size(), &halSources[0],
287 sinks.size(), &halSinks[0],
288 &halPatch));
289 if (retval == Result::OK) {
290 patch = static_cast<AudioPatchHandle>(halPatch);
291 }
292 }
293 _hidl_cb(retval, patch);
294 return Void();
295}
296
297Return<Result> Device::releaseAudioPatch(int32_t patch) {
298 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
299 return analyzeStatus(
300 "release_audio_patch",
301 mDevice->release_audio_patch(mDevice, static_cast<audio_patch_handle_t>(patch)));
302 }
303 return Result::NOT_SUPPORTED;
304}
305
306Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
307 audio_port halPort;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800308 HidlUtils::audioPortToHal(port, &halPort);
Mikhail Naganov10548292016-10-31 10:39:47 -0700309 Result retval = analyzeStatus("get_audio_port", mDevice->get_audio_port(mDevice, &halPort));
310 AudioPort resultPort = port;
311 if (retval == Result::OK) {
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800312 HidlUtils::audioPortFromHal(halPort, &resultPort);
Mikhail Naganov10548292016-10-31 10:39:47 -0700313 }
314 _hidl_cb(retval, resultPort);
315 return Void();
316}
317
318Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
319 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
320 struct audio_port_config halPortConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800321 HidlUtils::audioPortConfigToHal(config, &halPortConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700322 return analyzeStatus(
323 "set_audio_port_config", mDevice->set_audio_port_config(mDevice, &halPortConfig));
324 }
325 return Result::NOT_SUPPORTED;
326}
327
328Return<AudioHwSync> Device::getHwAvSync() {
329 int halHwAvSync;
Mikhail Naganov86685f52017-05-03 16:39:28 +0000330 Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
Mikhail Naganov10548292016-10-31 10:39:47 -0700331 return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
332}
333
334Return<Result> Device::setScreenState(bool turnedOn) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000335 return setParam(AudioParameter::keyScreenState, turnedOn);
Mikhail Naganov10548292016-10-31 10:39:47 -0700336}
337
338Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000339 getParametersImpl(keys, _hidl_cb);
Mikhail Naganov10548292016-10-31 10:39:47 -0700340 return Void();
341}
342
343Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000344 return setParametersImpl(parameters);
Mikhail Naganov10548292016-10-31 10:39:47 -0700345}
346
Martijn Coenen70b9a152016-11-18 15:29:32 +0100347Return<void> Device::debugDump(const hidl_handle& fd) {
Mikhail Naganov3e6fe752017-04-24 10:44:08 -0700348 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700349 analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
350 }
351 return Void();
352}
353
354} // namespace implementation
355} // namespace V2_0
356} // namespace audio
357} // namespace hardware
358} // namespace android