1 /*
2  * Copyright 2020 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 #define LOG_TAG "SurfaceToNativeHandleConverter"
18 
19 #include <android_os_NativeHandle.h>
20 #include <android_runtime/AndroidRuntime.h>
21 #include <android_runtime/android_view_Surface.h>
22 #include <gui/IGraphicBufferProducer.h>
23 #include <gui/Surface.h>
24 #include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
25 #include <utils/Log.h>
26 
27 #include "jni.h"
28 
29 namespace android {
30 namespace {
31 
32 constexpr int WINDOW_HAL_TOKEN_SIZE_MAX = 256;
33 
convertHalTokenToNativeHandle(const HalToken & halToken)34 native_handle_t* convertHalTokenToNativeHandle(const HalToken& halToken) {
35     // We attempt to store halToken in the ints of the native_handle_t after its
36     // size. The first int stores the size of the token. We store this in an int
37     // to avoid alignment issues where size_t and int do not have the same
38     // alignment.
39     size_t nhDataByteSize = halToken.size();
40     if (nhDataByteSize > WINDOW_HAL_TOKEN_SIZE_MAX) {
41         // The size of the token isn't reasonable..
42         return nullptr;
43     }
44     size_t numInts = ceil(nhDataByteSize / sizeof(int)) + 1;
45 
46     // We don't check for overflow, whether numInts can fit in an int, since we
47     // expect WINDOW_HAL_TOKEN_SIZE_MAX to be a reasonable limit.
48     // create a native_handle_t with 0 numFds and numInts number of ints.
49     native_handle_t* nh = native_handle_create(0, numInts);
50     if (!nh) {
51         return nullptr;
52     }
53     // Store the size of the token in the first int.
54     nh->data[0] = nhDataByteSize;
55     memcpy(&(nh->data[1]), halToken.data(), nhDataByteSize);
56     return nh;
57 }
58 
convertNativeHandleToHalToken(native_handle_t * handle)59 HalToken convertNativeHandleToHalToken(native_handle_t* handle) {
60     int size = handle->data[0];
61     auto data = reinterpret_cast<uint8_t*>(&handle->data[1]);
62     HalToken halToken;
63     halToken.setToExternal(data, size);
64     return halToken;
65 }
66 
acquireSurfaceHandle(JNIEnv * env,jobject,jobject jSurface)67 jobject acquireSurfaceHandle(JNIEnv* env, jobject /* clazz */, jobject jSurface) {
68     ALOGD("%s", __func__);
69     if (jSurface == nullptr) {
70         ALOGE("%s: jSurface is null", __func__);
71         return nullptr;
72     }
73 
74     sp<Surface> surface = android_view_Surface_getSurface(env, jSurface);
75     if (surface == nullptr) {
76         ALOGE("%s: surface is null", __func__);
77         return nullptr;
78     }
79 
80     sp<IGraphicBufferProducer> igbp = surface->getIGraphicBufferProducer();
81     sp<HGraphicBufferProducer> hgbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(igbp);
82     // The HAL token will be closed in releaseSurfaceHandle.
83     HalToken halToken;
84     createHalToken(hgbp, &halToken);
85 
86     native_handle_t* native_handle = convertHalTokenToNativeHandle(halToken);
87     if (native_handle == nullptr) {
88         ALOGE("%s: native_handle is null", __func__);
89         return nullptr;
90     }
91     jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, native_handle);
92     native_handle_delete(native_handle);
93 
94     return jHandle;
95 }
96 
releaseSurfaceHandle(JNIEnv * env,jobject,jobject jHandle)97 void releaseSurfaceHandle(JNIEnv* env, jobject /* clazz */, jobject jHandle) {
98     ALOGD("%s", __func__);
99     // Creates a native handle from a Java handle. We must call native_handle_delete when we're done
100     // with it because we created it, but we shouldn't call native_handle_close because we don't own
101     // the underlying FDs.
102     native_handle_t* handle =
103             JNativeHandle::MakeCppNativeHandle(env, jHandle, nullptr /* storage */);
104     if (handle == nullptr) {
105         ALOGE("%s: handle is null", __func__);
106         return;
107     }
108 
109     HalToken token = convertNativeHandleToHalToken(handle);
110     ALOGD("%s: deleteHalToken, success: %d", __func__, deleteHalToken(token));
111     ALOGD("%s: native_handle_delete, success: %d", __func__, !native_handle_delete(handle));
112 }
113 
114 const JNINativeMethod method_table[] = {
115         {"acquireSurfaceHandle", "(Landroid/view/Surface;)Landroid/os/NativeHandle;",
116          reinterpret_cast<void*>(acquireSurfaceHandle)},
117         {"releaseSurfaceHandle", "(Landroid/os/NativeHandle;)V",
118          reinterpret_cast<void*>(releaseSurfaceHandle)},
119 };
120 } // namespace
121 
register_android_server_FaceService(JNIEnv * env)122 int register_android_server_FaceService(JNIEnv* env) {
123     return AndroidRuntime::
124             registerNativeMethods(env, "com/android/server/biometrics/sensors/face/FaceService",
125                                   method_table, NELEM(method_table));
126 }
127 } // namespace android
128