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