1 /*
2  * Copyright (C) 2022 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 package com.android.car.evs;
18 
19 import android.hardware.HardwareBuffer;
20 
21 import com.android.car.internal.evs.EvsHalWrapper;
22 import com.android.internal.annotations.GuardedBy;
23 import com.android.internal.annotations.VisibleForTesting;
24 
25 /**
26  * EvaHalWrapper impl used by updatable car service.
27  */
28 public final class EvsHalWrapperImpl extends EvsHalWrapper {
29 
30 
31     /**
32      * Because of its dependency on FMQ type, android.hardware.automotive.evs@1.1 interface does
33      * not support Java backend.  Therefore, all hwbinder transactions happen in native methods
34      * declared below.
35      */
36 
37     static {
38         System.loadLibrary("carservicejni");
39     }
40 
41     private final EvsHalWrapper.HalEventCallback mCallback;
42 
43     private final Object mLock = new Object();
44 
45     /** Stores a service handle initialized in native methods */
46     @GuardedBy("mLock")
47     private long mNativeEvsServiceObj;
48 
49     /** Constructor */
EvsHalWrapperImpl(EvsHalWrapper.HalEventCallback callback)50     public EvsHalWrapperImpl(EvsHalWrapper.HalEventCallback callback) {
51         super();
52         mCallback = callback;
53     }
54 
55     /**
56      * Create a {@code EvsHalWrapperImpl} object with a given JNI library that implements native
57      * methods.
58      */
59     @VisibleForTesting
create(EvsHalWrapper.HalEventCallback callback, String jniLibraryName)60     static EvsHalWrapperImpl create(EvsHalWrapper.HalEventCallback callback,
61             String jniLibraryName) {
62         System.loadLibrary(jniLibraryName);
63         return new EvsHalWrapperImpl(callback);
64     }
65 
66     @Override
init()67     public boolean init() {
68         long handle = nativeCreateServiceHandle();
69         if (handle == 0) {
70             return false;
71         }
72         synchronized (mLock) {
73             mNativeEvsServiceObj = handle;
74         }
75         return true;
76     }
77 
78     @Override
release()79     public void release() {
80         long handle;
81         synchronized (mLock) {
82             handle = mNativeEvsServiceObj;
83             mNativeEvsServiceObj = 0;
84         }
85         if (handle == 0) {
86             return;
87         }
88         nativeDestroyServiceHandle(handle);
89     }
90 
91     @Override
isConnected()92     public boolean isConnected() {
93         return getNativeHandle() != 0;
94     }
95 
96     @Override
connectToHalServiceIfNecessary()97     public boolean connectToHalServiceIfNecessary() {
98         if (!isConnected() && !init()) {
99             return false;
100         }
101 
102         return nativeConnectToHalServiceIfNecessary(getNativeHandle());
103     }
104 
105     @Override
disconnectFromHalService()106     public void disconnectFromHalService() {
107         nativeDisconnectFromHalService(getNativeHandle());
108     }
109 
110     @Override
openCamera(String cameraId)111     public boolean openCamera(String cameraId) {
112         return nativeOpenCamera(getNativeHandle(), cameraId);
113     }
114 
115     @Override
closeCamera()116     public void closeCamera() {
117         nativeCloseCamera(getNativeHandle());
118     }
119 
120     @Override
requestToStartVideoStream()121     public boolean requestToStartVideoStream() {
122         return nativeRequestToStartVideoStream(getNativeHandle());
123     }
124 
125     @Override
requestToStopVideoStream()126     public void requestToStopVideoStream() {
127         nativeRequestToStopVideoStream(getNativeHandle());
128     }
129 
130     @Override
doneWithFrame(int bufferId)131     public void doneWithFrame(int bufferId) {
132         nativeDoneWithFrame(getNativeHandle(), bufferId);
133     }
134 
135     @VisibleForTesting
setServiceHandle(long handleToUse)136     boolean setServiceHandle(long handleToUse) {
137         if (handleToUse == 0) {
138             return false;
139         }
140 
141         long handleToDestroy;
142         synchronized (mLock) {
143             handleToDestroy = mNativeEvsServiceObj;
144             mNativeEvsServiceObj = handleToUse;
145         }
146 
147         nativeDestroyServiceHandle(handleToDestroy);
148         return true;
149     }
150 
151     @VisibleForTesting
createServiceHandleForTest()152     long createServiceHandleForTest() {
153         return nativeCreateServiceHandleForTest();
154     }
155 
156 
157     @VisibleForTesting
triggerBinderDied()158     void triggerBinderDied() {
159         nativeTriggerBinderDied(getNativeHandle());
160     }
161 
getNativeHandle()162     private long getNativeHandle() {
163         synchronized (mLock) {
164             return mNativeEvsServiceObj;
165         }
166     }
167 
168     /** EVS stream event handler called after a native handler */
postNativeEventHandler(int eventType)169     private void postNativeEventHandler(int eventType) {
170         mCallback.onHalEvent(eventType);
171     }
172 
173     /** EVS frame handler called after a native handler */
postNativeFrameHandler(int id, HardwareBuffer buffer)174     private void postNativeFrameHandler(int id, HardwareBuffer buffer) {
175         mCallback.onFrameEvent(id, buffer);
176     }
177 
178     /** EVS service death handler called after a native handler */
postNativeDeathHandler()179     private void postNativeDeathHandler() {
180         mCallback.onHalDeath();
181     }
182 
183     /** Attempts to connect to the HAL service if it has not done yet */
nativeConnectToHalServiceIfNecessary(long handle)184     private native boolean nativeConnectToHalServiceIfNecessary(long handle);
185 
186     /** Attempts to disconnect from the HAL service */
nativeDisconnectFromHalService(long handle)187     private native void nativeDisconnectFromHalService(long handle);
188 
189     /** Attempts to open a target camera device */
nativeOpenCamera(long handle, String cameraId)190     private native boolean nativeOpenCamera(long handle, String cameraId);
191 
192     /** Requests to close a target camera device */
nativeCloseCamera(long handle)193     private native void nativeCloseCamera(long handle);
194 
195     /** Requests to start a video stream */
nativeRequestToStartVideoStream(long handle)196     private native boolean nativeRequestToStartVideoStream(long handle);
197 
198     /** Requests to stop a video stream */
nativeRequestToStopVideoStream(long handle)199     private native void nativeRequestToStopVideoStream(long handle);
200 
201     /** Request to return an used buffer */
nativeDoneWithFrame(long handle, int bufferId)202     private native void nativeDoneWithFrame(long handle, int bufferId);
203 
204     /** Trigger a onBinderDied callback for tests */
nativeTriggerBinderDied(long handle)205     private native void nativeTriggerBinderDied(long handle);
206 
207     /** Creates a EVS service handle */
nativeCreateServiceHandle()208     private static native long nativeCreateServiceHandle();
209 
210     /** Creates a EVS service handle for tests */
nativeCreateServiceHandleForTest()211     private static native long nativeCreateServiceHandleForTest();
212 
213     /** Destroys a EVS service handle */
nativeDestroyServiceHandle(long handle)214     private static native void nativeDestroyServiceHandle(long handle);
215 }
216