Added separate launcher for android
This commit is contained in:
+2
-2
@@ -138,14 +138,14 @@ void setupCompilationFlags() {
|
||||
"android_arm32":
|
||||
["-target", getTargetArg("android_arm32"),
|
||||
"--sysroot=$android_arm32SysrootDir",
|
||||
"-D__ANDROID__", "-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=32",
|
||||
"-D__ANDROID__", "-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=32", "-DANDROID",
|
||||
// HACKS!
|
||||
"-I$android_arm32SysrootDir/usr/include/c++/4.9.x",
|
||||
"-I$android_arm32SysrootDir/usr/include/c++/4.9.x/arm-linux-androideabi"],
|
||||
"android_arm64":
|
||||
["-target", getTargetArg("android_arm64"),
|
||||
"--sysroot=$android_arm64SysrootDir",
|
||||
"-D__ANDROID__", "-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=64",
|
||||
"-D__ANDROID__", "-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=64", "-DANDROID",
|
||||
// HACKS!
|
||||
"-I$android_arm64SysrootDir/usr/include/c++/4.9.x",
|
||||
"-I$android_arm64SysrootDir/usr/include/c++/4.9.x/aarch64-linux-android"]
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Memory.h"
|
||||
#include "Natives.h"
|
||||
#include "Runtime.h"
|
||||
#include "KString.h"
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "androidLauncher.h"
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Konan_main", __VA_ARGS__))
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "Konan_main", __VA_ARGS__))
|
||||
|
||||
/* For debug builds, always enable the debug traces in this library */
|
||||
#ifndef NDEBUG
|
||||
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "Konan_main", __VA_ARGS__))
|
||||
#else
|
||||
# define LOGV(...) ((void)0)
|
||||
#endif
|
||||
|
||||
//--- main --------------------------------------------------------------------//
|
||||
extern "C" KInt Konan_start(const ObjHeader*);
|
||||
|
||||
static int pipeC, pipeKonan;
|
||||
|
||||
static NativeActivityState nativeActivityState;
|
||||
|
||||
extern "C" void getNativeActivityState(NativeActivityState* state) {
|
||||
state->activity = nativeActivityState.activity;
|
||||
state->savedState = nativeActivityState.savedState;
|
||||
state->savedStateSize = nativeActivityState.savedStateSize;
|
||||
state->looper = nativeActivityState.looper;
|
||||
}
|
||||
|
||||
extern "C" void notifySysEventProcessed(int fd) {
|
||||
if (fd != pipeKonan) return;
|
||||
int8_t message;
|
||||
write(pipeKonan, &message, sizeof(message));
|
||||
}
|
||||
|
||||
static void* entry(void* param) {
|
||||
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||
ALooper_addFd(looper, pipeKonan, LOOPER_ID_SYS, ALOOPER_EVENT_INPUT, NULL, NULL);
|
||||
nativeActivityState.looper = looper;
|
||||
|
||||
RuntimeState* state = InitRuntime();
|
||||
|
||||
if (state == nullptr) {
|
||||
LOGE("Unable to init runtime\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
KInt exitStatus;
|
||||
{
|
||||
ObjHolder args;
|
||||
AllocArrayInstance(theArrayTypeInfo, 0, args.slot());
|
||||
exitStatus = Konan_start(args.obj());
|
||||
}
|
||||
|
||||
DeinitRuntime(state);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void runKonan_start() {
|
||||
int pipes[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipes)) {
|
||||
LOGE("Could not create pipe: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
pipeC = pipes[0];
|
||||
pipeKonan = pipes[1];
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, &attr, entry, nullptr);
|
||||
}
|
||||
|
||||
static void putEventSynchronously(void* event) {
|
||||
uint64_t value = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(event));
|
||||
if (write(pipeC, &value, sizeof(value)) != sizeof(value)) {
|
||||
LOGE("Failure writing event: %s\n", strerror(errno));
|
||||
}
|
||||
int8_t response;
|
||||
if (read(pipeC, &response, sizeof(response)) != sizeof(response)) {
|
||||
LOGE("Failure reading response: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void onDestroy(ANativeActivity* activity) {
|
||||
LOGV("onDestroy called");
|
||||
NativeActivityEvent event = { DESTROY };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onStart(ANativeActivity* activity) {
|
||||
LOGV("onStart called");
|
||||
NativeActivityEvent event = { START };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onResume(ANativeActivity* activity) {
|
||||
LOGV("onResume called");
|
||||
NativeActivitySaveStateEvent event = { RESUME };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
|
||||
LOGV("onSaveInstanceState called");
|
||||
NativeActivitySaveStateEvent event = { SAVE_INSTANCE_STATE };
|
||||
putEventSynchronously(&event);
|
||||
*outLen = event.savedStateSize;
|
||||
return event.savedState;
|
||||
}
|
||||
|
||||
static void onPause(ANativeActivity* activity) {
|
||||
LOGV("onPause called");
|
||||
NativeActivityEvent event = { PAUSE };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onStop(ANativeActivity* activity) {
|
||||
LOGV("onStop called");
|
||||
NativeActivityEvent event = { STOP };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onConfigurationChanged(ANativeActivity* activity) {
|
||||
LOGV("onConfigurationChanged called");
|
||||
NativeActivityEvent event = { CONFIGURATION_CHANGED };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onLowMemory(ANativeActivity* activity) {
|
||||
LOGV("onLowMemory called");
|
||||
NativeActivityEvent event = { LOW_MEMORY };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
|
||||
LOGV("onWindowFocusChanged called");
|
||||
NativeActivityEvent event = { focused ? WINDOW_GAINED_FOCUS : WINDOW_LOST_FOCUS };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGV("onNativeWindowCreated called");
|
||||
NativeActivityWindowEvent event = { NATIVE_WINDOW_CREATED, window };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGV("onNativeWindowDestroyed called");
|
||||
NativeActivityWindowEvent event = { NATIVE_WINDOW_DESTROYED, window };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
|
||||
LOGV("onInputQueueCreated called");
|
||||
NativeActivityQueueEvent event = { INPUT_QUEUE_CREATED, queue };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
|
||||
LOGV("onInputQueueDestroyed called");
|
||||
NativeActivityQueueEvent event = { INPUT_QUEUE_DESTROYED, queue };
|
||||
putEventSynchronously(&event);
|
||||
}
|
||||
|
||||
// ANativeActivity_onCreate.
|
||||
extern "C" void Konan_main(ANativeActivity* activity, void* savedState, size_t savedStateSize) {
|
||||
nativeActivityState = {activity, savedState, savedStateSize};
|
||||
|
||||
activity->callbacks->onDestroy = onDestroy;
|
||||
activity->callbacks->onStart = onStart;
|
||||
activity->callbacks->onResume = onResume;
|
||||
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
|
||||
activity->callbacks->onPause = onPause;
|
||||
activity->callbacks->onStop = onStop;
|
||||
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
|
||||
activity->callbacks->onLowMemory = onLowMemory;
|
||||
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
|
||||
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
|
||||
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
|
||||
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
|
||||
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
|
||||
|
||||
runKonan_start();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_LAUNCHER_H
|
||||
#define ANDROID_LAUNCHER_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <android/configuration.h>
|
||||
#include <android/looper.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct NativeActivityState {
|
||||
struct ANativeActivity* activity;
|
||||
void* savedState;
|
||||
size_t savedStateSize;
|
||||
struct ALooper* looper;
|
||||
};
|
||||
|
||||
void getNativeActivityState(struct NativeActivityState* state);
|
||||
|
||||
void notifySysEventProcessed(int fd);
|
||||
|
||||
#define LOOPER_ID_SYS 1
|
||||
|
||||
typedef enum NativeActivityEventKind {
|
||||
UNKNOWN,
|
||||
DESTROY,
|
||||
START,
|
||||
RESUME,
|
||||
SAVE_INSTANCE_STATE,
|
||||
PAUSE,
|
||||
STOP,
|
||||
CONFIGURATION_CHANGED,
|
||||
LOW_MEMORY,
|
||||
WINDOW_GAINED_FOCUS,
|
||||
WINDOW_LOST_FOCUS,
|
||||
NATIVE_WINDOW_CREATED,
|
||||
NATIVE_WINDOW_DESTROYED,
|
||||
INPUT_QUEUE_CREATED,
|
||||
INPUT_QUEUE_DESTROYED
|
||||
} NativeActivityEventKind;
|
||||
|
||||
struct NativeActivityEvent {
|
||||
NativeActivityEventKind eventKind;
|
||||
};
|
||||
|
||||
struct NativeActivitySaveStateEvent {
|
||||
NativeActivityEventKind eventKind;
|
||||
void* savedState;
|
||||
size_t savedStateSize;
|
||||
};
|
||||
|
||||
struct NativeActivityWindowEvent {
|
||||
NativeActivityEventKind eventKind;
|
||||
struct ANativeWindow* window;
|
||||
};
|
||||
|
||||
struct NativeActivityQueueEvent {
|
||||
NativeActivityEventKind eventKind;
|
||||
struct AInputQueue* queue;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ANDROID_LAUNCHER_H
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "KString.h"
|
||||
#include "Types.h"
|
||||
|
||||
#ifndef ANDROID
|
||||
|
||||
//--- Setup args --------------------------------------------------------------//
|
||||
|
||||
OBJ_GETTER(setupArgs, int argc, const char** argv) {
|
||||
@@ -54,3 +56,5 @@ extern "C" int Konan_main(int argc, const char** argv) {
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
OBJ_GETTER(utf8ToUtf16, const char* rawString, size_t rawStringLength) {
|
||||
@@ -1129,7 +1133,11 @@ void Kotlin_io_Console_print(KString message) {
|
||||
const KChar* utf16 = CharArrayAddressOfElementAt(message, 0);
|
||||
std::string utf8;
|
||||
utf8::utf16to8(utf16, utf16 + message->count_, back_inserter(utf8));
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, "Konan_main", "%s", utf8.c_str());
|
||||
#else
|
||||
write(STDOUT_FILENO, utf8.c_str(), utf8.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Kotlin_io_Console_println(KString message) {
|
||||
@@ -1138,7 +1146,11 @@ void Kotlin_io_Console_println(KString message) {
|
||||
}
|
||||
|
||||
void Kotlin_io_Console_println0() {
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, "Konan_main", "\n");
|
||||
#else
|
||||
write(STDOUT_FILENO, "\n", 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
OBJ_GETTER0(Kotlin_io_Console_readLine) {
|
||||
|
||||
Reference in New Issue
Block a user