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