1 /*
2  * Copyright (c) 2021, 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 "ScriptExecutorListener.h"
18 
19 #include "JniUtils.h"
20 #include "nativehelper/scoped_local_ref.h"
21 
22 #include <android-base/logging.h>
23 
24 namespace com {
25 namespace android {
26 namespace car {
27 namespace scriptexecutor {
28 
~ScriptExecutorListener()29 ScriptExecutorListener::~ScriptExecutorListener() {
30     JNIEnv* env = getCurrentJNIEnv();
31     if (mScriptExecutorListener != nullptr) {
32         env->DeleteGlobalRef(mScriptExecutorListener);
33     }
34 }
35 
ScriptExecutorListener(JNIEnv * env,jobject scriptExecutorListener)36 ScriptExecutorListener::ScriptExecutorListener(JNIEnv* env, jobject scriptExecutorListener) {
37     mScriptExecutorListener = env->NewGlobalRef(scriptExecutorListener);
38     env->GetJavaVM(&mJavaVM);
39 }
40 
onSuccess(jobject bundle)41 void ScriptExecutorListener::onSuccess(jobject bundle) {
42     JNIEnv* env = getCurrentJNIEnv();
43     ScopedLocalRef<jclass> listenerClassRef(env, env->GetObjectClass(mScriptExecutorListener));
44     jmethodID onSuccessMethod = env->GetMethodID(listenerClassRef.get(), "onSuccess",
45                                                  "(Landroid/os/PersistableBundle;)V");
46     env->CallVoidMethod(mScriptExecutorListener, onSuccessMethod, bundle);
47 }
48 
onScriptFinished(jobject bundle)49 void ScriptExecutorListener::onScriptFinished(jobject bundle) {
50     JNIEnv* env = getCurrentJNIEnv();
51     ScopedLocalRef<jclass> listenerClassRef(env, env->GetObjectClass(mScriptExecutorListener));
52     jmethodID onScriptFinished = env->GetMethodID(listenerClassRef.get(), "onScriptFinished",
53                                                   "(Landroid/os/PersistableBundle;)V");
54     env->CallVoidMethod(mScriptExecutorListener, onScriptFinished, bundle);
55 }
56 
onError(const ErrorType errorType,const char * message,const char * stackTrace)57 void ScriptExecutorListener::onError(const ErrorType errorType, const char* message,
58                                      const char* stackTrace) {
59     JNIEnv* env = getCurrentJNIEnv();
60     ScopedLocalRef<jclass> listenerClassRef(env, env->GetObjectClass(mScriptExecutorListener));
61     jmethodID onErrorMethod = env->GetMethodID(listenerClassRef.get(), "onError",
62                                                "(ILjava/lang/String;Ljava/lang/String;)V");
63 
64     ScopedLocalRef<jstring> messageStringRef(env, env->NewStringUTF(message));
65     if (messageStringRef == nullptr) {
66         LOG(ERROR) << "Failed to create a Java string for provided error message due to OOM error";
67         return;
68     }
69 
70     ScopedLocalRef<jstring> stackTraceRef(env, env->NewStringUTF(stackTrace));
71     if (stackTraceRef == nullptr) {
72         LOG(ERROR) << "Failed to create a Java string for stack trace due to OOM error";
73         return;
74     }
75 
76     env->CallVoidMethod(mScriptExecutorListener, onErrorMethod, static_cast<int>(errorType),
77                         messageStringRef.get(), stackTraceRef.get());
78 }
79 
getCurrentJNIEnv()80 JNIEnv* ScriptExecutorListener::getCurrentJNIEnv() {
81     JNIEnv* env;
82     if (mJavaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
83         LOG(FATAL) << "Unable to return JNIEnv from JavaVM";
84     }
85     return env;
86 }
87 
88 }  // namespace scriptexecutor
89 }  // namespace car
90 }  // namespace android
91 }  // namespace com
92