1 /*
2 * Copyright 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 "EvsServiceContext.h"
18
19 #include <android-base/chrono_utils.h>
20 #include <android-base/logging.h>
21 #include <android/hardware_buffer.h>
22 #include <android_runtime/android_hardware_HardwareBuffer.h>
23 #include <nativehelper/JNIHelp.h>
24 #include <ui/GraphicBuffer.h>
25 #include <utils/Errors.h>
26 #include <utils/Mutex.h>
27 #include <utils/StrongPointer.h>
28 #include <vndk/hardware_buffer.h>
29
30 #include <jni.h>
31
32 #include <map>
33
34 using ::android::GraphicBuffer;
35 using ::android::Mutex;
36 using ::android::sp;
37 using ::android::automotive::evs::EvsServiceContext;
38
39 using namespace ::android::hardware::automotive::evs::V1_1;
40
41 namespace {
42
43 // CarEvsService class
44 constexpr const char* kCarEvsServiceClassName = "com/android/car/evs/CarEvsService";
45
46 /*
47 * Connects to the Extended View System service
48 */
connectToHalServiceIfNecessary(JNIEnv * env,jobject thiz,jlong handle)49 jboolean connectToHalServiceIfNecessary(JNIEnv* env, jobject thiz, jlong handle) {
50 EvsServiceContext* ctxt = reinterpret_cast<EvsServiceContext*>(handle);
51 if (!ctxt) {
52 LOG(ERROR) << "The service context is invalid.";
53 return JNI_FALSE;
54 }
55
56 if (ctxt->isAvailable()) {
57 LOG(DEBUG) << "Service is connected already.";
58 return JNI_TRUE;
59 }
60
61 LOG(DEBUG) << "Connecting to EVS service";
62
63 // Initializes a new service context with a death handler
64 if (!ctxt->initialize(env, thiz)) {
65 LOG(ERROR) << "Failed to initialize a service context";
66 return JNI_FALSE;
67 }
68
69 return JNI_TRUE;
70 }
71
72 /*
73 * Returns a consumed frame buffer to EVS service
74 */
returnFrameBuffer(JNIEnv *,jobject,jlong handle,jint bufferId)75 void returnFrameBuffer(JNIEnv* /*env*/, jobject /*thiz*/, jlong handle, jint bufferId) {
76 EvsServiceContext* ctxt = reinterpret_cast<EvsServiceContext*>(handle);
77 if (!ctxt) {
78 LOG(ERROR) << __FUNCTION__ << ": EVS service context is not available.";
79 return;
80 }
81
82 ctxt->doneWithFrame(bufferId);
83 }
84
85 /*
86 * Open the target camera device for the service
87 */
openCamera(JNIEnv * env,jobject,jlong handle,jstring cameraId)88 jboolean openCamera(JNIEnv* env, jobject /*thiz*/, jlong handle, jstring cameraId) {
89 EvsServiceContext* ctxt = reinterpret_cast<EvsServiceContext*>(handle);
90 if (!ctxt) {
91 LOG(ERROR) << __FUNCTION__ << ": EVS service context is not available.";
92 return JNI_FALSE;
93 }
94
95 // Attempts to open the target camera device
96 const char* id = env->GetStringUTFChars(cameraId, NULL);
97 if (!id || !ctxt->openCamera(id)) {
98 LOG(ERROR) << "Failed to open a camera device";
99 return JNI_FALSE;
100 }
101
102 env->ReleaseStringUTFChars(cameraId, id);
103 return JNI_TRUE;
104 }
105
106 /*
107 * Close the target camera device
108 */
closeCamera(JNIEnv *,jobject,jlong handle)109 void closeCamera(JNIEnv* /*env*/, jobject /*thiz*/, jlong handle) {
110 EvsServiceContext* ctxt = reinterpret_cast<EvsServiceContext*>(handle);
111 if (!ctxt) {
112 LOG(WARNING) << __FUNCTION__ << ": EVS service context is not available.";
113 }
114
115 ctxt->closeCamera();
116 }
117
118 /*
119 * Request to start a video stream
120 */
startVideoStream(JNIEnv *,jobject,jlong handle)121 jboolean startVideoStream(JNIEnv* /*env*/, jobject /*thiz*/, jlong handle) {
122 EvsServiceContext* ctxt = reinterpret_cast<EvsServiceContext*>(handle);
123 if (!ctxt) {
124 LOG(ERROR) << __FUNCTION__ << ": EVS service context is not available.";
125 return JNI_FALSE;
126 }
127
128 return ctxt->startVideoStream() ? JNI_TRUE : JNI_FALSE;
129 }
130
131 /*
132 * Request to stop a video stream
133 */
stopVideoStream(JNIEnv *,jobject,jlong handle)134 void stopVideoStream(JNIEnv* /*env*/, jobject /*thiz*/, jlong handle) {
135 EvsServiceContext* ctxt = reinterpret_cast<EvsServiceContext*>(handle);
136 if (!ctxt) {
137 LOG(WARNING) << __FUNCTION__ << ": EVS service context is not available.";
138 return;
139 }
140
141 ctxt->stopVideoStream();
142 }
143
144 /*
145 * Static method to create the service context
146 */
createServiceHandle(JNIEnv * env,jclass clazz)147 jlong createServiceHandle(JNIEnv* env, jclass clazz) {
148 JavaVM* vm = nullptr;
149 env->GetJavaVM(&vm);
150 if (vm == nullptr) {
151 jniThrowException(env, "java/lang/IllegalStateException",
152 "Can't initialize the EvsServiceContext because the JavaVM is invalid");
153 }
154
155 return reinterpret_cast<jlong>(new EvsServiceContext(vm, clazz));
156 }
157
158 /*
159 * Static method to destroy the service context
160 */
destroyServiceHandle(JNIEnv *,jclass,jlong handle)161 void destroyServiceHandle(JNIEnv* /*env*/, jclass /*clazz*/, jlong handle) {
162 delete reinterpret_cast<EvsServiceContext*>(handle);
163 }
164
165 } // namespace
166
167 namespace android {
168
initializeCarEvsService(JavaVM * vm)169 jint initializeCarEvsService(JavaVM* vm) {
170 JNIEnv* env;
171 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
172 LOG(ERROR) << __FUNCTION__ << ": Failed to get the environment.";
173 return JNI_ERR;
174 }
175
176 // Registers native methods
177 static const JNINativeMethod methods[] = {
178 {"nativeConnectToHalServiceIfNecessary", "(J)Z",
179 reinterpret_cast<void*>(connectToHalServiceIfNecessary)},
180 {"nativeOpenCamera", "(JLjava/lang/String;)Z",
181 reinterpret_cast<void*>(openCamera)},
182 {"nativeCloseCamera", "(J)V",
183 reinterpret_cast<void*>(closeCamera)},
184 {"nativeRequestToStartVideoStream", "(J)Z",
185 reinterpret_cast<void*>(startVideoStream)},
186 {"nativeRequestToStopVideoStream", "(J)V",
187 reinterpret_cast<void*>(stopVideoStream)},
188 {"nativeDoneWithFrame", "(JI)V",
189 reinterpret_cast<void*>(returnFrameBuffer)},
190 {"nativeCreateServiceHandle", "()J",
191 reinterpret_cast<void*>(createServiceHandle)},
192 {"nativeDestroyServiceHandle", "(J)V",
193 reinterpret_cast<void*>(destroyServiceHandle)},
194 };
195 jniRegisterNativeMethods(env, kCarEvsServiceClassName, methods, NELEM(methods));
196
197 return JNI_VERSION_1_6;
198 }
199
200 } // namespace android
201