From 3cbf176e7c6a96c535f56cb7d10e2de79a54cbd0 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 13 Dec 2018 16:04:56 -0800 Subject: [view-compiler] Add layout validation Layout validation walks over a layout resource and verifies that the layout only uses features the layout compiler supports. Currently this means we reject layouts that use any of the following tags: * include * fragment * merge * view In the future, we will extend the layout compiler to handle these, but for now we want to be liberal in what we reject. Bug: 111895153 Test: atest view-compiler-tests Change-Id: I8dca30c035a83b6763497a36fc60c68438fa1b0c --- startop/view_compiler/Android.bp | 7 +- startop/view_compiler/layout_validation.cc | 42 ++++++ startop/view_compiler/layout_validation.h | 46 +++++++ startop/view_compiler/layout_validation_test.cc | 163 ++++++++++++++++++++++++ startop/view_compiler/main.cc | 7 + startop/view_compiler/tinyxml_layout_parser.cc | 34 +++++ startop/view_compiler/tinyxml_layout_parser.h | 65 ++++++++++ 7 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 startop/view_compiler/layout_validation.cc create mode 100644 startop/view_compiler/layout_validation.h create mode 100644 startop/view_compiler/layout_validation_test.cc create mode 100644 startop/view_compiler/tinyxml_layout_parser.cc create mode 100644 startop/view_compiler/tinyxml_layout_parser.h diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp index de40e0df48e7..91cec554d7cd 100644 --- a/startop/view_compiler/Android.bp +++ b/startop/view_compiler/Android.bp @@ -24,6 +24,9 @@ cc_defaults { "libdexfile", "slicer", ], + static_libs: [ + "libtinyxml2", + ], } cc_library_host_static { @@ -32,7 +35,9 @@ cc_library_host_static { srcs: [ "dex_builder.cc", "java_lang_builder.cc", + "tinyxml_layout_parser.cc", "util.cc", + "layout_validation.cc", ], } @@ -43,7 +48,6 @@ cc_binary_host { "main.cc", ], static_libs: [ - "libtinyxml2", "libgflags", "libviewcompiler", ], @@ -54,6 +58,7 @@ cc_test_host { defaults: ["viewcompiler_defaults"], srcs: [ "dex_builder_test.cc", + "layout_validation_test.cc", "util_test.cc", ], static_libs: [ diff --git a/startop/view_compiler/layout_validation.cc b/startop/view_compiler/layout_validation.cc new file mode 100644 index 000000000000..8c7737749124 --- /dev/null +++ b/startop/view_compiler/layout_validation.cc @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "layout_validation.h" + +#include "android-base/stringprintf.h" + +namespace startop { + +void LayoutValidationVisitor::VisitStartTag(const std::u16string& name) { + if (0 == name.compare(u"merge")) { + message_ = "Merge tags are not supported"; + can_compile_ = false; + } + if (0 == name.compare(u"include")) { + message_ = "Include tags are not supported"; + can_compile_ = false; + } + if (0 == name.compare(u"view")) { + message_ = "View tags are not supported"; + can_compile_ = false; + } + if (0 == name.compare(u"fragment")) { + message_ = "Fragment tags are not supported"; + can_compile_ = false; + } +} + +} // namespace startop \ No newline at end of file diff --git a/startop/view_compiler/layout_validation.h b/startop/view_compiler/layout_validation.h new file mode 100644 index 000000000000..bed34bb38e5e --- /dev/null +++ b/startop/view_compiler/layout_validation.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LAYOUT_VALIDATION_H_ +#define LAYOUT_VALIDATION_H_ + +#include "dex_builder.h" + +#include + +namespace startop { + +// This visitor determines whether a layout can be compiled. Since we do not currently support all +// features, such as includes and merges, we need to pre-validate the layout before we start +// compiling. +class LayoutValidationVisitor { + public: + void VisitStartDocument() const {} + void VisitEndDocument() const {} + void VisitStartTag(const std::u16string& name); + void VisitEndTag() const {} + + const std::string& message() const { return message_; } + bool can_compile() const { return can_compile_; } + + private: + std::string message_{"Okay"}; + bool can_compile_{true}; +}; + +} // namespace startop + +#endif // LAYOUT_VALIDATION_H_ diff --git a/startop/view_compiler/layout_validation_test.cc b/startop/view_compiler/layout_validation_test.cc new file mode 100644 index 000000000000..b74cdae8d725 --- /dev/null +++ b/startop/view_compiler/layout_validation_test.cc @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tinyxml_layout_parser.h" + +#include "gtest/gtest.h" + +using startop::CanCompileLayout; +using std::string; + +namespace { +void ValidateXmlText(const string& xml, bool expected) { + tinyxml2::XMLDocument doc; + doc.Parse(xml.c_str()); + EXPECT_EQ(CanCompileLayout(doc), expected); +} +} // namespace + +TEST(LayoutValidationTest, SingleButtonLayout) { + const string xml = R"( +)"; + ValidateXmlText(xml, /*expected=*/true); +} + +TEST(LayoutValidationTest, SmallConstraintLayout) { + const string xml = R"( + + +