• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <memory>
18 
19 #include "dumpsys/filter.h"
20 #include "dumpsys/internal/filter_internal.h"
21 #include "os/log.h"
22 
23 using namespace bluetooth;
24 using namespace dumpsys;
25 
26 class Filter {
27  public:
Filter(const dumpsys::ReflectionSchema & reflection_schema)28   Filter(const dumpsys::ReflectionSchema& reflection_schema) : reflection_schema_(reflection_schema) {}
29 
30   virtual ~Filter() = default;
31 
32   virtual void FilterInPlace(char* dumpsys_data) = 0;
33 
34   static std::unique_ptr<Filter> Factory(
35       dumpsys::FilterType filter_type, const dumpsys::ReflectionSchema& reflection_schema);
36 
37  protected:
38   /**
39    * Given both reflection field data and the populated flatbuffer table data, if any,
40    * filter the contents of the field based upon the filtering privacy level.
41    *
42    * Primitives and composite strings may be successfully processed at this point.
43    * Other composite types (e.g. structs or tables) must be expanded into the
44    * respective grouping of subfields.
45    *
46    * @param field The reflection field information from the bundled schema
47    * @param table The populated field data, if any
48    *
49    * @return true if field was filtered successfully, false otherwise.
50    */
FilterField(const reflection::Field * field,flatbuffers::Table * table)51   virtual bool FilterField(const reflection::Field* field, flatbuffers::Table* table) {
52     return false;
53   }
54 
55   /**
56    * Given both reflection object data and the populated flatbuffer table data, if any,
57    * filter the object fields based upon the filtering privacy level.
58    *
59    * @param object The reflection object information from the bundled schema
60    * @param table The populated field data, if any
61    *
62    */
FilterObject(const reflection::Object * object,flatbuffers::Table * table)63   virtual void FilterObject(const reflection::Object* object, flatbuffers::Table* table){};
64 
65   /**
66    * Given both reflection field data and the populated table data, if any,
67    * filter the contents of the table based upon the filtering privacy level.
68    *
69    * @param schema The reflection schema information from the bundled schema
70    * @param table The populated field data, if any
71    *
72    */
FilterTable(const reflection::Schema * schema,flatbuffers::Table * table)73   virtual void FilterTable(const reflection::Schema* schema, flatbuffers::Table* table){};
74 
75   const dumpsys::ReflectionSchema& reflection_schema_;
76 };
77 
78 class DeveloperPrivacyFilter : public Filter {
79  public:
DeveloperPrivacyFilter(const dumpsys::ReflectionSchema & reflection_schema)80   DeveloperPrivacyFilter(const dumpsys::ReflectionSchema& reflection_schema) : Filter(reflection_schema) {}
FilterInPlace(char * dumpsys_data)81   void FilterInPlace(char* dumpsys_data) override {}
82 };
83 
84 class UserPrivacyFilter : public Filter {
85  public:
UserPrivacyFilter(const dumpsys::ReflectionSchema & reflection_schema)86   UserPrivacyFilter(const dumpsys::ReflectionSchema& reflection_schema) : Filter(reflection_schema) {}
87   void FilterInPlace(char* dumpsys_data) override;
88 
89  protected:
90   bool FilterField(const reflection::Field* field, flatbuffers::Table* table) override;
91   void FilterObject(const reflection::Object* object, flatbuffers::Table* table) override;
92   void FilterTable(const reflection::Schema* schema, flatbuffers::Table* table) override;
93 };
94 
FilterField(const reflection::Field * field,flatbuffers::Table * table)95 bool UserPrivacyFilter::FilterField(const reflection::Field* field, flatbuffers::Table* table) {
96   ASSERT(field != nullptr);
97   ASSERT(table != nullptr);
98   internal::PrivacyLevel privacy_level = internal::FindFieldPrivacyLevel(*field);
99 
100   switch (field->type()->base_type()) {
101     case flatbuffers::BASE_TYPE_INT:
102       return internal::FilterTypeInteger(*field, table, privacy_level);
103       break;
104     case flatbuffers::BASE_TYPE_FLOAT:
105       return internal::FilterTypeFloat(*field, table, privacy_level);
106       break;
107     case flatbuffers::BASE_TYPE_STRING:
108       return internal::FilterTypeString(*field, table, privacy_level);
109       break;
110     case flatbuffers::BASE_TYPE_STRUCT:
111       return internal::FilterTypeStruct(*field, table, privacy_level);
112       break;
113     case flatbuffers::BASE_TYPE_BOOL:
114       return internal::FilterTypeBool(*field, table, privacy_level);
115       break;
116     default:
117       LOG_WARN("%s WARN Unsupported base type\n", __func__);
118       break;
119   }
120   return false;
121 }
122 
FilterObject(const reflection::Object * object,flatbuffers::Table * table)123 void UserPrivacyFilter::FilterObject(const reflection::Object* object, flatbuffers::Table* table) {
124   ASSERT(object != nullptr);
125   if (table == nullptr) {
126     return;  // table data is not populated
127   }
128   for (auto it = object->fields()->cbegin(); it != object->fields()->cend(); ++it) {
129     if (!FilterField(*it, table)) {
130       LOG_ERROR("%s Unable to filter field from an object when it's expected it will work", __func__);
131     };
132   }
133 }
134 
FilterTable(const reflection::Schema * schema,flatbuffers::Table * table)135 void UserPrivacyFilter::FilterTable(const reflection::Schema* schema, flatbuffers::Table* table) {
136   if (schema == nullptr) {
137     LOG_WARN("%s schema is nullptr...probably ok", __func__);
138     return;
139   }
140 
141   const reflection::Object* object = schema->root_table();
142   if (object == nullptr) {
143     LOG_WARN("%s reflection object is nullptr...is ok ?", __func__);
144     return;
145   }
146 
147   if (table == nullptr) {
148     return;  // table not populated
149   }
150 
151   for (auto it = object->fields()->cbegin(); it != object->fields()->cend(); ++it) {
152     if (FilterField(*it, table)) {
153       continue;  // Field successfully filtered
154     }
155     // Get the index of this complex non-string object from the schema which is
156     // also the same index into the data table.
157     int32_t index = it->type()->index();
158     ASSERT(index != -1);
159 
160     flatbuffers::Table* sub_table = table->GetPointer<flatbuffers::Table*>(it->offset());
161     const reflection::Schema* sub_schema =
162         reflection_schema_.FindInReflectionSchema(schema->objects()->Get(index)->name()->str());
163 
164     if (sub_schema != nullptr) {
165       FilterTable(sub_schema, sub_table);  // Top level schema
166     } else {
167       // Leaf node schema
168       const flatbuffers::String* name = schema->objects()->Get(index)->name();
169       const reflection::Object* sub_object = internal::FindReflectionObject(schema->objects(), name);
170       if (sub_object != nullptr) {
171         FilterObject(sub_object, sub_table);
172       } else {
173         LOG_ERROR("Unable to find reflection sub object:%s\n", name->c_str());
174       }
175     }
176   }
177 }
178 
FilterInPlace(char * dumpsys_data)179 void UserPrivacyFilter::FilterInPlace(char* dumpsys_data) {
180   ASSERT(dumpsys_data != nullptr);
181   const reflection::Schema* root_schema = reflection_schema_.FindInReflectionSchema(reflection_schema_.GetRootName());
182   flatbuffers::Table* table = const_cast<flatbuffers::Table*>(flatbuffers::GetRoot<flatbuffers::Table>(dumpsys_data));
183   FilterTable(root_schema, table);
184 }
185 
Factory(dumpsys::FilterType filter_type,const dumpsys::ReflectionSchema & reflection_schema)186 std::unique_ptr<Filter> Filter::Factory(
187     dumpsys::FilterType filter_type, const dumpsys::ReflectionSchema& reflection_schema) {
188   switch (filter_type) {
189     case dumpsys::FilterType::AS_DEVELOPER:
190       return std::make_unique<DeveloperPrivacyFilter>(reflection_schema);
191     default:
192       return std::make_unique<UserPrivacyFilter>(reflection_schema);
193   }
194 }
195 
FilterInPlace(FilterType filter_type,const ReflectionSchema & reflection_schema,std::string * dumpsys_data)196 void bluetooth::dumpsys::FilterInPlace(
197     FilterType filter_type, const ReflectionSchema& reflection_schema, std::string* dumpsys_data) {
198   auto filter = Filter::Factory(filter_type, reflection_schema);
199   filter->FilterInPlace(dumpsys_data->data());
200 }
201