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   Res_value value;
112   ResTable_config config;
113   uint32_t flags = 0u;
114   ApkAssetsCookie cookie =
115       assetmanager.GetResource(basic::R::layout::layoutt, false /*may_be_bag*/,
116                                0u /*density_override*/, &value, &config, &flags);
117   if (cookie == kInvalidCookie) {
118     state.SkipWithError("failed to find R.layout.layout");
119     return;
120   }
121 
122   size_t len = 0u;
123   const char* layout_path =
124       assetmanager.GetStringPoolForCookie(cookie)->string8At(value.data, &len);
125   if (layout_path == nullptr || len == 0u) {
126     state.SkipWithError("failed to lookup layout path");
127     return;
128   }
129 
130   std::unique_ptr<Asset> asset = assetmanager.OpenNonAsset(
131       StringPiece(layout_path, len).to_string(), cookie, Asset::ACCESS_BUFFER);
132   if (asset == nullptr) {
133     state.SkipWithError("failed to load layout");
134     return;
135   }
136 
137   ResXMLTree xml_tree;
138   if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
139     state.SkipWithError("corrupt xml layout");
140     return;
141   }
142 
143   // Skip to the first tag.
144   while (xml_tree.next() != ResXMLParser::START_TAG) {
145   }
146 
147   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
148   theme->ApplyStyle(Theme_Material_Light);
149 
150   std::array<uint32_t, 92> attrs{
151       {0x0101000e, 0x01010034, 0x01010095, 0x01010096, 0x01010097, 0x01010098, 0x01010099,
152        0x0101009a, 0x0101009b, 0x010100ab, 0x010100af, 0x010100b0, 0x010100b1, 0x0101011f,
153        0x01010120, 0x0101013f, 0x01010140, 0x0101014e, 0x0101014f, 0x01010150, 0x01010151,
154        0x01010152, 0x01010153, 0x01010154, 0x01010155, 0x01010156, 0x01010157, 0x01010158,
155        0x01010159, 0x0101015a, 0x0101015b, 0x0101015c, 0x0101015d, 0x0101015e, 0x0101015f,
156        0x01010160, 0x01010161, 0x01010162, 0x01010163, 0x01010164, 0x01010165, 0x01010166,
157        0x01010167, 0x01010168, 0x01010169, 0x0101016a, 0x0101016b, 0x0101016c, 0x0101016d,
158        0x0101016e, 0x0101016f, 0x01010170, 0x01010171, 0x01010217, 0x01010218, 0x0101021d,
159        0x01010220, 0x01010223, 0x01010224, 0x01010264, 0x01010265, 0x01010266, 0x010102c5,
160        0x010102c6, 0x010102c7, 0x01010314, 0x01010315, 0x01010316, 0x0101035e, 0x0101035f,
161        0x01010362, 0x01010374, 0x0101038c, 0x01010392, 0x01010393, 0x010103ac, 0x0101045d,
162        0x010104b6, 0x010104b7, 0x010104d6, 0x010104d7, 0x010104dd, 0x010104de, 0x010104df,
163        0x01010535, 0x01010536, 0x01010537, 0x01010538, 0x01010546, 0x01010567, 0x011100c9,
164        0x011100ca}};
165 
166   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
167   std::array<uint32_t, attrs.size() + 1> indices;
168   while (state.KeepRunning()) {
169     ApplyStyle(theme.get(), &xml_tree, 0x01010084u /*def_style_attr*/, 0u /*def_style_res*/,
170                attrs.data(), attrs.size(), values.data(), indices.data());
171   }
172 }
173 BENCHMARK(BM_ApplyStyleFramework);
174 
175 }  // namespace android
176