1 /*
2 * Copyright 2019 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 #define LOG_TAG "bt_gd_shim"
17
18 #include "dumpsys/dumpsys.h"
19
20 #include <future>
21 #include <string>
22
23 #include "dumpsys/filter.h"
24 #include "module.h"
25 #include "os/log.h"
26 #include "os/system_properties.h"
27 #include "shim/dumpsys.h"
28 #include "shim/dumpsys_args.h"
29
30 namespace bluetooth {
31 namespace shim {
32
33 static const std::string kReadOnlyDebuggableProperty = "ro.debuggable";
34
35 namespace {
36 constexpr char kModuleName[] = "shim::Dumpsys";
37 constexpr char kDumpsysTitle[] = "----- Gd Dumpsys ------";
38 } // namespace
39
40 struct Dumpsys::impl {
41 public:
42 void DumpWithArgsSync(int fd, const char** args, std::promise<void> promise);
43 int GetNumberOfBundledSchemas() const;
44
45 impl(const Dumpsys& dumpsys_module, const dumpsys::ReflectionSchema& reflection_schema);
46 ~impl() = default;
47
48 protected:
49 void FilterAsUser(std::string* dumpsys_data);
50 void FilterAsDeveloper(std::string* dumpsys_data);
51 std::string PrintAsJson(std::string* dumpsys_data) const;
52
53 bool IsDebuggable() const;
54
55 private:
56 void DumpWithArgsAsync(int fd, const char** args);
57
58 const Dumpsys& dumpsys_module_;
59 const dumpsys::ReflectionSchema reflection_schema_;
60 };
61
62 const ModuleFactory Dumpsys::Factory =
__anonb7b255dd0202() 63 ModuleFactory([]() { return new Dumpsys(bluetooth::dumpsys::GetBundledSchemaData()); });
64
impl(const Dumpsys & dumpsys_module,const dumpsys::ReflectionSchema & reflection_schema)65 Dumpsys::impl::impl(const Dumpsys& dumpsys_module, const dumpsys::ReflectionSchema& reflection_schema)
66 : dumpsys_module_(dumpsys_module), reflection_schema_(std::move(reflection_schema)) {}
67
GetNumberOfBundledSchemas() const68 int Dumpsys::impl::GetNumberOfBundledSchemas() const {
69 return reflection_schema_.GetNumberOfBundledSchemas();
70 }
71
IsDebuggable() const72 bool Dumpsys::impl::IsDebuggable() const {
73 return (os::GetSystemProperty(kReadOnlyDebuggableProperty) == "1");
74 }
75
FilterAsDeveloper(std::string * dumpsys_data)76 void Dumpsys::impl::FilterAsDeveloper(std::string* dumpsys_data) {
77 ASSERT(dumpsys_data != nullptr);
78 dumpsys::FilterInPlace(dumpsys::FilterType::AS_DEVELOPER, reflection_schema_, dumpsys_data);
79 }
80
FilterAsUser(std::string * dumpsys_data)81 void Dumpsys::impl::FilterAsUser(std::string* dumpsys_data) {
82 ASSERT(dumpsys_data != nullptr);
83 dumpsys::FilterInPlace(dumpsys::FilterType::AS_USER, reflection_schema_, dumpsys_data);
84 }
85
PrintAsJson(std::string * dumpsys_data) const86 std::string Dumpsys::impl::PrintAsJson(std::string* dumpsys_data) const {
87 ASSERT(dumpsys_data != nullptr);
88
89 const std::string root_name = reflection_schema_.GetRootName();
90 if (root_name.empty()) {
91 char buf[255];
92 snprintf(buf, sizeof(buf), "ERROR: Unable to find root name in prebundled reflection schema\n");
93 LOG_WARN("%s", buf);
94 return std::string(buf);
95 }
96
97 const reflection::Schema* schema = reflection_schema_.FindInReflectionSchema(root_name);
98 if (schema == nullptr) {
99 char buf[255];
100 snprintf(buf, sizeof(buf), "ERROR: Unable to find schema root name:%s\n", root_name.c_str());
101 LOG_WARN("%s", buf);
102 return std::string(buf);
103 }
104
105 flatbuffers::IDLOptions options{};
106 options.output_default_scalars_in_json = true;
107 flatbuffers::Parser parser{options};
108 if (!parser.Deserialize(schema)) {
109 char buf[255];
110 snprintf(buf, sizeof(buf), "ERROR: Unable to deserialize bundle root name:%s\n", root_name.c_str());
111 LOG_WARN("%s", buf);
112 return std::string(buf);
113 }
114
115 std::string jsongen;
116 flatbuffers::GenerateText(parser, dumpsys_data->data(), &jsongen);
117 return jsongen;
118 }
119
DumpWithArgsAsync(int fd,const char ** args)120 void Dumpsys::impl::DumpWithArgsAsync(int fd, const char** args) {
121 ParsedDumpsysArgs parsed_dumpsys_args(args);
122 const auto registry = dumpsys_module_.GetModuleRegistry();
123
124 ModuleDumper dumper(*registry, kDumpsysTitle);
125 std::string dumpsys_data;
126 dumper.DumpState(&dumpsys_data);
127
128 dprintf(fd, " ----- Filtering as Developer -----\n");
129 FilterAsDeveloper(&dumpsys_data);
130
131 dprintf(fd, "%s", PrintAsJson(&dumpsys_data).c_str());
132 }
133
DumpWithArgsSync(int fd,const char ** args,std::promise<void> promise)134 void Dumpsys::impl::DumpWithArgsSync(int fd, const char** args, std::promise<void> promise) {
135 DumpWithArgsAsync(fd, args);
136 promise.set_value();
137 }
138
Dumpsys(const std::string & pre_bundled_schema)139 Dumpsys::Dumpsys(const std::string& pre_bundled_schema)
140 : reflection_schema_(dumpsys::ReflectionSchema(pre_bundled_schema)) {}
141
Dump(int fd,const char ** args)142 void Dumpsys::Dump(int fd, const char** args) {
143 if (fd <= 0) {
144 return;
145 }
146 std::promise<void> promise;
147 auto future = promise.get_future();
148 CallOn(pimpl_.get(), &Dumpsys::impl::DumpWithArgsSync, fd, args, std::move(promise));
149 future.get();
150 }
151
Dump(int fd,const char ** args,std::promise<void> promise)152 void Dumpsys::Dump(int fd, const char** args, std::promise<void> promise) {
153 if (fd <= 0) {
154 promise.set_value();
155 return;
156 }
157 CallOn(pimpl_.get(), &Dumpsys::impl::DumpWithArgsSync, fd, args, std::move(promise));
158 }
159
GetGdShimHandler()160 os::Handler* Dumpsys::GetGdShimHandler() {
161 return GetHandler();
162 }
163
164 /**
165 * Module methods
166 */
ListDependencies(ModuleList * list) const167 void Dumpsys::ListDependencies(ModuleList* list) const {}
168
Start()169 void Dumpsys::Start() {
170 pimpl_ = std::make_unique<impl>(*this, reflection_schema_);
171 }
172
Stop()173 void Dumpsys::Stop() {
174 pimpl_.reset();
175 }
176
GetDumpsysData(flatbuffers::FlatBufferBuilder * fb_builder) const177 DumpsysDataFinisher Dumpsys::GetDumpsysData(flatbuffers::FlatBufferBuilder* fb_builder) const {
178 auto name = fb_builder->CreateString("----- Shim Dumpsys -----");
179
180 DumpsysModuleDataBuilder builder(*fb_builder);
181 builder.add_title(name);
182 builder.add_number_of_bundled_schemas(pimpl_->GetNumberOfBundledSchemas());
183 auto dumpsys_data = builder.Finish();
184
185 return [dumpsys_data](DumpsysDataBuilder* builder) { builder->add_shim_dumpsys_data(dumpsys_data); };
186 }
187
ToString() const188 std::string Dumpsys::ToString() const {
189 return kModuleName;
190 }
191
192 } // namespace shim
193 } // namespace bluetooth
194