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