1 /*
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"
18 //#define LOG_NDEBUG 0
19
20 #include <algorithm>
21 #include <memory.h>
22 #include <string.h>
23
24 #include <android/log.h>
25
26 #include "Conversions.h"
27 #include "Device.h"
28 #include "HidlUtils.h"
29 #include "StreamIn.h"
30 #include "StreamOut.h"
31 #include "Util.h"
32
33 namespace android {
34 namespace hardware {
35 namespace audio {
36 namespace V2_0 {
37 namespace implementation {
38
Device(audio_hw_device_t * device)39 Device::Device(audio_hw_device_t* device)
40 : mDevice(device) {
41 }
42
~Device()43 Device::~Device() {
44 int status = audio_hw_device_close(mDevice);
45 ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice,
46 strerror(-status));
47 mDevice = nullptr;
48 }
49
analyzeStatus(const char * funcName,int status)50 Result Device::analyzeStatus(const char* funcName, int status) {
51 if (status != 0) {
52 ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
53 }
54 switch (status) {
55 case 0:
56 return Result::OK;
57 case -EINVAL:
58 return Result::INVALID_ARGUMENTS;
59 case -ENODATA:
60 return Result::INVALID_STATE;
61 case -ENODEV:
62 return Result::NOT_INITIALIZED;
63 case -ENOSYS:
64 return Result::NOT_SUPPORTED;
65 default:
66 return Result::INVALID_STATE;
67 }
68 }
69
closeInputStream(audio_stream_in_t * stream)70 void Device::closeInputStream(audio_stream_in_t* stream) {
71 mDevice->close_input_stream(mDevice, stream);
72 }
73
closeOutputStream(audio_stream_out_t * stream)74 void Device::closeOutputStream(audio_stream_out_t* stream) {
75 mDevice->close_output_stream(mDevice, stream);
76 }
77
halGetParameters(const char * keys)78 char* Device::halGetParameters(const char* keys) {
79 return mDevice->get_parameters(mDevice, keys);
80 }
81
halSetParameters(const char * keysAndValues)82 int Device::halSetParameters(const char* keysAndValues) {
83 return mDevice->set_parameters(mDevice, keysAndValues);
84 }
85
86 // Methods from ::android::hardware::audio::V2_0::IDevice follow.
initCheck()87 Return<Result> Device::initCheck() {
88 return analyzeStatus("init_check", mDevice->init_check(mDevice));
89 }
90
setMasterVolume(float volume)91 Return<Result> Device::setMasterVolume(float volume) {
92 if (mDevice->set_master_volume == NULL) {
93 return Result::NOT_SUPPORTED;
94 }
95 if (!isGainNormalized(volume)) {
96 ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
97 return Result::INVALID_ARGUMENTS;
98 }
99 return analyzeStatus("set_master_volume",
100 mDevice->set_master_volume(mDevice, volume));
101 }
102
getMasterVolume(getMasterVolume_cb _hidl_cb)103 Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
104 Result retval(Result::NOT_SUPPORTED);
105 float volume = 0;
106 if (mDevice->get_master_volume != NULL) {
107 retval = analyzeStatus("get_master_volume",
108 mDevice->get_master_volume(mDevice, &volume));
109 }
110 _hidl_cb(retval, volume);
111 return Void();
112 }
113
setMicMute(bool mute)114 Return<Result> Device::setMicMute(bool mute) {
115 return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
116 }
117
getMicMute(getMicMute_cb _hidl_cb)118 Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
119 bool mute = false;
120 Result retval =
121 analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
122 _hidl_cb(retval, mute);
123 return Void();
124 }
125
setMasterMute(bool mute)126 Return<Result> Device::setMasterMute(bool mute) {
127 Result retval(Result::NOT_SUPPORTED);
128 if (mDevice->set_master_mute != NULL) {
129 retval = analyzeStatus("set_master_mute",
130 mDevice->set_master_mute(mDevice, mute));
131 }
132 return retval;
133 }
134
getMasterMute(getMasterMute_cb _hidl_cb)135 Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
136 Result retval(Result::NOT_SUPPORTED);
137 bool mute = false;
138 if (mDevice->get_master_mute != NULL) {
139 retval = analyzeStatus("get_master_mute",
140 mDevice->get_master_mute(mDevice, &mute));
141 }
142 _hidl_cb(retval, mute);
143 return Void();
144 }
145
getInputBufferSize(const AudioConfig & config,getInputBufferSize_cb _hidl_cb)146 Return<void> Device::getInputBufferSize(const AudioConfig& config,
147 getInputBufferSize_cb _hidl_cb) {
148 audio_config_t halConfig;
149 HidlUtils::audioConfigToHal(config, &halConfig);
150 size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
151 Result retval(Result::INVALID_ARGUMENTS);
152 uint64_t bufferSize = 0;
153 if (halBufferSize != 0) {
154 retval = Result::OK;
155 bufferSize = halBufferSize;
156 }
157 _hidl_cb(retval, bufferSize);
158 return Void();
159 }
160
openOutputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,AudioOutputFlag flags,openOutputStream_cb _hidl_cb)161 Return<void> Device::openOutputStream(int32_t ioHandle,
162 const DeviceAddress& device,
163 const AudioConfig& config,
164 AudioOutputFlag flags,
165 openOutputStream_cb _hidl_cb) {
166 audio_config_t halConfig;
167 HidlUtils::audioConfigToHal(config, &halConfig);
168 audio_stream_out_t* halStream;
169 ALOGV(
170 "open_output_stream handle: %d devices: %x flags: %#x "
171 "srate: %d format %#x channels %x address %s",
172 ioHandle, static_cast<audio_devices_t>(device.device),
173 static_cast<audio_output_flags_t>(flags), halConfig.sample_rate,
174 halConfig.format, halConfig.channel_mask,
175 deviceAddressToHal(device).c_str());
176 int status = mDevice->open_output_stream(
177 mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
178 static_cast<audio_output_flags_t>(flags), &halConfig, &halStream,
179 deviceAddressToHal(device).c_str());
180 ALOGV("open_output_stream status %d stream %p", status, halStream);
181 sp<IStreamOut> streamOut;
182 if (status == OK) {
183 streamOut = new StreamOut(this, halStream);
184 }
185 AudioConfig suggestedConfig;
186 HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
187 _hidl_cb(analyzeStatus("open_output_stream", status), streamOut,
188 suggestedConfig);
189 return Void();
190 }
191
openInputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,AudioInputFlag flags,AudioSource source,openInputStream_cb _hidl_cb)192 Return<void> Device::openInputStream(int32_t ioHandle,
193 const DeviceAddress& device,
194 const AudioConfig& config,
195 AudioInputFlag flags, AudioSource source,
196 openInputStream_cb _hidl_cb) {
197 audio_config_t halConfig;
198 HidlUtils::audioConfigToHal(config, &halConfig);
199 audio_stream_in_t* halStream;
200 ALOGV(
201 "open_input_stream handle: %d devices: %x flags: %#x "
202 "srate: %d format %#x channels %x address %s source %d",
203 ioHandle, static_cast<audio_devices_t>(device.device),
204 static_cast<audio_input_flags_t>(flags), halConfig.sample_rate,
205 halConfig.format, halConfig.channel_mask,
206 deviceAddressToHal(device).c_str(),
207 static_cast<audio_source_t>(source));
208 int status = mDevice->open_input_stream(
209 mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
210 &halConfig, &halStream, static_cast<audio_input_flags_t>(flags),
211 deviceAddressToHal(device).c_str(),
212 static_cast<audio_source_t>(source));
213 ALOGV("open_input_stream status %d stream %p", status, halStream);
214 sp<IStreamIn> streamIn;
215 if (status == OK) {
216 streamIn = new StreamIn(this, halStream);
217 }
218 AudioConfig suggestedConfig;
219 HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
220 _hidl_cb(analyzeStatus("open_input_stream", status), streamIn,
221 suggestedConfig);
222 return Void();
223 }
224
supportsAudioPatches()225 Return<bool> Device::supportsAudioPatches() {
226 return version() >= AUDIO_DEVICE_API_VERSION_3_0;
227 }
228
createAudioPatch(const hidl_vec<AudioPortConfig> & sources,const hidl_vec<AudioPortConfig> & sinks,createAudioPatch_cb _hidl_cb)229 Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
230 const hidl_vec<AudioPortConfig>& sinks,
231 createAudioPatch_cb _hidl_cb) {
232 Result retval(Result::NOT_SUPPORTED);
233 AudioPatchHandle patch = 0;
234 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
235 std::unique_ptr<audio_port_config[]> halSources(
236 HidlUtils::audioPortConfigsToHal(sources));
237 std::unique_ptr<audio_port_config[]> halSinks(
238 HidlUtils::audioPortConfigsToHal(sinks));
239 audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
240 retval = analyzeStatus(
241 "create_audio_patch",
242 mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
243 sinks.size(), &halSinks[0], &halPatch));
244 if (retval == Result::OK) {
245 patch = static_cast<AudioPatchHandle>(halPatch);
246 }
247 }
248 _hidl_cb(retval, patch);
249 return Void();
250 }
251
releaseAudioPatch(int32_t patch)252 Return<Result> Device::releaseAudioPatch(int32_t patch) {
253 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
254 return analyzeStatus(
255 "release_audio_patch",
256 mDevice->release_audio_patch(
257 mDevice, static_cast<audio_patch_handle_t>(patch)));
258 }
259 return Result::NOT_SUPPORTED;
260 }
261
getAudioPort(const AudioPort & port,getAudioPort_cb _hidl_cb)262 Return<void> Device::getAudioPort(const AudioPort& port,
263 getAudioPort_cb _hidl_cb) {
264 audio_port halPort;
265 HidlUtils::audioPortToHal(port, &halPort);
266 Result retval = analyzeStatus("get_audio_port",
267 mDevice->get_audio_port(mDevice, &halPort));
268 AudioPort resultPort = port;
269 if (retval == Result::OK) {
270 HidlUtils::audioPortFromHal(halPort, &resultPort);
271 }
272 _hidl_cb(retval, resultPort);
273 return Void();
274 }
275
setAudioPortConfig(const AudioPortConfig & config)276 Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
277 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
278 struct audio_port_config halPortConfig;
279 HidlUtils::audioPortConfigToHal(config, &halPortConfig);
280 return analyzeStatus(
281 "set_audio_port_config",
282 mDevice->set_audio_port_config(mDevice, &halPortConfig));
283 }
284 return Result::NOT_SUPPORTED;
285 }
286
getHwAvSync()287 Return<AudioHwSync> Device::getHwAvSync() {
288 int halHwAvSync;
289 Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
290 return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
291 }
292
setScreenState(bool turnedOn)293 Return<Result> Device::setScreenState(bool turnedOn) {
294 return setParam(AudioParameter::keyScreenState, turnedOn);
295 }
296
getParameters(const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)297 Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys,
298 getParameters_cb _hidl_cb) {
299 getParametersImpl(keys, _hidl_cb);
300 return Void();
301 }
302
setParameters(const hidl_vec<ParameterValue> & parameters)303 Return<Result> Device::setParameters(
304 const hidl_vec<ParameterValue>& parameters) {
305 return setParametersImpl(parameters);
306 }
307
debugDump(const hidl_handle & fd)308 Return<void> Device::debugDump(const hidl_handle& fd) {
309 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
310 analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
311 }
312 return Void();
313 }
314
315 } // namespace implementation
316 } // namespace V2_0
317 } // namespace audio
318 } // namespace hardware
319 } // namespace android
320