Updated demos to use DALi clang-format
[platform/core/uifw/dali-demo.git] / build / android / app / src / main / cpp / main.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
18 // EXTERNAL INCLUDES
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include <android/log.h>
24 #include <android_native_app_glue.h>
25 #include <dali-demo-native-activity-jni.h>
26 #include <dali/devel-api/adaptor-framework/application-devel.h>
27 #include <dali/integration-api/adaptor-framework/android/android-framework.h>
28 #include <dali/integration-api/debug.h>
29 #include <dlfcn.h>
30
31 // from android_native_app_glue.c
32 #ifndef NDEBUG
33 #define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "dalidemo", __VA_ARGS__))
34 #else
35 #define LOGV(...) ((void)0)
36 #endif
37
38 namespace
39 {
40 void free_saved_state(struct android_app* android_app)
41 {
42   LOGV("free_saved_state");
43   pthread_mutex_lock(&android_app->mutex);
44
45   if(android_app->savedState != NULL)
46   {
47     free(android_app->savedState);
48     android_app->savedState     = NULL;
49     android_app->savedStateSize = 0;
50   }
51
52   pthread_mutex_unlock(&android_app->mutex);
53 }
54
55 void android_app_destroy(struct android_app* android_app)
56 {
57   LOGV("android_app_destroy");
58   free_saved_state(android_app);
59   pthread_mutex_lock(&android_app->mutex);
60
61   if(android_app->inputQueue != NULL)
62   {
63     AInputQueue_detachLooper(android_app->inputQueue);
64   }
65
66   AConfiguration_delete(android_app->config);
67   android_app->destroyed = 1;
68
69   pthread_cond_broadcast(&android_app->cond);
70   pthread_mutex_unlock(&android_app->mutex);
71
72   // Can't touch android_app object after this.
73 }
74
75 } // namespace
76
77 void ExtractAsset(struct android_app* state, const std::string& assetPath, const std::string& filePath)
78 {
79   AAsset* asset = AAssetManager_open(state->activity->assetManager, assetPath.c_str(), AASSET_MODE_BUFFER);
80   if(asset)
81   {
82     size_t length = AAsset_getLength(asset) + 1;
83
84     char* buffer = new char[length];
85     length       = AAsset_read(asset, buffer, length);
86
87     FILE* file = fopen(filePath.c_str(), "wb");
88     if(file)
89     {
90       fwrite(buffer, 1, length, file);
91       fclose(file);
92     }
93
94     delete[] buffer;
95     AAsset_close(asset);
96   }
97 }
98
99 void ExtractAssets(struct android_app* state, const std::string& assetDirPath, const std::string& filesDirPath)
100 {
101   AAssetDir* assetDir = AAssetManager_openDir(state->activity->assetManager, assetDirPath.c_str());
102   if(assetDir)
103   {
104     if(mkdir(filesDirPath.c_str(), S_IRWXU) != -1)
105     {
106       const char* filename  = NULL;
107       std::string assetPath = assetDirPath + "/";
108       while((filename = AAssetDir_getNextFileName(assetDir)) != NULL)
109       {
110         ExtractAsset(state, assetPath + filename, filesDirPath + "/" + filename);
111       }
112     }
113
114     AAssetDir_close(assetDir);
115   }
116 }
117
118 void ExtractFontConfig(struct android_app* state, std::string assetFontConfig, std::string fontsPath)
119 {
120   AAsset* asset = AAssetManager_open(state->activity->assetManager, assetFontConfig.c_str(), AASSET_MODE_BUFFER);
121   if(asset)
122   {
123     size_t length = AAsset_getLength(asset) + 1;
124
125     char* buffer = new char[length];
126     length       = AAsset_read(asset, buffer, length);
127
128     std::string fontConfig = std::string(buffer, length);
129     int         i          = fontConfig.find("~");
130     if(i != std::string::npos)
131     {
132       std::string filesDir = state->activity->internalDataPath;
133       fontConfig.replace(i, 1, filesDir);
134     }
135
136     std::string fontsFontConfig = fontsPath;
137     FILE*       file            = fopen(fontsFontConfig.c_str(), "wb");
138     if(file)
139     {
140       fwrite(fontConfig.c_str(), 1, fontConfig.size(), file);
141       fclose(file);
142     }
143
144     delete[] buffer;
145     AAsset_close(asset);
146   }
147 }
148
149 extern "C" void FcConfigPathInit(const char* path, const char* file);
150
151 void android_main(struct android_app* state)
152 {
153   LOGV("android_main() >>");
154
155   std::string filesDir = state->activity->internalDataPath;
156
157   std::string fontconfigPath = filesDir + "/fonts";
158   setenv("FONTCONFIG_PATH", fontconfigPath.c_str(), 1);
159
160   std::string fontconfigFile = fontconfigPath + "/fonts.conf";
161   setenv("FONTCONFIG_FILE", fontconfigFile.c_str(), 1);
162
163   struct stat st = {0};
164   FcConfigPathInit(fontconfigPath.c_str(), fontconfigFile.c_str());
165
166   if(stat(fontconfigPath.c_str(), &st) == -1)
167   {
168     mkdir(fontconfigPath.c_str(), S_IRWXU);
169     ExtractFontConfig(state, "fonts/fonts.conf", fontconfigPath + "/fonts.conf");
170     ExtractFontConfig(state, "fonts/fonts.dtd", fontconfigPath + "/fonts.dtd");
171     ExtractFontConfig(state, "fonts/local.conf", fontconfigPath + "/local.conf");
172     ExtractAssets(state, "fonts/dejavu", fontconfigPath + "/dejavu");
173     ExtractAssets(state, "fonts/tizen", fontconfigPath + "/tizen");
174     ExtractAssets(state, "fonts/bitmap", fontconfigPath + "/bitmap");
175   }
176
177   Dali::Integration::AndroidFramework::New();
178   Dali::Integration::AndroidFramework::Get().SetNativeApplication(state);
179   Dali::Integration::AndroidFramework::Get().SetApplicationConfiguration(state->config);
180   Dali::Integration::AndroidFramework::Get().SetApplicationAssets(state->activity->assetManager);
181   Dali::Integration::AndroidFramework::Get().SetInternalDataPath(filesDir);
182
183   DaliDemoNativeActivity nativeActivity(state->activity);
184
185   int         status    = 0;
186   std::string libpath   = "/data/data/com.sec.dalidemo/lib/libdali-demo.so";
187   std::string callParam = nativeActivity.GetIntentStringExtra("start");
188   if(callParam.empty())
189   {
190     callParam = nativeActivity.GetMetaData("start");
191   }
192
193   if(!callParam.empty())
194   {
195     libpath = "/data/data/com.sec.dalidemo/lib/lib" + callParam + ".so";
196   }
197
198   void* handle = dlopen(libpath.c_str(), RTLD_LAZY);
199   if(!handle)
200   {
201     std::exit(status);
202   }
203
204   dlerror(); /* Clear any existing error */
205
206   int (*main)(int, char**) = (int (*)(int, char**))dlsym(handle, "main");
207   if(main)
208   {
209     status = main(0, nullptr);
210   }
211
212   if(handle)
213   {
214     dlclose(handle);
215     handle = nullptr;
216   }
217
218   android_app_destroy(state);
219
220   Dali::Integration::AndroidFramework::Get().SetNativeApplication(nullptr);
221   Dali::Integration::AndroidFramework::Get().SetApplicationConfiguration(nullptr);
222   Dali::Integration::AndroidFramework::Get().SetApplicationAssets(nullptr);
223   Dali::Integration::AndroidFramework::Delete();
224
225   LOGV("android_main() <<");
226
227   // We need to kill the application process manually, DALi cannot exit the process properly due to memory leaks
228   std::exit(status);
229 }
230
231 //END_INCLUDE(all)