• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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