1 /*
2  * Copyright (C) 2020 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 #ifndef ANDROID_AUDIO_CONFIG_H
18 #define ANDROID_AUDIO_CONFIG_H
19 
20 #ifdef __cplusplus
21 
22 #include <string>
23 #include <unistd.h>
24 #include <vector>
25 
26 #include <cutils/properties.h>
27 
28 namespace android {
29 
30 // Returns a vector of paths where audio configuration files
31 // must be searched, in the provided order.
audio_get_configuration_paths()32 static inline std::vector<std::string> audio_get_configuration_paths() {
33     static const std::vector<std::string> paths = []() {
34         char value[PROPERTY_VALUE_MAX] = {};
35         if (property_get("ro.boot.product.vendor.sku", value, "") <= 0) {
36             return std::vector<std::string>({"/odm/etc", "/vendor/etc", "/system/etc"});
37         } else {
38             return std::vector<std::string>({
39                     "/odm/etc", std::string("/vendor/etc/audio/sku_") + value,
40                     "/vendor/etc", "/system/etc"});
41         }
42     }();
43     return paths;
44 }
45 
audio_find_readable_configuration_file(const char * fileName)46 static inline std::string audio_find_readable_configuration_file(const char* fileName) {
47     for (const auto& path : audio_get_configuration_paths()) {
48         std::string tryPath = path + "/" + fileName;
49         if (access(tryPath.c_str(), R_OK) == 0) {
50             return tryPath;
51         }
52     }
53     return {};
54 }
55 
audio_get_audio_policy_config_file()56 static inline std::string audio_get_audio_policy_config_file() {
57     static constexpr const char *apmXmlConfigFileName = "audio_policy_configuration.xml";
58     static constexpr const char *apmA2dpOffloadDisabledXmlConfigFileName =
59             "audio_policy_configuration_a2dp_offload_disabled.xml";
60     static constexpr const char *apmBluetoothLegacyHalXmlConfigFileName =
61             "audio_policy_configuration_bluetooth_legacy_hal.xml";
62 
63     std::string audioPolicyXmlConfigFile;
64     // First try alternative files if needed
65     if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false)) {
66         if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false) &&
67             property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
68             // Both BluetoothAudio@2.0 and BluetoothA2dp@1.0 (Offload) are disabled, and uses
69             // the legacy hardware module for A2DP and hearing aid.
70             audioPolicyXmlConfigFile = audio_find_readable_configuration_file(
71                     apmBluetoothLegacyHalXmlConfigFileName);
72         } else if (property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
73             // A2DP offload supported but disabled: try to use special XML file
74             audioPolicyXmlConfigFile = audio_find_readable_configuration_file(
75                     apmA2dpOffloadDisabledXmlConfigFileName);
76         }
77     } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false)) {
78         audioPolicyXmlConfigFile = audio_find_readable_configuration_file(
79                 apmBluetoothLegacyHalXmlConfigFileName);
80     }
81     return audioPolicyXmlConfigFile.empty() ?
82             audio_find_readable_configuration_file(apmXmlConfigFileName) : audioPolicyXmlConfigFile;
83 }
84 
85 }  // namespace android
86 
87 #endif  // __cplusplus
88 
89 #endif  // ANDROID_AUDIO_CONFIG_H
90