From 52b8ffe97696df0f8f607a00327c01a387607aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Mon, 7 Oct 2019 19:03:02 +0200 Subject: [PATCH] Finish Regist JNI Bindings --- android/app/src/main/cpp/chiaki-jni.c | 96 ++++++++++++++++++- .../java/com/metallic/chiaki/lib/Chiaki.kt | 16 +++- .../metallic/chiaki/regist/RegistActivity.kt | 2 +- .../chiaki/regist/RegistExecuteActivity.kt | 21 ++++ .../chiaki/regist/RegistExecuteViewModel.kt | 85 ++++++++++++++++ lib/CMakeLists.txt | 2 +- lib/include/chiaki/regist.h | 4 +- lib/src/{sessionlog.c => log.c} | 0 lib/src/regist.c | 8 +- 9 files changed, 219 insertions(+), 15 deletions(-) create mode 100644 android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt rename lib/src/{sessionlog.c => log.c} (100%) diff --git a/android/app/src/main/cpp/chiaki-jni.c b/android/app/src/main/cpp/chiaki-jni.c index e7e4203..12dbff7 100644 --- a/android/app/src/main/cpp/chiaki-jni.c +++ b/android/app/src/main/cpp/chiaki-jni.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,40 @@ static JNIEnv *attach_thread_jni() return NULL; } +typedef struct android_chiaki_log_t +{ + jobject java_log; + jmethodID java_log_meth; + ChiakiLog log; +} AndroidChiakiLog; + +static void android_chiaki_log_cb(ChiakiLogLevel level, const char *msg, void *user) +{ + log_cb_android(level, msg, NULL); + + AndroidChiakiLog *log = user; + JNIEnv *env = attach_thread_jni(); + if(!env) + return; + E->CallVoidMethod(env, log->java_log, log->java_log_meth, (jint)level, jnistr_from_ascii(env, msg)); + (*global_vm)->DetachCurrentThread(global_vm); +} + +static void android_chiaki_log_init(AndroidChiakiLog *log, JNIEnv *env, jobject java_log) +{ + log->java_log = E->NewGlobalRef(env, java_log); + jclass log_class = E->GetObjectClass(env, log->java_log); + log->java_log_meth = E->GetMethodID(env, log_class, "log", "(ILjava/lang/String;)V"); + log->log.level_mask = (uint32_t)E->GetIntField(env, log->java_log, E->GetFieldID(env, log_class, "levelMask", "I")); + log->log.cb = android_chiaki_log_cb; + log->log.user = log; +} + +static void android_chiaki_log_fini(AndroidChiakiLog *log, JNIEnv *env) +{ + E->DeleteGlobalRef(env, log->java_log); +} + static void android_chiaki_event_cb(ChiakiEvent *event, void *user) { AndroidChiakiSession *session = user; @@ -571,17 +606,74 @@ JNIEXPORT void JNICALL JNI_FCN(discoveryServiceFree)(JNIEnv *env, jobject obj, j free(service); } +typedef struct android_chiaki_regist_t +{ + AndroidChiakiLog log; + jobject java_regist; + ChiakiRegist regist; +} AndroidChiakiRegist; + +static void android_chiaki_regist_cb(ChiakiRegistEvent *event, void *user) +{ + // TODO +} + JNIEXPORT void JNICALL JNI_FCN(registStart)(JNIEnv *env, jobject obj, jobject result, jobject regist_info_obj, jobject log_obj, jobject java_regist) { + jclass result_class = E->GetObjectClass(env, result); + ChiakiErrorCode err = CHIAKI_ERR_SUCCESS; + AndroidChiakiRegist *regist = CHIAKI_NEW(AndroidChiakiRegist); + if(!regist) + { + err = CHIAKI_ERR_MEMORY; + goto beach; + } + android_chiaki_log_init(®ist->log, env, log_obj); + + regist->java_regist = E->NewGlobalRef(env, java_regist); + + jclass regist_info_class = E->GetObjectClass(env, regist_info_obj); + jstring host_string = E->GetObjectField(env, regist_info_obj, E->GetFieldID(env, regist_info_class, "host", "Ljava/lang/String;")); + jboolean broadcast = E->GetBooleanField(env, regist_info_obj, E->GetFieldID(env, regist_info_class, "broadcast", "Z")); + jstring psn_id_string = E->GetObjectField(env, regist_info_obj, E->GetFieldID(env, regist_info_class, "psnId", "Ljava/lang/String;")); + jint pin = E->GetIntField(env, regist_info_obj, E->GetFieldID(env, regist_info_class, "pin", "I")); + + ChiakiRegistInfo regist_info; + regist_info.host = E->GetStringUTFChars(env, host_string, NULL); + regist_info.broadcast = broadcast; + regist_info.psn_id = E->GetStringUTFChars(env, psn_id_string, NULL); + regist_info.pin = (uint32_t)pin; + + err = chiaki_regist_start(®ist->regist, ®ist->log.log, ®ist_info, android_chiaki_regist_cb, regist); + + E->ReleaseStringUTFChars(env, host_string, regist_info.host); + E->ReleaseStringUTFChars(env, psn_id_string, regist_info.psn_id); + + if(err != CHIAKI_ERR_SUCCESS) + { + android_chiaki_log_fini(®ist->log, env); + E->DeleteGlobalRef(env, regist->java_regist); + free(regist); + regist = NULL; + } + +beach: + E->SetIntField(env, result, E->GetFieldID(env, result_class, "errorCode", "I"), (jint)err); + E->SetLongField(env, result, E->GetFieldID(env, result_class, "ptr", "J"), (jlong)regist); } JNIEXPORT void JNICALL JNI_FCN(registStop)(JNIEnv *env, jobject obj, jlong ptr) { - + AndroidChiakiRegist *regist = (AndroidChiakiRegist *)ptr; + chiaki_regist_stop(®ist->regist); } JNIEXPORT void JNICALL JNI_FCN(registFree)(JNIEnv *env, jobject obj, jlong ptr) { - + AndroidChiakiRegist *regist = (AndroidChiakiRegist *)ptr; + chiaki_regist_fini(®ist->regist); + android_chiaki_log_fini(®ist->log, env); + E->DeleteGlobalRef(env, regist->java_regist); + free(regist); } diff --git a/android/app/src/main/java/com/metallic/chiaki/lib/Chiaki.kt b/android/app/src/main/java/com/metallic/chiaki/lib/Chiaki.kt index 85dadfd..5dbbac7 100644 --- a/android/app/src/main/java/com/metallic/chiaki/lib/Chiaki.kt +++ b/android/app/src/main/java/com/metallic/chiaki/lib/Chiaki.kt @@ -46,7 +46,7 @@ private class ChiakiNative @JvmStatic external fun sessionSetLoginPin(ptr: Long, pin: String) @JvmStatic external fun discoveryServiceCreate(result: CreateResult, options: DiscoveryServiceOptions, javaService: DiscoveryService) @JvmStatic external fun discoveryServiceFree(ptr: Long) - @JvmStatic external fun registStart(result: CreateResult, registInfo: RegistInfo, javaLog: Log, javaRegist: Regist) + @JvmStatic external fun registStart(result: CreateResult, registInfo: RegistInfo, javaLog: ChiakiLog, javaRegist: Regist) @JvmStatic external fun registStop(ptr: Long) @JvmStatic external fun registFree(ptr: Long) } @@ -58,7 +58,7 @@ class ErrorCode(val value: Int) var isSuccess = value == 0 } -class Log(val levelMask: Int) +class ChiakiLog(val levelMask: Int) { enum class Level(val value: Int) { @@ -66,7 +66,8 @@ class Log(val levelMask: Int) VERBOSE(1 shl 3), INFO(1 shl 2), WARNING(1 shl 1), - ERROR(1 shl 0) + ERROR(1 shl 0), + ALL(0.inv()) } private fun log(level: Int, text: String) @@ -286,11 +287,11 @@ data class RegistHost( sealed class RegistEvent object RegistEventCanceled: RegistEvent() object RegistEventFailed: RegistEvent() -class RegistEventSuccess(val host: RegistHost) +class RegistEventSuccess(val host: RegistHost): RegistEvent() class Regist( info: RegistInfo, - log: Log, + log: ChiakiLog, val callback: (RegistEvent) -> Unit ) { @@ -318,4 +319,9 @@ class Regist( ChiakiNative.registFree(nativePtr) nativePtr = 0L } + + private fun event(event: RegistEvent) + { + callback(event) + } } diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt index ef30146..e9ed90a 100644 --- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt +++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt @@ -73,7 +73,7 @@ class RegistActivity: AppCompatActivity(), RevealActivity it.putExtra(RegistExecuteActivity.EXTRA_HOST, host) it.putExtra(RegistExecuteActivity.EXTRA_BROADCAST, broadcast) it.putExtra(RegistExecuteActivity.EXTRA_PSN_ID, psnId) - it.putExtra(RegistExecuteActivity.EXTRA_PIN, pin) + it.putExtra(RegistExecuteActivity.EXTRA_PIN, pin.toUInt().toInt()) startActivity(it) } } diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt index f1b2238..058e973 100644 --- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt +++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt @@ -19,7 +19,9 @@ package com.metallic.chiaki.regist import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProviders import com.metallic.chiaki.R +import com.metallic.chiaki.lib.RegistInfo class RegistExecuteActivity: AppCompatActivity() { @@ -31,9 +33,28 @@ class RegistExecuteActivity: AppCompatActivity() const val EXTRA_PIN = "regist_pin" } + private lateinit var viewModel: RegistExecuteViewModel + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_regist_execute) + + viewModel = ViewModelProviders.of(this).get(RegistExecuteViewModel::class.java) + + val registInfo = RegistInfo( + intent.getStringExtra(EXTRA_HOST) ?: return, + intent.getBooleanExtra(EXTRA_BROADCAST, false) ?: return, + intent.getStringExtra(EXTRA_PSN_ID) ?: return, + intent.getIntExtra(EXTRA_PIN, 0).toUInt() + ) + + viewModel.start(registInfo) + } + + override fun onStop() + { + super.onStop() + viewModel.stop() } } \ No newline at end of file diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt new file mode 100644 index 0000000..1a536ff --- /dev/null +++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt @@ -0,0 +1,85 @@ +/* + * This file is part of Chiaki. + * + * Chiaki is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Chiaki is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chiaki. If not, see . + */ + +package com.metallic.chiaki.regist + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.metallic.chiaki.lib.* + +class RegistExecuteViewModel: ViewModel() +{ + enum class State + { + IDLE, + RUNNING, + STOPPED, + FAILED, + SUCCESSFUL + } + + private val _state = MutableLiveData(State.IDLE) + val state: LiveData get() = _state + + private val log = ChiakiLog(ChiakiLog.Level.ALL.value/* and ChiakiLog.Level.VERBOSE.value.inv()*/) + private var regist: Regist? = null + + fun start(info: RegistInfo) + { + if(regist != null) + return + try + { + regist = Regist(info, log, this::registEvent) + _state.value = State.RUNNING + } + catch(error: CreateError) + { + // TODO: log about error + _state.value = State.FAILED + } + } + + fun stop() + { + regist?.stop() + } + + private fun registEvent(event: RegistEvent) + { + when(event) + { + is RegistEventCanceled -> { + _state.postValue(State.STOPPED) + } + is RegistEventFailed -> { + _state.postValue(State.FAILED) + } + is RegistEventSuccess -> { + // TODO: save event.host into db + _state.postValue(State.SUCCESSFUL) + } + } + } + + override fun onCleared() + { + super.onCleared() + regist?.dispose() + } +} \ No newline at end of file diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index b7930eb..663ba69 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -41,7 +41,7 @@ set(SOURCE_FILES src/thread.c src/base64.c src/http.c - src/sessionlog.c + src/log.c src/ctrl.c src/rpcrypt.c src/takion.c diff --git a/lib/include/chiaki/regist.h b/lib/include/chiaki/regist.h index 451ac13..1c8fb72 100644 --- a/lib/include/chiaki/regist.h +++ b/lib/include/chiaki/regist.h @@ -31,9 +31,9 @@ extern "C" { typedef struct chiaki_regist_info_t { - char *host; + const char *host; bool broadcast; - char *psn_id; + const char *psn_id; uint32_t pin; } ChiakiRegistInfo; diff --git a/lib/src/sessionlog.c b/lib/src/log.c similarity index 100% rename from lib/src/sessionlog.c rename to lib/src/log.c diff --git a/lib/src/regist.c b/lib/src/regist.c index dab7bfa..56be300 100644 --- a/lib/src/regist.c +++ b/lib/src/regist.c @@ -75,9 +75,9 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLo error_stop_pipe: chiaki_stop_pipe_fini(®ist->stop_pipe); error_psn_id: - free(regist->info.psn_id); + free((char *)regist->info.psn_id); error_host: - free(regist->info.host); + free((char *)regist->info.host); return err; } @@ -85,8 +85,8 @@ CHIAKI_EXPORT void chiaki_regist_fini(ChiakiRegist *regist) { chiaki_thread_join(®ist->thread, NULL); chiaki_stop_pipe_fini(®ist->stop_pipe); - free(regist->info.psn_id); - free(regist->info.host); + free((char *)regist->info.psn_id); + free((char *)regist->info.host); } CHIAKI_EXPORT void chiaki_regist_stop(ChiakiRegist *regist)