1 /*
2  * Copyright (C) 2018 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 "DevicesFactoryHAL"
18 
19 #include "core/default/DevicesFactory.h"
20 #include "core/default/Device.h"
21 #include "core/default/PrimaryDevice.h"
22 
23 #include <string.h>
24 
25 #include <android/log.h>
26 #include <hidl/HidlTransportSupport.h>
27 #include <system/thread_defs.h>
28 
29 namespace android {
30 namespace hardware {
31 namespace audio {
32 namespace CPP_VERSION {
33 namespace implementation {
34 
35 #if MAJOR_VERSION == 2
openDevice(IDevicesFactory::Device device,openDevice_cb _hidl_cb)36 Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) {
37     switch (device) {
38         case IDevicesFactory::Device::PRIMARY:
39             return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
40         case IDevicesFactory::Device::A2DP:
41             return openDevice(AUDIO_HARDWARE_MODULE_ID_A2DP, _hidl_cb);
42         case IDevicesFactory::Device::USB:
43             return openDevice(AUDIO_HARDWARE_MODULE_ID_USB, _hidl_cb);
44         case IDevicesFactory::Device::R_SUBMIX:
45             return openDevice(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, _hidl_cb);
46         case IDevicesFactory::Device::STUB:
47             return openDevice(AUDIO_HARDWARE_MODULE_ID_STUB, _hidl_cb);
48     }
49     _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
50     return Void();
51 }
52 
openDevice(const char * moduleName,openDevice_cb _hidl_cb)53 Return<void> DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) {
54     return openDevice<implementation::Device>(moduleName, _hidl_cb);
55 }
56 #elif MAJOR_VERSION >= 4
57 Return<void> DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) {
58     if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
59         return openDevice<PrimaryDevice>(moduleName.c_str(), _hidl_cb);
60     }
61     return openDevice<implementation::Device>(moduleName.c_str(), _hidl_cb);
62 }
63 Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
64     return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
65 }
66 #endif
67 
68 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
openDevice_7_1(const hidl_string & moduleName,openDevice_7_1_cb _hidl_cb)69 Return<void> DevicesFactory::openDevice_7_1(const hidl_string& moduleName,
70                                             openDevice_7_1_cb _hidl_cb) {
71     if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
72         Result result;
73         sp<IPrimaryDevice> primary;
74         auto ret = openDevice<PrimaryDevice>(
75                 AUDIO_HARDWARE_MODULE_ID_PRIMARY,
76                 [&result, &primary](Result r, const sp<IPrimaryDevice>& p) {
77                     result = r;
78                     primary = p;
79                 });
80         if (ret.isOk() && result == Result::OK && primary != nullptr) {
81             auto getDeviceRet = primary->getDevice();
82             if (getDeviceRet.isOk()) {
83                 _hidl_cb(result, getDeviceRet);
84             } else {
85                 _hidl_cb(Result::NOT_INITIALIZED, nullptr);
86             }
87         } else {
88             _hidl_cb(result, nullptr);
89         }
90         return Void();
91     }
92     return openDevice<implementation::Device>(moduleName.c_str(), _hidl_cb);
93 }
94 
openPrimaryDevice_7_1(openPrimaryDevice_7_1_cb _hidl_cb)95 Return<void> DevicesFactory::openPrimaryDevice_7_1(openPrimaryDevice_7_1_cb _hidl_cb) {
96     return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
97 }
98 #endif  // V7.1
99 
100 template <class DeviceShim, class Callback>
openDevice(const char * moduleName,Callback _hidl_cb)101 Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
102     audio_hw_device_t* halDevice;
103     Result retval(Result::INVALID_ARGUMENTS);
104     sp<DeviceShim> result;
105     int halStatus = loadAudioInterface(moduleName, &halDevice);
106     if (halStatus == OK) {
107         result = new DeviceShim(halDevice);
108         android::hardware::setMinSchedulerPolicy(result, SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
109         retval = Result::OK;
110     } else if (halStatus == -EINVAL) {
111         retval = Result::NOT_INITIALIZED;
112     }
113     _hidl_cb(retval, result);
114     return Void();
115 }
116 
117 // static
loadAudioInterface(const char * if_name,audio_hw_device_t ** dev)118 int DevicesFactory::loadAudioInterface(const char* if_name, audio_hw_device_t** dev) {
119     const hw_module_t* mod;
120     int rc;
121 
122     rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
123     if (rc) {
124         ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID,
125               if_name, strerror(-rc));
126         goto out;
127     }
128     rc = audio_hw_device_open(mod, dev);
129     if (rc) {
130         ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID,
131               if_name, strerror(-rc));
132         goto out;
133     }
134     if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
135         ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
136         rc = -EINVAL;
137         audio_hw_device_close(*dev);
138         goto out;
139     }
140     return OK;
141 
142 out:
143     *dev = NULL;
144     return rc;
145 }
146 
HIDL_FETCH_IDevicesFactory(const char * name)147 IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name) {
148     return strcmp(name, "default") == 0 ? new DevicesFactory() : nullptr;
149 }
150 
151 }  // namespace implementation
152 }  // namespace CPP_VERSION
153 }  // namespace audio
154 }  // namespace hardware
155 }  // namespace android
156