1 // Copyright 2019 The Amber Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <android/log.h>
16 #include <android_native_app_glue.h>
17 
18 #include "amber/amber.h"
19 #include "amber/recipe.h"
20 #include "amber/result.h"
21 #include "amber_script.h"
22 
23 namespace {
24 
25 // TODO(jaebaek): Change this as a method rather than macro.
26 // Android log function wrappers
27 const char* kTAG = "Amber";
28 #define LOGE(...) \
29   ((void)__android_log_print(ANDROID_LOG_ERROR, kTAG, __VA_ARGS__))
30 
amber_sample_main(android_app * app)31 void amber_sample_main(android_app* app) {
32   amber::android::AmberScriptLoader loader(app);
33 
34   amber::Result r = loader.LoadAllScriptsFromAsset();
35   if (!r.IsSuccess()) {
36     LOGE("%s", r.Error().c_str());
37     return;
38   }
39 
40   const auto& script_info = loader.GetScripts();
41 
42   std::vector<std::string> failures;
43   for (const auto& info : script_info) {
44     LOGE("\ncase %s: run...", info.asset_name.c_str());
45 
46     amber::Amber am;
47     amber::Recipe recipe;
48     amber::Result r = am.Parse(info.script_content, &recipe);
49     if (!r.IsSuccess()) {
50       LOGE("\ncase %s: fail\n\t%s", info.asset_name.c_str(), r.Error().c_str());
51       failures.push_back(info.asset_name);
52       continue;
53     }
54 
55     amber::Options amber_options;
56     r = am.ExecuteWithShaderData(&recipe, amber_options, info.shader_map);
57     if (!r.IsSuccess()) {
58       LOGE("\ncase %s: fail\n\t%s", info.asset_name.c_str(), r.Error().c_str());
59       failures.push_back(info.asset_name);
60       continue;
61     }
62 
63     LOGE("\ncase %s: pass", info.asset_name.c_str());
64   }
65 
66   if (!failures.empty()) {
67     LOGE("\nSummary of Failures:");
68     for (const auto& failure : failures)
69       LOGE("%s", failure.c_str());
70   }
71   LOGE("\nsummary: %u pass, %u fail",
72        static_cast<uint32_t>(script_info.size() - failures.size()),
73        static_cast<uint32_t>(failures.size()));
74 }
75 
76 // Process the next main command.
handle_cmd(android_app * app,int32_t cmd)77 void handle_cmd(android_app* app, int32_t cmd) {
78   switch (cmd) {
79     case APP_CMD_INIT_WINDOW:
80       amber_sample_main(app);
81       break;
82     case APP_CMD_TERM_WINDOW:
83       break;
84     default:
85       break;
86   }
87 }
88 
89 }  // namespace
90 
android_main(struct android_app * app)91 void android_main(struct android_app* app) {
92   // Set the callback to process system events
93   app->onAppCmd = handle_cmd;
94 
95   // Used to poll the events in the main loop
96   int events;
97   android_poll_source* source;
98 
99   // Main loop
100   while (app->destroyRequested == 0) {
101     if (ALooper_pollAll(1, nullptr, &events, (void**)&source) >= 0) {
102       if (source != NULL)
103         source->process(app, source);
104     }
105   }
106 }
107