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
30namespace app = com::android::app;
31namespace basic = com::android::basic;
32
33namespace android {
34
35constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
36constexpr const static uint32_t Theme_Material_Light = 0x01030237u;
37
38static 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}
80BENCHMARK(BM_ApplyStyle);
81
82static 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}
173BENCHMARK(BM_ApplyStyleFramework);
174
175}  // namespace android
176