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 "BundleWrapper.h"
18
19 #include "JniUtils.h"
20 #include "nativehelper/scoped_local_ref.h"
21
22 namespace com {
23 namespace android {
24 namespace car {
25 namespace scriptexecutor {
26
27 using ::android::base::Error;
28 using ::android::base::Result;
29
BundleWrapper(JNIEnv * env)30 BundleWrapper::BundleWrapper(JNIEnv* env) {
31 mJNIEnv = env;
32 ScopedLocalRef<jclass> localBundleClassRef(mJNIEnv,
33 mJNIEnv->FindClass("android/os/PersistableBundle"));
34 mBundleClass = static_cast<jclass>(mJNIEnv->NewGlobalRef(localBundleClassRef.get()));
35
36 jmethodID bundleConstructor = mJNIEnv->GetMethodID(mBundleClass, "<init>", "()V");
37 ScopedLocalRef<jobject> localBundleObjectRef(mJNIEnv,
38 mJNIEnv->NewObject(mBundleClass,
39 bundleConstructor));
40 mBundle = mJNIEnv->NewGlobalRef(localBundleObjectRef.get());
41 }
42
~BundleWrapper()43 BundleWrapper::~BundleWrapper() {
44 // Delete global JNI references.
45 if (mBundle != NULL) {
46 mJNIEnv->DeleteGlobalRef(mBundle);
47 }
48 if (mBundleClass != NULL) {
49 mJNIEnv->DeleteGlobalRef(mBundleClass);
50 }
51 }
52
putBoolean(const char * key,bool value)53 Result<void> BundleWrapper::putBoolean(const char* key, bool value) {
54 ScopedLocalRef<jstring> keyStringRef(mJNIEnv, mJNIEnv->NewStringUTF(key));
55 if (keyStringRef == nullptr) {
56 return Error() << "Failed to create a string for a key=" << key << " due to OOM error";
57 }
58
59 // TODO(b/188832769): consider caching the references.
60 jmethodID putBooleanMethod =
61 mJNIEnv->GetMethodID(mBundleClass, "putBoolean", "(Ljava/lang/String;Z)V");
62 mJNIEnv->CallVoidMethod(mBundle, putBooleanMethod, keyStringRef.get(),
63 static_cast<jboolean>(value));
64 return {}; // ok result
65 }
66
putLong(const char * key,int64_t value)67 Result<void> BundleWrapper::putLong(const char* key, int64_t value) {
68 ScopedLocalRef<jstring> keyStringRef(mJNIEnv, mJNIEnv->NewStringUTF(key));
69 if (keyStringRef == nullptr) {
70 return Error() << "Failed to create a string for a key=" << key << " due to OOM error";
71 }
72
73 jmethodID putLongMethod =
74 mJNIEnv->GetMethodID(mBundleClass, "putLong", "(Ljava/lang/String;J)V");
75 mJNIEnv->CallVoidMethod(mBundle, putLongMethod, keyStringRef.get(), static_cast<jlong>(value));
76 return {}; // ok result
77 }
78
putDouble(const char * key,double value)79 Result<void> BundleWrapper::putDouble(const char* key, double value) {
80 ScopedLocalRef<jstring> keyStringRef(mJNIEnv, mJNIEnv->NewStringUTF(key));
81 if (keyStringRef == nullptr) {
82 return Error() << "Failed to create a string for a key=" << key << " due to OOM error";
83 }
84
85 jmethodID putDoubleMethod =
86 mJNIEnv->GetMethodID(mBundleClass, "putDouble", "(Ljava/lang/String;D)V");
87 mJNIEnv->CallVoidMethod(mBundle, putDoubleMethod, keyStringRef.get(),
88 static_cast<jdouble>(value));
89 return {}; // ok result
90 }
91
putString(const char * key,const char * value)92 Result<void> BundleWrapper::putString(const char* key, const char* value) {
93 jmethodID putStringMethod = mJNIEnv->GetMethodID(mBundleClass, "putString",
94 "(Ljava/lang/String;Ljava/lang/String;)V");
95 ScopedLocalRef<jstring> keyStringRef(mJNIEnv, mJNIEnv->NewStringUTF(key));
96 if (keyStringRef == nullptr) {
97 return Error() << "Failed to create a string for a key=" << key << " due to OOM error";
98 }
99
100 ScopedLocalRef<jstring> valueStringRef(mJNIEnv, mJNIEnv->NewStringUTF(value));
101 if (valueStringRef == nullptr) {
102 return Error() << "Failed to create a string for the provided value due to OOM error";
103 }
104
105 mJNIEnv->CallVoidMethod(mBundle, putStringMethod, keyStringRef.get(), valueStringRef.get());
106 return {}; // ok result
107 }
108
putLongArray(const char * key,const std::vector<int64_t> & value)109 Result<void> BundleWrapper::putLongArray(const char* key, const std::vector<int64_t>& value) {
110 ScopedLocalRef<jstring> keyStringRef(mJNIEnv, mJNIEnv->NewStringUTF(key));
111 if (keyStringRef == nullptr) {
112 return Error() << "Failed to create a string for a key=" << key << " due to OOM error";
113 }
114
115 jmethodID putLongArrayMethod =
116 mJNIEnv->GetMethodID(mBundleClass, "putLongArray", "(Ljava/lang/String;[J)V");
117
118 ScopedLocalRef<jlongArray> arrayRef(mJNIEnv, mJNIEnv->NewLongArray(value.size()));
119 mJNIEnv->SetLongArrayRegion(arrayRef.get(), 0, value.size(), &value[0]);
120 mJNIEnv->CallVoidMethod(mBundle, putLongArrayMethod, keyStringRef.get(), arrayRef.get());
121 return {}; // ok result
122 }
123
putStringArray(const char * key,const std::vector<std::string> & value)124 Result<void> BundleWrapper::putStringArray(const char* key, const std::vector<std::string>& value) {
125 ScopedLocalRef<jstring> keyStringRef(mJNIEnv, mJNIEnv->NewStringUTF(key));
126 if (keyStringRef == nullptr) {
127 return Error() << "Failed to create a string for a key=" << key << " due to OOM error";
128 }
129
130 jmethodID putStringArrayMethod =
131 mJNIEnv->GetMethodID(mBundleClass, "putStringArray",
132 "(Ljava/lang/String;[Ljava/lang/String;)V");
133
134 ScopedLocalRef<jclass> stringClassRef(mJNIEnv, mJNIEnv->FindClass("java/lang/String"));
135 ScopedLocalRef<jobjectArray> arrayRef(mJNIEnv,
136 mJNIEnv->NewObjectArray(value.size(),
137 mJNIEnv->FindClass(
138 "java/lang/String"),
139 nullptr));
140 for (int i = 0; i < value.size(); i++) {
141 ScopedLocalRef<jstring> valueStringRef(mJNIEnv, mJNIEnv->NewStringUTF(value[i].c_str()));
142 if (valueStringRef == nullptr) {
143 return Error() << "Failed to create a string for provided value due to OOM error";
144 }
145 mJNIEnv->SetObjectArrayElement(arrayRef.get(), i, valueStringRef.get());
146 }
147 mJNIEnv->CallVoidMethod(mBundle, putStringArrayMethod, keyStringRef.get(), arrayRef.get());
148 return {}; // ok result
149 }
150
getBundle()151 jobject BundleWrapper::getBundle() {
152 return mBundle;
153 }
154
155 } // namespace scriptexecutor
156 } // namespace car
157 } // namespace android
158 } // namespace com
159