1 /*
2  * Copyright 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 #include "sysprops/sysprops_module.h"
18 
19 #include <filesystem>
20 
21 #include "os/handler.h"
22 #include "os/log.h"
23 #include "os/parameter_provider.h"
24 #include "os/system_properties.h"
25 #include "storage/legacy_config_file.h"
26 
27 namespace bluetooth {
28 namespace sysprops {
29 
30 static const size_t kDefaultCapacity = 10000;
31 static const char* kAflagSection = "Aflags";
32 static const char* kAflagPrefix = "persist.device_config.aconfig_flags.bluetooth.";
33 
SyspropsModule()34 SyspropsModule::SyspropsModule() {}
~SyspropsModule()35 SyspropsModule::~SyspropsModule() {
36   pimpl_.reset();
37 }
38 
__anon412fd4560102() 39 const ModuleFactory SyspropsModule::Factory = ModuleFactory([]() { return new SyspropsModule(); });
40 
41 struct SyspropsModule::impl {
implbluetooth::sysprops::SyspropsModule::impl42   impl(os::Handler* sysprops_handler) : sysprops_handler_(sysprops_handler) {}
43 
44   os::Handler* sysprops_handler_;
45 };
46 
ListDependencies(ModuleList *) const47 void SyspropsModule::ListDependencies(ModuleList* /* list */) const {}
48 
Start()49 void SyspropsModule::Start() {
50   std::string file_path = os::ParameterProvider::SyspropsFilePath();
51   if (!file_path.empty()) {
52     parse_config(file_path);
53     // Merge config fragments
54     std::string override_dir = file_path + ".d";
55     if (std::filesystem::exists(override_dir)) {
56       for (const auto& entry : std::filesystem::directory_iterator(override_dir)) {
57         parse_config(entry.path());
58       }
59     }
60   }
61 
62   pimpl_ = std::make_unique<impl>(GetHandler());
63 }
64 
Stop()65 void SyspropsModule::Stop() {
66   pimpl_.reset();
67 }
68 
ToString() const69 std::string SyspropsModule::ToString() const {
70   return "Sysprops Module";
71 }
72 
parse_config(std::string file_path)73 void SyspropsModule::parse_config(std::string file_path) {
74   const std::list<std::string> supported_sysprops = {
75       // General
76       "bluetooth.btm.sec.delay_auth_ms.value",
77       "bluetooth.device.default_name",
78       "bluetooth.core.gap.le.privacy.enabled",
79       "bluetooth.core.gap.le.privacy.own_address_type.enabled",
80       "bluetooth.core.gap.le.conn.only_init_1m_phy.enabled",
81       "bluetooth.device.class_of_device",
82       "bluetooth.device_id.product_id",
83       "bluetooth.device_id.product_version",
84       "bluetooth.device_id.vendor_id",
85       "bluetooth.device_id.vendor_id_source",
86       "persist.bluetooth.inq_by_rssi",
87       // BR/EDR
88       "bluetooth.core.classic.page_scan_type",
89       "bluetooth.core.classic.page_scan_interval",
90       "bluetooth.core.classic.page_scan_window",
91       "bluetooth.core.classic.inq_scan_type",
92       "bluetooth.core.classic.inq_scan_interval",
93       "bluetooth.core.classic.inq_scan_window",
94       "bluetooth.core.classic.inq_length",
95       "bluetooth.core.acl.link_supervision_timeout",
96       "bluetooth.core.classic.page_timeout",
97       "bluetooth.core.classic.sniff_max_intervals",
98       "bluetooth.core.classic.sniff_min_intervals",
99       "bluetooth.core.classic.sniff_attempts",
100       "bluetooth.core.classic.sniff_timeouts",
101       // LE
102       "bluetooth.core.le.min_connection_interval",
103       "bluetooth.core.le.max_connection_interval",
104       "bluetooth.core.le.connection_latency",
105       "bluetooth.core.le.connection_supervision_timeout",
106       "bluetooth.core.le.direct_connection_timeout",
107       "bluetooth.core.le.connection_scan_interval_fast",
108       "bluetooth.core.le.connection_scan_window_fast",
109       "bluetooth.core.le.connection_scan_window_2m_fast",
110       "bluetooth.core.le.connection_scan_window_coded_fast",
111       "bluetooth.core.le.connection_scan_interval_slow",
112       "bluetooth.core.le.connection_scan_window_slow",
113       "bluetooth.core.le.connection_scan_interval_system_suspend",
114       "bluetooth.core.le.connection_scan_window_system_suspend",
115       "bluetooth.core.le.inquiry_scan_interval",
116       "bluetooth.core.le.inquiry_scan_window",
117       "bluetooth.core.le.adv_mon_scan_interval",
118       "bluetooth.core.le.adv_mon_scan_window",
119       "bluetooth.core.le.adv_mon_rtl_quirk",
120       "bluetooth.core.le.adv_mon_qca_quirk",
121       "bluetooth.core.le.vendor_capabilities.enabled",
122       // LE Audio
123       "bluetooth.le_audio.enable_le_audio_only",
124       "bluetooth.leaudio.dual_bidirection_swb.supported",
125       // SCO
126       "bluetooth.sco.disable_enhanced_connection",
127       "bluetooth.sco.swb_supported",
128       // Profile
129       "persist.bluetooth.avrcpcontrolversion",
130   };
131 
132   auto config = storage::LegacyConfigFile::FromPath(file_path).Read(kDefaultCapacity);
133   if (!config) {
134     return;
135   }
136 
137   for (auto s = supported_sysprops.begin(); s != supported_sysprops.end(); s++) {
138     auto str = config->GetProperty("Sysprops", *s);
139     if (str) {
140       bluetooth::os::SetSystemProperty(*s, *str);
141     }
142   }
143 
144   for (const auto& name : config->GetPropertyNames(kAflagSection)) {
145     if (name.find(kAflagPrefix) == 0) {
146       auto val = config->GetProperty(kAflagSection, name);
147       if (val) {
148         bluetooth::os::SetSystemProperty(name, *val);
149       }
150     }
151   }
152 }
153 
154 }  // namespace sysprops
155 }  // namespace bluetooth
156