1 /*
2  * Copyright (C) 2017 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 "benchmark/benchmark.h"
18 
19 //#include "android-base/stringprintf.h"
20 #include "androidfw/ApkAssets.h"
21 #include "androidfw/AssetManager.h"
22 #include "androidfw/AssetManager2.h"
23 #include "androidfw/AttributeResolution.h"
24 #include "androidfw/ResourceTypes.h"
25 
26 #include "BenchmarkHelpers.h"
27 #include "data/basic/R.h"
28 #include "data/styles/R.h"
29 
30 namespace app = com::android::app;
31 namespace basic = com::android::basic;
32 
33 namespace android {
34 
35 constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
36 constexpr const static uint32_t Theme_Material_Light = 0x01030237u;
37 
BM_ApplyStyle(benchmark::State & state)38 static void BM_ApplyStyle(benchmark::State& state) {
39   std::unique_ptr<const ApkAssets> styles_apk =
40       ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
41   if (styles_apk == nullptr) {
42     state.SkipWithError("failed to load assets");
43     return;
44   }
45 
46   AssetManager2 assetmanager;
47   assetmanager.SetApkAssets({styles_apk.get()});
48 
49   std::unique_ptr<Asset> asset =
50       assetmanager.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
51   if (asset == nullptr) {
52     state.SkipWithError("failed to load layout");
53     return;
54   }
55 
56   ResXMLTree xml_tree;
57   if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
58     state.SkipWithError("corrupt xml layout");
59     return;
60   }
61 
62   // Skip to the first tag.
63   while (xml_tree.next() != ResXMLParser::START_TAG) {
64   }
65 
66   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
67   theme->ApplyStyle(app::R::style::StyleTwo);
68 
69   std::array<uint32_t, 6> attrs{{app::R::attr::attr_one, app::R::attr::attr_two,
70                                  app::R::attr::attr_three, app::R::attr::attr_four,
71                                  app::R::attr::attr_five, app::R::attr::attr_empty}};
72   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
73   std::array<uint32_t, attrs.size() + 1> indices;
74 
75   while (state.KeepRunning()) {
76     ApplyStyle(theme.get(), &xml_tree, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
77                attrs.size(), values.data(), indices.data());
78   }
79 }
80 BENCHMARK(BM_ApplyStyle);
81 
BM_ApplyStyleFramework(benchmark::State & state)82 static void BM_ApplyStyleFramework(benchmark::State& state) {
83   std::unique_ptr<const ApkAssets> framework_apk = ApkAssets::Load(kFrameworkPath);
84   if (framework_apk == nullptr) {
85     state.SkipWithError("failed to load framework assets");
86     return;
87   }
88 
89   std::unique_ptr<const ApkAssets> basic_apk =
90       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
91   if (basic_apk == nullptr) {
92     state.SkipWithError("failed to load assets");
93     return;
94   }
95 
96   AssetManager2 assetmanager;
97   assetmanager.SetApkAssets({framework_apk.get(), basic_apk.get()});
98 
99   ResTable_config device_config;
100   memset(&device_config, 0, sizeof(device_config));
101   device_config.language[0] = 'e';
102   device_config.language[1] = 'n';
103   device_config.country[0] = 'U';
104   device_config.country[1] = 'S';
105   device_config.orientation = ResTable_config::ORIENTATION_PORT;
106   device_config.smallestScreenWidthDp = 700;
107   device_config.screenWidthDp = 700;
108   device_config.screenHeightDp = 1024;
109   device_config.sdkVersion = 27;
110 
111   auto value = assetmanager.GetResource(basic::R::layout::layoutt);
112   if (!value.has_value()) {
113     state.SkipWithError("failed to find R.layout.layout");
114     return;
115   }
116 
117   auto layout_path = assetmanager.GetStringPoolForCookie(value->cookie)->string8At(value->data);
118   if (!layout_path.has_value()) {
119     state.SkipWithError("failed to lookup layout path");
120     return;
121   }
122 
123   std::unique_ptr<Asset> asset = assetmanager.OpenNonAsset(layout_path->to_string(), value->cookie,
124                                                            Asset::ACCESS_BUFFER);
125   if (asset == nullptr) {
126     state.SkipWithError("failed to load layout");
127     return;
128   }
129 
130   ResXMLTree xml_tree;
131   if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
132     state.SkipWithError("corrupt xml layout");
133     return;
134   }
135 
136   // Skip to the first tag.
137   while (xml_tree.next() != ResXMLParser::START_TAG) {
138   }
139 
140   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
141   theme->ApplyStyle(Theme_Material_Light);
142 
143   std::array<uint32_t, 92> attrs{
144       {0x0101000e, 0x01010034, 0x01010095, 0x01010096, 0x01010097, 0x01010098, 0x01010099,
145        0x0101009a, 0x0101009b, 0x010100ab, 0x010100af, 0x010100b0, 0x010100b1, 0x0101011f,
146        0x01010120, 0x0101013f, 0x01010140, 0x0101014e, 0x0101014f, 0x01010150, 0x01010151,
147        0x01010152, 0x01010153, 0x01010154, 0x01010155, 0x01010156, 0x01010157, 0x01010158,
148        0x01010159, 0x0101015a, 0x0101015b, 0x0101015c, 0x0101015d, 0x0101015e, 0x0101015f,
149        0x01010160, 0x01010161, 0x01010162, 0x01010163, 0x01010164, 0x01010165, 0x01010166,
150        0x01010167, 0x01010168, 0x01010169, 0x0101016a, 0x0101016b, 0x0101016c, 0x0101016d,
151        0x0101016e, 0x0101016f, 0x01010170, 0x01010171, 0x01010217, 0x01010218, 0x0101021d,
152        0x01010220, 0x01010223, 0x01010224, 0x01010264, 0x01010265, 0x01010266, 0x010102c5,
153        0x010102c6, 0x010102c7, 0x01010314, 0x01010315, 0x01010316, 0x0101035e, 0x0101035f,
154        0x01010362, 0x01010374, 0x0101038c, 0x01010392, 0x01010393, 0x010103ac, 0x0101045d,
155        0x010104b6, 0x010104b7, 0x010104d6, 0x010104d7, 0x010104dd, 0x010104de, 0x010104df,
156        0x01010535, 0x01010536, 0x01010537, 0x01010538, 0x01010546, 0x01010567, 0x011100c9,
157        0x011100ca}};
158 
159   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
160   std::array<uint32_t, attrs.size() + 1> indices;
161   while (state.KeepRunning()) {
162     ApplyStyle(theme.get(), &xml_tree, 0x01010084u /*def_style_attr*/, 0u /*def_style_res*/,
163                attrs.data(), attrs.size(), values.data(), indices.data());
164   }
165 }
166 BENCHMARK(BM_ApplyStyleFramework);
167 
168 }  // namespace android
169