blob: 9246f8b4e3611b87348352d23c424ee0372a03fe [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"
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);
Kevin Rocard72e50e22017-05-05 14:02:55 -070095 ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice,
96 strerror(-status));
Mikhail Naganov10548292016-10-31 10:39:47 -070097 mDevice = nullptr;
98}
99
Mikhail Naganov10548292016-10-31 10:39:47 -0700100Result Device::analyzeStatus(const char* funcName, int status) {
101 if (status != 0) {
102 ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
103 }
104 switch (status) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700105 case 0:
106 return Result::OK;
107 case -EINVAL:
108 return Result::INVALID_ARGUMENTS;
109 case -ENODATA:
110 return Result::INVALID_STATE;
111 case -ENODEV:
112 return Result::NOT_INITIALIZED;
113 case -ENOSYS:
114 return Result::NOT_SUPPORTED;
115 default:
116 return Result::INVALID_STATE;
Mikhail Naganov10548292016-10-31 10:39:47 -0700117 }
118}
119
Mikhail Naganov936279e2017-03-29 09:31:18 -0700120void Device::closeInputStream(audio_stream_in_t* stream) {
121 mDevice->close_input_stream(mDevice, stream);
122}
123
124void Device::closeOutputStream(audio_stream_out_t* stream) {
125 mDevice->close_output_stream(mDevice, stream);
126}
127
Mikhail Naganov86685f52017-05-03 16:39:28 +0000128char* Device::halGetParameters(const char* keys) {
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -0700129 Diagnostics::getInstance().checkForErasedHalCblk(this);
Mikhail Naganov86685f52017-05-03 16:39:28 +0000130 return mDevice->get_parameters(mDevice, keys);
Mikhail Naganov10548292016-10-31 10:39:47 -0700131}
132
Mikhail Naganov86685f52017-05-03 16:39:28 +0000133int Device::halSetParameters(const char* keysAndValues) {
Mikhail Naganov6c0f76a2017-05-03 12:08:22 -0700134 Diagnostics::getInstance().checkForErasedHalCblk(this);
Mikhail Naganov86685f52017-05-03 16:39:28 +0000135 return mDevice->set_parameters(mDevice, keysAndValues);
Mikhail Naganov10548292016-10-31 10:39:47 -0700136}
137
138// Methods from ::android::hardware::audio::V2_0::IDevice follow.
Kevin Rocard72e50e22017-05-05 14:02:55 -0700139Return<Result> Device::initCheck() {
Mikhail Naganov10548292016-10-31 10:39:47 -0700140 return analyzeStatus("init_check", mDevice->init_check(mDevice));
141}
142
Kevin Rocard72e50e22017-05-05 14:02:55 -0700143Return<Result> Device::setMasterVolume(float volume) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700144 Result retval(Result::NOT_SUPPORTED);
145 if (mDevice->set_master_volume != NULL) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700146 retval = analyzeStatus("set_master_volume",
147 mDevice->set_master_volume(mDevice, volume));
Mikhail Naganov10548292016-10-31 10:39:47 -0700148 }
149 return retval;
150}
151
Kevin Rocard72e50e22017-05-05 14:02:55 -0700152Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700153 Result retval(Result::NOT_SUPPORTED);
154 float volume = 0;
155 if (mDevice->get_master_volume != NULL) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700156 retval = analyzeStatus("get_master_volume",
157 mDevice->get_master_volume(mDevice, &volume));
Mikhail Naganov10548292016-10-31 10:39:47 -0700158 }
159 _hidl_cb(retval, volume);
160 return Void();
161}
162
Kevin Rocard72e50e22017-05-05 14:02:55 -0700163Return<Result> Device::setMicMute(bool mute) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700164 return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
165}
166
Kevin Rocard72e50e22017-05-05 14:02:55 -0700167Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700168 bool mute = false;
Kevin Rocard72e50e22017-05-05 14:02:55 -0700169 Result retval =
170 analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
Mikhail Naganov10548292016-10-31 10:39:47 -0700171 _hidl_cb(retval, mute);
172 return Void();
173}
174
Kevin Rocard72e50e22017-05-05 14:02:55 -0700175Return<Result> Device::setMasterMute(bool mute) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700176 Result retval(Result::NOT_SUPPORTED);
177 if (mDevice->set_master_mute != NULL) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700178 retval = analyzeStatus("set_master_mute",
179 mDevice->set_master_mute(mDevice, mute));
Mikhail Naganov10548292016-10-31 10:39:47 -0700180 }
181 return retval;
182}
183
Kevin Rocard72e50e22017-05-05 14:02:55 -0700184Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700185 Result retval(Result::NOT_SUPPORTED);
186 bool mute = false;
187 if (mDevice->get_master_mute != NULL) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700188 retval = analyzeStatus("get_master_mute",
189 mDevice->get_master_mute(mDevice, &mute));
Mikhail Naganov10548292016-10-31 10:39:47 -0700190 }
191 _hidl_cb(retval, mute);
192 return Void();
193}
194
Kevin Rocard72e50e22017-05-05 14:02:55 -0700195Return<void> Device::getInputBufferSize(const AudioConfig& config,
196 getInputBufferSize_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700197 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800198 HidlUtils::audioConfigToHal(config, &halConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700199 size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
200 Result retval(Result::INVALID_ARGUMENTS);
201 uint64_t bufferSize = 0;
202 if (halBufferSize != 0) {
203 retval = Result::OK;
204 bufferSize = halBufferSize;
205 }
206 _hidl_cb(retval, bufferSize);
207 return Void();
208}
209
Kevin Rocard72e50e22017-05-05 14:02:55 -0700210Return<void> Device::openOutputStream(int32_t ioHandle,
211 const DeviceAddress& device,
212 const AudioConfig& config,
213 AudioOutputFlag flags,
214 openOutputStream_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700215 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800216 HidlUtils::audioConfigToHal(config, &halConfig);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700217 audio_stream_out_t* halStream;
218 ALOGV(
219 "open_output_stream handle: %d devices: %x flags: %#x "
220 "srate: %d format %#x channels %x address %s",
221 ioHandle, static_cast<audio_devices_t>(device.device),
222 static_cast<audio_output_flags_t>(flags), halConfig.sample_rate,
223 halConfig.format, halConfig.channel_mask,
224 deviceAddressToHal(device).c_str());
Mikhail Naganov10548292016-10-31 10:39:47 -0700225 int status = mDevice->open_output_stream(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700226 mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
227 static_cast<audio_output_flags_t>(flags), &halConfig, &halStream,
228 deviceAddressToHal(device).c_str());
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800229 ALOGV("open_output_stream status %d stream %p", status, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700230 sp<IStreamOut> streamOut;
231 if (status == OK) {
Mikhail Naganov936279e2017-03-29 09:31:18 -0700232 streamOut = new StreamOut(this, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700233 }
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800234 AudioConfig suggestedConfig;
235 HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700236 _hidl_cb(analyzeStatus("open_output_stream", status), streamOut,
237 suggestedConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700238 return Void();
239}
240
Kevin Rocard72e50e22017-05-05 14:02:55 -0700241Return<void> Device::openInputStream(int32_t ioHandle,
242 const DeviceAddress& device,
243 const AudioConfig& config,
244 AudioInputFlag flags, AudioSource source,
245 openInputStream_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700246 audio_config_t halConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800247 HidlUtils::audioConfigToHal(config, &halConfig);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700248 audio_stream_in_t* halStream;
249 ALOGV(
250 "open_input_stream handle: %d devices: %x flags: %#x "
251 "srate: %d format %#x channels %x address %s source %d",
252 ioHandle, static_cast<audio_devices_t>(device.device),
253 static_cast<audio_input_flags_t>(flags), halConfig.sample_rate,
254 halConfig.format, halConfig.channel_mask,
255 deviceAddressToHal(device).c_str(),
256 static_cast<audio_source_t>(source));
Mikhail Naganov10548292016-10-31 10:39:47 -0700257 int status = mDevice->open_input_stream(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700258 mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
259 &halConfig, &halStream, static_cast<audio_input_flags_t>(flags),
260 deviceAddressToHal(device).c_str(),
261 static_cast<audio_source_t>(source));
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800262 ALOGV("open_input_stream status %d stream %p", status, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700263 sp<IStreamIn> streamIn;
264 if (status == OK) {
Mikhail Naganov936279e2017-03-29 09:31:18 -0700265 streamIn = new StreamIn(this, halStream);
Mikhail Naganov10548292016-10-31 10:39:47 -0700266 }
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800267 AudioConfig suggestedConfig;
268 HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700269 _hidl_cb(analyzeStatus("open_input_stream", status), streamIn,
270 suggestedConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700271 return Void();
272}
273
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800274Return<bool> Device::supportsAudioPatches() {
275 return version() >= AUDIO_DEVICE_API_VERSION_3_0;
276}
277
Kevin Rocard72e50e22017-05-05 14:02:55 -0700278Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
279 const hidl_vec<AudioPortConfig>& sinks,
280 createAudioPatch_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700281 Result retval(Result::NOT_SUPPORTED);
282 AudioPatchHandle patch = 0;
283 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
Kevin Rocard72e50e22017-05-05 14:02:55 -0700284 std::unique_ptr<audio_port_config[]> halSources(
285 HidlUtils::audioPortConfigsToHal(sources));
286 std::unique_ptr<audio_port_config[]> halSinks(
287 HidlUtils::audioPortConfigsToHal(sinks));
Derek Chenab24ecd2017-04-03 19:00:50 -0400288 audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
Mikhail Naganov10548292016-10-31 10:39:47 -0700289 retval = analyzeStatus(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700290 "create_audio_patch",
291 mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
292 sinks.size(), &halSinks[0], &halPatch));
Mikhail Naganov10548292016-10-31 10:39:47 -0700293 if (retval == Result::OK) {
294 patch = static_cast<AudioPatchHandle>(halPatch);
295 }
296 }
297 _hidl_cb(retval, patch);
298 return Void();
299}
300
Kevin Rocard72e50e22017-05-05 14:02:55 -0700301Return<Result> Device::releaseAudioPatch(int32_t patch) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700302 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
303 return analyzeStatus(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700304 "release_audio_patch",
305 mDevice->release_audio_patch(
306 mDevice, static_cast<audio_patch_handle_t>(patch)));
Mikhail Naganov10548292016-10-31 10:39:47 -0700307 }
308 return Result::NOT_SUPPORTED;
309}
310
Kevin Rocard72e50e22017-05-05 14:02:55 -0700311Return<void> Device::getAudioPort(const AudioPort& port,
312 getAudioPort_cb _hidl_cb) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700313 audio_port halPort;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800314 HidlUtils::audioPortToHal(port, &halPort);
Kevin Rocard72e50e22017-05-05 14:02:55 -0700315 Result retval = analyzeStatus("get_audio_port",
316 mDevice->get_audio_port(mDevice, &halPort));
Mikhail Naganov10548292016-10-31 10:39:47 -0700317 AudioPort resultPort = port;
318 if (retval == Result::OK) {
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800319 HidlUtils::audioPortFromHal(halPort, &resultPort);
Mikhail Naganov10548292016-10-31 10:39:47 -0700320 }
321 _hidl_cb(retval, resultPort);
322 return Void();
323}
324
Kevin Rocard72e50e22017-05-05 14:02:55 -0700325Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700326 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
327 struct audio_port_config halPortConfig;
Mikhail Naganov6e81e9b2016-11-16 16:30:17 -0800328 HidlUtils::audioPortConfigToHal(config, &halPortConfig);
Mikhail Naganov10548292016-10-31 10:39:47 -0700329 return analyzeStatus(
Kevin Rocard72e50e22017-05-05 14:02:55 -0700330 "set_audio_port_config",
331 mDevice->set_audio_port_config(mDevice, &halPortConfig));
Mikhail Naganov10548292016-10-31 10:39:47 -0700332 }
333 return Result::NOT_SUPPORTED;
334}
335
Kevin Rocard72e50e22017-05-05 14:02:55 -0700336Return<AudioHwSync> Device::getHwAvSync() {
Mikhail Naganov10548292016-10-31 10:39:47 -0700337 int halHwAvSync;
Mikhail Naganov86685f52017-05-03 16:39:28 +0000338 Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
Mikhail Naganov10548292016-10-31 10:39:47 -0700339 return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
340}
341
Kevin Rocard72e50e22017-05-05 14:02:55 -0700342Return<Result> Device::setScreenState(bool turnedOn) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000343 return setParam(AudioParameter::keyScreenState, turnedOn);
Mikhail Naganov10548292016-10-31 10:39:47 -0700344}
345
Kevin Rocard72e50e22017-05-05 14:02:55 -0700346Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys,
347 getParameters_cb _hidl_cb) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000348 getParametersImpl(keys, _hidl_cb);
Mikhail Naganov10548292016-10-31 10:39:47 -0700349 return Void();
350}
351
Kevin Rocard72e50e22017-05-05 14:02:55 -0700352Return<Result> Device::setParameters(
353 const hidl_vec<ParameterValue>& parameters) {
Mikhail Naganov86685f52017-05-03 16:39:28 +0000354 return setParametersImpl(parameters);
Mikhail Naganov10548292016-10-31 10:39:47 -0700355}
356
Kevin Rocard72e50e22017-05-05 14:02:55 -0700357Return<void> Device::debugDump(const hidl_handle& fd) {
Mikhail Naganov3e6fe752017-04-24 10:44:08 -0700358 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700359 analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
360 }
361 return Void();
362}
363
364} // namespace implementation
365} // namespace V2_0
366} // namespace audio
367} // namespace hardware
368} // namespace android