Merge "Implementing support for HIDL native handles in Java"
am: 1e1d8d2485
Change-Id: I5f2f709bcb87174850140e5ca7d4296338c1f56f
This commit is contained in:
@@ -898,6 +898,7 @@ java_library {
|
||||
"core/java/android/os/IHwInterface.java",
|
||||
"core/java/android/os/DeadObjectException.java",
|
||||
"core/java/android/os/DeadSystemException.java",
|
||||
"core/java/android/os/NativeHandle.java",
|
||||
"core/java/android/os/RemoteException.java",
|
||||
"core/java/android/util/AndroidException.java",
|
||||
],
|
||||
@@ -1444,6 +1445,7 @@ droiddoc {
|
||||
"core/java/android/os/IHwInterface.java",
|
||||
"core/java/android/os/DeadObjectException.java",
|
||||
"core/java/android/os/DeadSystemException.java",
|
||||
"core/java/android/os/NativeHandle.java",
|
||||
"core/java/android/os/RemoteException.java",
|
||||
"core/java/android/util/AndroidException.java",
|
||||
],
|
||||
|
||||
@@ -3726,6 +3726,7 @@ package android.os {
|
||||
method public final void putInt64Array(long, long[]);
|
||||
method public final void putInt8(long, byte);
|
||||
method public final void putInt8Array(long, byte[]);
|
||||
method public final void putNativeHandle(long, android.os.NativeHandle);
|
||||
method public final void putString(long, java.lang.String);
|
||||
method public static java.lang.Boolean[] wrapArray(boolean[]);
|
||||
method public static java.lang.Long[] wrapArray(long[]);
|
||||
@@ -3745,6 +3746,7 @@ package android.os {
|
||||
method public final double readDouble();
|
||||
method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
|
||||
method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
|
||||
method public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
|
||||
method public final float readFloat();
|
||||
method public final java.util.ArrayList<java.lang.Float> readFloatVector();
|
||||
method public final short readInt16();
|
||||
@@ -3755,6 +3757,8 @@ package android.os {
|
||||
method public final java.util.ArrayList<java.lang.Long> readInt64Vector();
|
||||
method public final byte readInt8();
|
||||
method public final java.util.ArrayList<java.lang.Byte> readInt8Vector();
|
||||
method public final android.os.NativeHandle readNativeHandle();
|
||||
method public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
|
||||
method public final java.lang.String readString();
|
||||
method public final java.util.ArrayList<java.lang.String> readStringVector();
|
||||
method public final android.os.IHwBinder readStrongBinder();
|
||||
@@ -3778,6 +3782,8 @@ package android.os {
|
||||
method public final void writeInt8(byte);
|
||||
method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
|
||||
method public final void writeInterfaceToken(java.lang.String);
|
||||
method public final void writeNativeHandle(android.os.NativeHandle);
|
||||
method public final void writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>);
|
||||
method public final void writeStatus(int);
|
||||
method public final void writeString(java.lang.String);
|
||||
method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
|
||||
@@ -3822,6 +3828,18 @@ package android.os {
|
||||
field public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
|
||||
}
|
||||
|
||||
public final class NativeHandle implements java.io.Closeable {
|
||||
ctor public NativeHandle();
|
||||
ctor public NativeHandle(java.io.FileDescriptor, boolean);
|
||||
ctor public NativeHandle(java.io.FileDescriptor[], int[], boolean);
|
||||
method public void close() throws java.io.IOException;
|
||||
method public android.os.NativeHandle dup() throws java.io.IOException;
|
||||
method public java.io.FileDescriptor getFileDescriptor();
|
||||
method public java.io.FileDescriptor[] getFileDescriptors();
|
||||
method public int[] getInts();
|
||||
method public boolean hasSingleFileDescriptor();
|
||||
}
|
||||
|
||||
public final class PowerManager {
|
||||
method public void userActivity(long, int, int);
|
||||
field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
|
||||
|
||||
@@ -232,6 +232,14 @@ public class HwBlob {
|
||||
* @throws IndexOutOfBoundsException when [offset, offset + sizeof(jstring)] is out of range
|
||||
*/
|
||||
public native final void putString(long offset, String x);
|
||||
/**
|
||||
* Writes a native handle (without duplicating the underlying file descriptors) at an offset.
|
||||
*
|
||||
* @param offset location to write value
|
||||
* @param x a {@link NativeHandle} instance to write
|
||||
* @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range
|
||||
*/
|
||||
public native final void putNativeHandle(long offset, NativeHandle x);
|
||||
|
||||
/**
|
||||
* Put a boolean array contiguously at an offset in the blob.
|
||||
|
||||
@@ -115,6 +115,13 @@ public class HwParcel {
|
||||
* @param val to write
|
||||
*/
|
||||
public native final void writeString(String val);
|
||||
/**
|
||||
* Writes a native handle (without duplicating the underlying
|
||||
* file descriptors) to the end of the parcel.
|
||||
*
|
||||
* @param val to write
|
||||
*/
|
||||
public native final void writeNativeHandle(NativeHandle val);
|
||||
|
||||
/**
|
||||
* Writes an array of boolean values to the end of the parcel.
|
||||
@@ -159,6 +166,11 @@ public class HwParcel {
|
||||
* @param val to write
|
||||
*/
|
||||
private native final void writeStringVector(String[] val);
|
||||
/**
|
||||
* Writes an array of native handles to the end of the parcel.
|
||||
* @param val array of {@link NativeHandle} objects to write
|
||||
*/
|
||||
private native final void writeNativeHandleVector(NativeHandle[] val);
|
||||
|
||||
/**
|
||||
* Helper method to write a list of Booleans to val.
|
||||
@@ -266,6 +278,14 @@ public class HwParcel {
|
||||
writeStringVector(val.toArray(new String[val.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to write a list of native handles to the end of the parcel.
|
||||
* @param val list of {@link NativeHandle} objects to write
|
||||
*/
|
||||
public final void writeNativeHandleVector(ArrayList<NativeHandle> val) {
|
||||
writeNativeHandleVector(val.toArray(new NativeHandle[val.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a hwbinder object to the end of the parcel.
|
||||
* @param binder value to write
|
||||
@@ -328,6 +348,30 @@ public class HwParcel {
|
||||
* @throws IllegalArgumentException if the parcel has no more data
|
||||
*/
|
||||
public native final String readString();
|
||||
/**
|
||||
* Reads a native handle (without duplicating the underlying file
|
||||
* descriptors) from the parcel. These file descriptors will only
|
||||
* be open for the duration that the binder window is open. If they
|
||||
* are needed further, you must call {@link NativeHandle#dup()}.
|
||||
*
|
||||
* @return a {@link NativeHandle} instance parsed from the parcel
|
||||
* @throws IllegalArgumentException if the parcel has no more data
|
||||
*/
|
||||
public native final NativeHandle readNativeHandle();
|
||||
/**
|
||||
* Reads an embedded native handle (without duplicating the underlying
|
||||
* file descriptors) from the parcel. These file descriptors will only
|
||||
* be open for the duration that the binder window is open. If they
|
||||
* are needed further, you must call {@link NativeHandle#dup()}. You
|
||||
* do not need to call close on the NativeHandle returned from this.
|
||||
*
|
||||
* @param parentHandle handle from which to read the embedded object
|
||||
* @param offset offset into parent
|
||||
* @return a {@link NativeHandle} instance parsed from the parcel
|
||||
* @throws IllegalArgumentException if the parcel has no more data
|
||||
*/
|
||||
public native final NativeHandle readEmbeddedNativeHandle(
|
||||
long parentHandle, long offset);
|
||||
|
||||
/**
|
||||
* Reads an array of boolean values from the parcel.
|
||||
@@ -377,6 +421,12 @@ public class HwParcel {
|
||||
* @throws IllegalArgumentException if the parcel has no more data
|
||||
*/
|
||||
private native final String[] readStringVectorAsArray();
|
||||
/**
|
||||
* Reads an array of native handles from the parcel.
|
||||
* @return array of {@link NativeHandle} objects
|
||||
* @throws IllegalArgumentException if the parcel has no more data
|
||||
*/
|
||||
private native final NativeHandle[] readNativeHandleAsArray();
|
||||
|
||||
/**
|
||||
* Convenience method to read a Boolean vector as an ArrayList.
|
||||
@@ -464,6 +514,15 @@ public class HwParcel {
|
||||
return new ArrayList<String>(Arrays.asList(readStringVectorAsArray()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to read a vector of native handles as an ArrayList.
|
||||
* @return array of {@link NativeHandle} objects.
|
||||
* @throws IllegalArgumentException if the parcel has no more data
|
||||
*/
|
||||
public final ArrayList<NativeHandle> readNativeHandleVector() {
|
||||
return new ArrayList<NativeHandle>(Arrays.asList(readNativeHandleAsArray()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a strong binder value from the parcel.
|
||||
* @return binder object read from parcel or null if no binder can be read
|
||||
|
||||
191
core/java/android/os/NativeHandle.java
Normal file
191
core/java/android/os/NativeHandle.java
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.os;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
/**
|
||||
* Collection representing a set of open file descriptors and an opaque data stream.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public final class NativeHandle implements Closeable {
|
||||
// whether this object owns mFds
|
||||
private boolean mOwn = false;
|
||||
private FileDescriptor[] mFds;
|
||||
private int[] mInts;
|
||||
|
||||
/**
|
||||
* Constructs a {@link NativeHandle} object containing
|
||||
* zero file descriptors and an empty data stream.
|
||||
*/
|
||||
public NativeHandle() {
|
||||
this(new FileDescriptor[0], new int[0], false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link NativeHandle} object containing the given
|
||||
* {@link FileDescriptor} object and an empty data stream.
|
||||
*/
|
||||
public NativeHandle(@NonNull FileDescriptor descriptor, boolean own) {
|
||||
this(new FileDescriptor[] {descriptor}, new int[0], own);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for creating a list of file descriptors.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
private static FileDescriptor[] createFileDescriptorArray(@NonNull int[] fds) {
|
||||
FileDescriptor[] list = new FileDescriptor[fds.length];
|
||||
for (int i = 0; i < fds.length; i++) {
|
||||
FileDescriptor descriptor = new FileDescriptor();
|
||||
descriptor.setInt$(fds[i]);
|
||||
list[i] = descriptor;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for instantiating a {@link NativeHandle} from JNI. It does
|
||||
* not take ownership of the int[] params. It does not dupe the FileDescriptors.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
private NativeHandle(@NonNull int[] fds, @NonNull int[] ints, boolean own) {
|
||||
this(createFileDescriptorArray(fds), ints, own);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate an opaque {@link NativeHandle} from fds and integers.
|
||||
*
|
||||
* @param own whether the fds are owned by this object and should be closed
|
||||
*/
|
||||
public NativeHandle(@NonNull FileDescriptor[] fds, @NonNull int[] ints, boolean own) {
|
||||
mFds = fds.clone();
|
||||
mInts = ints.clone();
|
||||
mOwn = own;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this {@link NativeHandle} object contains a single file
|
||||
* descriptor and nothing else.
|
||||
*
|
||||
* @return a boolean value
|
||||
*/
|
||||
public boolean hasSingleFileDescriptor() {
|
||||
return mFds.length == 1 && mInts.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly duplicate NativeHandle (this dups all file descritptors).
|
||||
*/
|
||||
public NativeHandle dup() throws java.io.IOException {
|
||||
FileDescriptor[] fds = new FileDescriptor[mFds.length];
|
||||
try {
|
||||
for (int i = 0; i < mFds.length; i++) {
|
||||
fds[i] = Os.dup(mFds[i]);
|
||||
}
|
||||
} catch (ErrnoException e) {
|
||||
e.rethrowAsIOException();
|
||||
}
|
||||
return new NativeHandle(fds, mInts, true /*own*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the file descriptors if they are owned by this object.
|
||||
*
|
||||
* This also invalidates the object.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws java.io.IOException {
|
||||
if (!mOwn) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
for (FileDescriptor fd : mFds) {
|
||||
Os.close(fd);
|
||||
}
|
||||
} catch (ErrnoException e) {
|
||||
e.rethrowAsIOException();
|
||||
}
|
||||
|
||||
mOwn = false;
|
||||
mFds = null;
|
||||
mInts = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying lone file descriptor.
|
||||
*
|
||||
* @return a {@link FileDescriptor} object
|
||||
* @throws IllegalStateException if this object contains either zero or
|
||||
* more than one file descriptor, or a non-empty data stream.
|
||||
*/
|
||||
public FileDescriptor getFileDescriptor() {
|
||||
if (!hasSingleFileDescriptor()) {
|
||||
throw new IllegalStateException(
|
||||
"NativeHandle is not single file descriptor. Contents must"
|
||||
+ " be retreived through getFileDescriptors and getInts.");
|
||||
}
|
||||
|
||||
return mFds[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for fetching this object's file descriptors from JNI.
|
||||
* @return a mutable copy of the underlying file descriptors (as an int[])
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
private int[] getFdsAsIntArray() {
|
||||
int numFds = mFds.length;
|
||||
int[] fds = new int[numFds];
|
||||
|
||||
for (int i = 0; i < numFds; i++) {
|
||||
fds[i] = mFds[i].getInt$();
|
||||
}
|
||||
|
||||
return fds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch file descriptors.
|
||||
*
|
||||
* @return the fds.
|
||||
*/
|
||||
public FileDescriptor[] getFileDescriptors() {
|
||||
return mFds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch opaque ints. Note: This object retains ownership of the data.
|
||||
*
|
||||
* @return the opaque data stream.
|
||||
*/
|
||||
public int[] getInts() {
|
||||
return mInts;
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,7 @@ cc_library_shared {
|
||||
"android_os_HwBlob.cpp",
|
||||
"android_os_HwParcel.cpp",
|
||||
"android_os_HwRemoteBinder.cpp",
|
||||
"android_os_NativeHandle.cpp",
|
||||
"android_os_MemoryFile.cpp",
|
||||
"android_os_MessageQueue.cpp",
|
||||
"android_os_Parcel.cpp",
|
||||
|
||||
@@ -165,6 +165,7 @@ extern int register_android_os_HwBinder(JNIEnv *env);
|
||||
extern int register_android_os_HwBlob(JNIEnv *env);
|
||||
extern int register_android_os_HwParcel(JNIEnv *env);
|
||||
extern int register_android_os_HwRemoteBinder(JNIEnv *env);
|
||||
extern int register_android_os_NativeHandle(JNIEnv *env);
|
||||
extern int register_android_os_MessageQueue(JNIEnv* env);
|
||||
extern int register_android_os_Parcel(JNIEnv* env);
|
||||
extern int register_android_os_SELinux(JNIEnv* env);
|
||||
@@ -1345,6 +1346,7 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_os_HwBlob),
|
||||
REG_JNI(register_android_os_HwParcel),
|
||||
REG_JNI(register_android_os_HwRemoteBinder),
|
||||
REG_JNI(register_android_os_NativeHandle),
|
||||
REG_JNI(register_android_os_VintfObject),
|
||||
REG_JNI(register_android_os_VintfRuntimeInfo),
|
||||
REG_JNI(register_android_nio_utils),
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "android_os_HwBlob.h"
|
||||
|
||||
#include "android_os_HwParcel.h"
|
||||
#include "android_os_NativeHandle.h"
|
||||
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
@@ -31,6 +32,7 @@
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
using android::AndroidRuntime;
|
||||
using android::hardware::hidl_handle;
|
||||
using android::hardware::hidl_string;
|
||||
|
||||
#define PACKAGE_PATH "android/os"
|
||||
@@ -82,6 +84,7 @@ sp<JHwBlob> JHwBlob::GetNativeContext(JNIEnv *env, jobject thiz) {
|
||||
JHwBlob::JHwBlob(JNIEnv *env, jobject thiz, size_t size)
|
||||
: mBuffer(nullptr),
|
||||
mSize(size),
|
||||
mType(BlobType::GENERIC),
|
||||
mOwnsBuffer(true),
|
||||
mHandle(0) {
|
||||
if (size > 0) {
|
||||
@@ -159,6 +162,15 @@ size_t JHwBlob::size() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
void JHwBlob::specializeBlobTo(BlobType type) {
|
||||
CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
|
||||
mType = type;
|
||||
}
|
||||
|
||||
JHwBlob::BlobType JHwBlob::type() const {
|
||||
return mType;
|
||||
}
|
||||
|
||||
status_t JHwBlob::putBlob(size_t offset, const sp<JHwBlob> &blob) {
|
||||
size_t index = mSubBlobs.add();
|
||||
BlobInfo *info = &mSubBlobs.editItemAt(index);
|
||||
@@ -172,42 +184,52 @@ status_t JHwBlob::putBlob(size_t offset, const sp<JHwBlob> &blob) {
|
||||
}
|
||||
|
||||
status_t JHwBlob::writeToParcel(hardware::Parcel *parcel) const {
|
||||
size_t handle;
|
||||
CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
|
||||
|
||||
size_t handle = 0;
|
||||
status_t err = parcel->writeBuffer(data(), size(), &handle);
|
||||
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mSubBlobs.size(); ++i) {
|
||||
const BlobInfo &info = mSubBlobs[i];
|
||||
|
||||
err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);
|
||||
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
return writeSubBlobsToParcel(parcel, handle);
|
||||
}
|
||||
|
||||
status_t JHwBlob::writeEmbeddedToParcel(
|
||||
hardware::Parcel *parcel,
|
||||
size_t parentHandle,
|
||||
size_t parentOffset) const {
|
||||
size_t handle;
|
||||
status_t err = parcel->writeEmbeddedBuffer(
|
||||
data(), size(), &handle, parentHandle, parentOffset);
|
||||
size_t handle = 0;
|
||||
status_t err = OK;
|
||||
|
||||
switch (mType) {
|
||||
case BlobType::GENERIC: {
|
||||
err = parcel->writeEmbeddedBuffer(data(), size(), &handle, parentHandle, parentOffset);
|
||||
break;
|
||||
}
|
||||
case BlobType::NATIVE_HANDLE: {
|
||||
err = parcel->writeEmbeddedNativeHandle(
|
||||
static_cast<const native_handle *>(data()), parentHandle, parentOffset);
|
||||
|
||||
CHECK(mSubBlobs.empty());
|
||||
break;
|
||||
}
|
||||
default: { err = INVALID_OPERATION; }
|
||||
}
|
||||
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return writeSubBlobsToParcel(parcel, handle);
|
||||
}
|
||||
|
||||
status_t JHwBlob::writeSubBlobsToParcel(hardware::Parcel *parcel,
|
||||
size_t parentHandle) const {
|
||||
for (size_t i = 0; i < mSubBlobs.size(); ++i) {
|
||||
const BlobInfo &info = mSubBlobs[i];
|
||||
|
||||
err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);
|
||||
status_t err = info.mBlob->writeEmbeddedToParcel(parcel, parentHandle, info.mOffset);
|
||||
|
||||
if (err != OK) {
|
||||
return err;
|
||||
@@ -252,7 +274,7 @@ static void releaseNativeContext(void *nativeContext) {
|
||||
}
|
||||
}
|
||||
|
||||
static jlong JHwBlob_native_init(JNIEnv *env) {
|
||||
static jlong JHwBlob_native_init(JNIEnv *env, jclass /*clazz*/) {
|
||||
JHwBlob::InitClass(env);
|
||||
|
||||
return reinterpret_cast<jlong>(&releaseNativeContext);
|
||||
@@ -456,6 +478,31 @@ static void JHwBlob_native_putString(
|
||||
blob->putBlob(offset + hidl_string::kOffsetOfBuffer, subBlob);
|
||||
}
|
||||
|
||||
static void JHwBlob_native_putNativeHandle(JNIEnv *env, jobject thiz,
|
||||
jlong offset, jobject jHandle) {
|
||||
std::unique_ptr<native_handle_t, int(*)(native_handle_t*)> nativeHandle(
|
||||
JNativeHandle::MakeCppNativeHandle(env, jHandle, nullptr /* storage */),
|
||||
native_handle_delete);
|
||||
|
||||
size_t size = 0;
|
||||
if (nativeHandle != nullptr) {
|
||||
size = sizeof(native_handle_t) + nativeHandle->numFds * sizeof(int)
|
||||
+ nativeHandle->numInts * sizeof(int);
|
||||
}
|
||||
|
||||
ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size));
|
||||
sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get());
|
||||
subBlob->specializeBlobTo(JHwBlob::BlobType::NATIVE_HANDLE);
|
||||
subBlob->write(0 /* offset */, nativeHandle.get(), size);
|
||||
|
||||
hidl_handle cppHandle;
|
||||
cppHandle.setTo(static_cast<native_handle_t *>(subBlob->data()), false /* shouldOwn */);
|
||||
|
||||
sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
|
||||
blob->write(offset, &cppHandle, sizeof(cppHandle));
|
||||
blob->putBlob(offset + hidl_handle::kOffsetOfNativeHandle, subBlob);
|
||||
}
|
||||
|
||||
#define DEFINE_BLOB_ARRAY_PUTTER(Suffix,Type,NewType) \
|
||||
static void JHwBlob_native_put ## Suffix ## Array( \
|
||||
JNIEnv *env, jobject thiz, jlong offset, Type ## Array array) { \
|
||||
@@ -563,6 +610,8 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "putFloat", "(JF)V", (void *)JHwBlob_native_putFloat },
|
||||
{ "putDouble", "(JD)V", (void *)JHwBlob_native_putDouble },
|
||||
{ "putString", "(JLjava/lang/String;)V", (void *)JHwBlob_native_putString },
|
||||
{ "putNativeHandle", "(JL" PACKAGE_PATH "/NativeHandle;)V",
|
||||
(void*)JHwBlob_native_putNativeHandle },
|
||||
|
||||
{ "putBoolArray", "(J[Z)V", (void *)JHwBlob_native_putBoolArray },
|
||||
{ "putInt8Array", "(J[B)V", (void *)JHwBlob_native_putInt8Array },
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
namespace android {
|
||||
|
||||
struct JHwBlob : public RefBase {
|
||||
enum class BlobType {
|
||||
GENERIC,
|
||||
NATIVE_HANDLE,
|
||||
};
|
||||
|
||||
static void InitClass(JNIEnv *env);
|
||||
|
||||
static sp<JHwBlob> SetNativeContext(
|
||||
@@ -54,6 +59,9 @@ struct JHwBlob : public RefBase {
|
||||
|
||||
size_t size() const;
|
||||
|
||||
void specializeBlobTo(BlobType type);
|
||||
BlobType type() const;
|
||||
|
||||
status_t putBlob(size_t offset, const sp<JHwBlob> &blob);
|
||||
|
||||
status_t writeToParcel(hardware::Parcel *parcel) const;
|
||||
@@ -74,12 +82,15 @@ private:
|
||||
|
||||
void *mBuffer;
|
||||
size_t mSize;
|
||||
BlobType mType;
|
||||
bool mOwnsBuffer;
|
||||
|
||||
size_t mHandle;
|
||||
|
||||
Vector<BlobInfo> mSubBlobs;
|
||||
|
||||
status_t writeSubBlobsToParcel(hardware::Parcel *parcel, size_t parentHandle) const;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JHwBlob);
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "android_os_HwBinder.h"
|
||||
#include "android_os_HwBlob.h"
|
||||
#include "android_os_NativeHandle.h"
|
||||
#include "android_os_HwRemoteBinder.h"
|
||||
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
@@ -34,6 +35,7 @@
|
||||
|
||||
using android::AndroidRuntime;
|
||||
|
||||
using ::android::hardware::hidl_handle;
|
||||
using ::android::hardware::hidl_string;
|
||||
using ::android::hardware::hidl_vec;
|
||||
|
||||
@@ -436,6 +438,18 @@ static void JHwParcel_native_writeString(
|
||||
signalExceptionForError(env, err);
|
||||
}
|
||||
|
||||
static void JHwParcel_native_writeNativeHandle(JNIEnv *env, jobject thiz, jobject valObj) {
|
||||
sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
|
||||
|
||||
EphemeralStorage *storage = impl->getStorage();
|
||||
native_handle_t *handle = JNativeHandle::MakeCppNativeHandle(env, valObj, storage);
|
||||
|
||||
hardware::Parcel *parcel = impl->getParcel();
|
||||
status_t err = parcel->writeNativeHandleNoDup(handle);
|
||||
|
||||
signalExceptionForError(env, err);
|
||||
}
|
||||
|
||||
#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
|
||||
static void JHwParcel_native_write ## Suffix ## Vector( \
|
||||
JNIEnv *env, jobject thiz, Type ## Array valObj) { \
|
||||
@@ -524,12 +538,96 @@ static void JHwParcel_native_writeBoolVector(
|
||||
signalExceptionForError(env, err);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void WriteHidlVector(JNIEnv *env, jobject thiz, const hidl_vec<T> &vec) {
|
||||
hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
|
||||
|
||||
size_t parentHandle;
|
||||
status_t err = parcel->writeBuffer(&vec, sizeof(vec), &parentHandle);
|
||||
|
||||
if (err == OK) {
|
||||
size_t childHandle;
|
||||
err = ::android::hardware::writeEmbeddedToParcel(
|
||||
vec,
|
||||
parcel,
|
||||
parentHandle,
|
||||
0 /* parentOffset */,
|
||||
&childHandle);
|
||||
|
||||
for (size_t i = 0; (err == OK) && (i < vec.size()); ++i) {
|
||||
err = ::android::hardware::writeEmbeddedToParcel(
|
||||
vec[i],
|
||||
parcel,
|
||||
childHandle,
|
||||
i * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
signalExceptionForError(env, err);
|
||||
}
|
||||
|
||||
static void JHwParcel_native_writeStringVector(
|
||||
JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
|
||||
if (arrayObj == nullptr) {
|
||||
jniThrowException(env, "java/lang/NullPointerException", nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
|
||||
EphemeralStorage *storage = impl->getStorage();
|
||||
|
||||
void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_string>));
|
||||
hidl_vec<hidl_string> *vec = new (vecPtr) hidl_vec<hidl_string>();
|
||||
|
||||
jsize len = env->GetArrayLength(arrayObj);
|
||||
hidl_string *strings = storage->allocStringArray(len);
|
||||
vec->setToExternal(strings, len, false /* shouldOwn */);
|
||||
|
||||
for (jsize i = 0; i < len; ++i) {
|
||||
ScopedLocalRef<jstring> stringObj(env, (jstring) env->GetObjectArrayElement(arrayObj, i));
|
||||
|
||||
const hidl_string *s = storage->allocTemporaryString(env, stringObj.get());
|
||||
strings[i].setToExternal(s->c_str(), s->size());
|
||||
}
|
||||
|
||||
WriteHidlVector(env, thiz, *vec);
|
||||
}
|
||||
|
||||
static void JHwParcel_native_writeNativeHandleVector(
|
||||
JNIEnv *env, jobject thiz, jobjectArray jHandleArray) {
|
||||
if (jHandleArray == nullptr) {
|
||||
jniThrowException(env, "java/lang/NullPointerException", nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
|
||||
EphemeralStorage *storage = impl->getStorage();
|
||||
|
||||
void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_handle>));
|
||||
hidl_vec<hidl_handle> *vec = new (vecPtr) hidl_vec<hidl_handle>();
|
||||
|
||||
jsize len = env->GetArrayLength(jHandleArray);
|
||||
hidl_handle *handles = static_cast<hidl_handle *>(
|
||||
storage->allocTemporaryStorage(len * sizeof(hidl_handle)));
|
||||
|
||||
vec->setToExternal(handles, len, false /* shouldOwn */);
|
||||
for (jsize i = 0; i < len; i++) {
|
||||
ScopedLocalRef<jobject> jHandle(env, env->GetObjectArrayElement(jHandleArray, i));
|
||||
|
||||
native_handle_t* handle = JNativeHandle::MakeCppNativeHandle(env, jHandle.get(), storage);
|
||||
|
||||
new (&(handles[i])) hidl_handle();
|
||||
handles[i].setTo(handle, false /* shouldOwn */);
|
||||
}
|
||||
|
||||
WriteHidlVector(env, thiz, *vec);
|
||||
}
|
||||
|
||||
static void JHwParcel_native_writeStrongBinder(
|
||||
JNIEnv *env, jobject thiz, jobject binderObj) {
|
||||
sp<hardware::IBinder> binder;
|
||||
if (binderObj != NULL) {
|
||||
ScopedLocalRef<jclass> hwBinderKlass(
|
||||
env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
|
||||
ScopedLocalRef<jclass> hwBinderKlass(env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
|
||||
|
||||
ScopedLocalRef<jclass> hwRemoteBinderKlass(
|
||||
env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
|
||||
@@ -587,6 +685,37 @@ static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
|
||||
return MakeStringObjFromHidlString(env, *s);
|
||||
}
|
||||
|
||||
static jobject ReadNativeHandle(JNIEnv *env, jobject thiz, jboolean embedded,
|
||||
jlong parentHandle, jlong offset) {
|
||||
hardware::Parcel *parcel =
|
||||
JHwParcel::GetNativeContext(env, thiz)->getParcel();
|
||||
|
||||
const native_handle_t *handle = nullptr;
|
||||
status_t err = OK;
|
||||
|
||||
if (embedded) {
|
||||
err = parcel->readNullableEmbeddedNativeHandle(parentHandle, offset, &handle);
|
||||
} else {
|
||||
err = parcel->readNullableNativeHandleNoDup(&handle);
|
||||
}
|
||||
|
||||
if (err != OK) {
|
||||
signalExceptionForError(env, err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return JNativeHandle::MakeJavaNativeHandleObj(env, handle);
|
||||
}
|
||||
|
||||
static jobject JHwParcel_native_readNativeHandle(JNIEnv *env, jobject thiz) {
|
||||
return ReadNativeHandle(env, thiz, false /*embedded*/, 0L /*parentHandle*/, 0L /*offset*/);
|
||||
}
|
||||
|
||||
static jobject JHwParcel_native_readEmbeddedNativeHandle(
|
||||
JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
|
||||
return ReadNativeHandle(env, thiz, true /*embedded*/, parentHandle, offset);
|
||||
}
|
||||
|
||||
#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
|
||||
static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
|
||||
JNIEnv *env, jobject thiz) { \
|
||||
@@ -630,10 +759,8 @@ DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
|
||||
DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
|
||||
DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
|
||||
|
||||
static jbooleanArray JHwParcel_native_readBoolVector(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
hardware::Parcel *parcel =
|
||||
JHwParcel::GetNativeContext(env, thiz)->getParcel();
|
||||
static jbooleanArray JHwParcel_native_readBoolVector(JNIEnv *env, jobject thiz) {
|
||||
hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
|
||||
|
||||
size_t parentHandle;
|
||||
|
||||
@@ -692,101 +819,62 @@ static jobjectArray MakeStringArray(
|
||||
return arrayObj;
|
||||
}
|
||||
|
||||
static jobjectArray JHwParcel_native_readStringVector(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
typedef hidl_vec<hidl_string> string_vec;
|
||||
template<typename T>
|
||||
static const hidl_vec<T> *ReadHidlVector(JNIEnv *env, jobject thiz) {
|
||||
const hidl_vec<T> *vec;
|
||||
|
||||
hardware::Parcel *parcel =
|
||||
JHwParcel::GetNativeContext(env, thiz)->getParcel();
|
||||
hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
|
||||
|
||||
size_t parentHandle;
|
||||
|
||||
const string_vec *vec;
|
||||
status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
|
||||
reinterpret_cast<const void **>(&vec));
|
||||
|
||||
if (err != OK) {
|
||||
signalExceptionForError(env, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t childHandle;
|
||||
err = ::android::hardware::readEmbeddedFromParcel(
|
||||
const_cast<string_vec &>(*vec),
|
||||
*parcel, parentHandle, 0 /* parentOffset */, &childHandle);
|
||||
|
||||
for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
|
||||
err = android::hardware::readEmbeddedFromParcel(
|
||||
const_cast<hidl_string &>((*vec)[i]),
|
||||
*parcel,
|
||||
childHandle,
|
||||
i * sizeof(hidl_string) /* parentOffset */);
|
||||
}
|
||||
|
||||
if (err != OK) {
|
||||
signalExceptionForError(env, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return MakeStringArray(env, &(*vec)[0], vec->size());
|
||||
}
|
||||
|
||||
static void JHwParcel_native_writeStringVector(
|
||||
JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
|
||||
typedef hidl_vec<hidl_string> string_vec;
|
||||
|
||||
if (arrayObj == NULL) {
|
||||
jniThrowException(env, "java/lang/NullPointerException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
jsize len = env->GetArrayLength(arrayObj);
|
||||
|
||||
sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
|
||||
|
||||
void *vecPtr =
|
||||
impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
|
||||
|
||||
string_vec *vec = new (vecPtr) string_vec;
|
||||
|
||||
hidl_string *strings = impl->getStorage()->allocStringArray(len);
|
||||
vec->setToExternal(strings, len);
|
||||
|
||||
for (jsize i = 0; i < len; ++i) {
|
||||
ScopedLocalRef<jstring> stringObj(
|
||||
env,
|
||||
(jstring)env->GetObjectArrayElement(arrayObj, i));
|
||||
|
||||
const hidl_string *s =
|
||||
impl->getStorage()->allocTemporaryString(env, stringObj.get());
|
||||
|
||||
strings[i].setToExternal(s->c_str(), s->size());
|
||||
}
|
||||
|
||||
hardware::Parcel *parcel = impl->getParcel();
|
||||
|
||||
size_t parentHandle;
|
||||
status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
|
||||
status_t err = parcel->readBuffer(sizeof(hidl_vec<T>),
|
||||
&parentHandle, reinterpret_cast<const void **>(&vec));
|
||||
|
||||
if (err == OK) {
|
||||
size_t childHandle;
|
||||
err = ::android::hardware::writeEmbeddedToParcel(
|
||||
*vec,
|
||||
parcel,
|
||||
parentHandle,
|
||||
err = ::android::hardware::readEmbeddedFromParcel(
|
||||
const_cast<hidl_vec<T> &>(*vec),
|
||||
*parcel, parentHandle,
|
||||
0 /* parentOffset */,
|
||||
&childHandle);
|
||||
|
||||
for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
|
||||
err = ::android::hardware::writeEmbeddedToParcel(
|
||||
(*vec)[i],
|
||||
parcel,
|
||||
for (size_t i = 0; (err == OK) && (i < vec->size()); i++) {
|
||||
err = android::hardware::readEmbeddedFromParcel(
|
||||
const_cast<T &>((*vec)[i]),
|
||||
*parcel,
|
||||
childHandle,
|
||||
i * sizeof(hidl_string));
|
||||
i * sizeof(T) /* parentOffset */);
|
||||
}
|
||||
}
|
||||
|
||||
signalExceptionForError(env, err);
|
||||
if (err != OK) {
|
||||
signalExceptionForError(env, err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
static jobjectArray JHwParcel_native_readStringVector(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
const hidl_vec<hidl_string> *vec = ReadHidlVector<hidl_string>(env, thiz);
|
||||
return MakeStringArray(env, &(*vec)[0], vec->size());
|
||||
}
|
||||
|
||||
static jobjectArray JHwParcel_native_readNativeHandleVector(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
const hidl_vec<hidl_handle> *vec = ReadHidlVector<hidl_handle>(env, thiz);
|
||||
|
||||
jsize length = vec->size();
|
||||
jobjectArray objArray = JNativeHandle::AllocJavaNativeHandleObjArray(
|
||||
env, length);
|
||||
|
||||
for (jsize i = 0; i < length; i++) {
|
||||
jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, (*vec)[i].getNativeHandle());
|
||||
|
||||
env->SetObjectArrayElement(objArray, i, jHandle);
|
||||
}
|
||||
|
||||
return objArray;
|
||||
}
|
||||
|
||||
static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
|
||||
@@ -890,6 +978,9 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "writeString", "(Ljava/lang/String;)V",
|
||||
(void *)JHwParcel_native_writeString },
|
||||
|
||||
{ "writeNativeHandle", "(L" PACKAGE_PATH "/NativeHandle;)V",
|
||||
(void *)JHwParcel_native_writeNativeHandle },
|
||||
|
||||
{ "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
|
||||
{ "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
|
||||
{ "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
|
||||
@@ -903,6 +994,9 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "writeStringVector", "([Ljava/lang/String;)V",
|
||||
(void *)JHwParcel_native_writeStringVector },
|
||||
|
||||
{ "writeNativeHandleVector", "([L" PACKAGE_PATH "/NativeHandle;)V",
|
||||
(void *)JHwParcel_native_writeNativeHandleVector },
|
||||
|
||||
{ "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
|
||||
(void *)JHwParcel_native_writeStrongBinder },
|
||||
|
||||
@@ -920,6 +1014,12 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "readString", "()Ljava/lang/String;",
|
||||
(void *)JHwParcel_native_readString },
|
||||
|
||||
{ "readNativeHandle", "()L" PACKAGE_PATH "/NativeHandle;",
|
||||
(void *)JHwParcel_native_readNativeHandle },
|
||||
|
||||
{ "readEmbeddedNativeHandle", "(JJ)L" PACKAGE_PATH "/NativeHandle;",
|
||||
(void *)JHwParcel_native_readEmbeddedNativeHandle },
|
||||
|
||||
{ "readBoolVectorAsArray", "()[Z",
|
||||
(void *)JHwParcel_native_readBoolVector },
|
||||
|
||||
@@ -944,6 +1044,9 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "readStringVectorAsArray", "()[Ljava/lang/String;",
|
||||
(void *)JHwParcel_native_readStringVector },
|
||||
|
||||
{ "readNativeHandleAsArray", "()[L" PACKAGE_PATH "/NativeHandle;",
|
||||
(void *)JHwParcel_native_readNativeHandleVector },
|
||||
|
||||
{ "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
|
||||
(void *)JHwParcel_native_readStrongBinder },
|
||||
|
||||
|
||||
103
core/jni/android_os_NativeHandle.cpp
Normal file
103
core/jni/android_os_NativeHandle.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "android_os_NativeHandle.h"
|
||||
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include <nativehelper/ScopedLocalRef.h>
|
||||
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
#define PACKAGE_PATH "android/os"
|
||||
#define CLASS_NAME "NativeHandle"
|
||||
#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
|
||||
|
||||
namespace android {
|
||||
|
||||
static struct {
|
||||
jclass clazz;
|
||||
jmethodID constructID; // NativeHandle(int[] fds, int[] ints, boolean owns)
|
||||
|
||||
jmethodID getFdsID; // int[] NativeHandle.getFds()
|
||||
jmethodID getIntsID; // int[] NativeHandle.getInts()
|
||||
} gNativeHandleFields;
|
||||
|
||||
jobject JNativeHandle::MakeJavaNativeHandleObj(
|
||||
JNIEnv *env, const native_handle_t *handle) {
|
||||
if (handle == nullptr) { return nullptr; }
|
||||
|
||||
const int numFds = handle->numFds;
|
||||
ScopedLocalRef<jintArray> fds(env, env->NewIntArray(numFds));
|
||||
env->SetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0]));
|
||||
|
||||
const int numInts = handle->numInts;
|
||||
ScopedLocalRef<jintArray> ints(env, env->NewIntArray(numInts));
|
||||
env->SetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds]));
|
||||
|
||||
return env->NewObject(gNativeHandleFields.clazz,
|
||||
gNativeHandleFields.constructID, fds.get(), ints.get(), false /*own*/);
|
||||
}
|
||||
|
||||
native_handle_t *JNativeHandle::MakeCppNativeHandle(
|
||||
JNIEnv *env, jobject jHandle, EphemeralStorage *storage) {
|
||||
if (jHandle == nullptr) { return nullptr; }
|
||||
|
||||
if (!env->IsInstanceOf(jHandle, gNativeHandleFields.clazz)) {
|
||||
jniThrowException(env, "java/lang/ClassCastException",
|
||||
"jHandle must be an instance of NativeHandle.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedLocalRef<jintArray> fds(env, (jintArray) env->CallObjectMethod(
|
||||
jHandle, gNativeHandleFields.getFdsID));
|
||||
|
||||
ScopedLocalRef<jintArray> ints(env, (jintArray) env->CallObjectMethod(
|
||||
jHandle, gNativeHandleFields.getIntsID));
|
||||
|
||||
const int numFds = (int) env->GetArrayLength(fds.get());
|
||||
const int numInts = (int) env->GetArrayLength(ints.get());
|
||||
|
||||
native_handle_t *handle = (storage == nullptr)
|
||||
? native_handle_create(numFds, numInts)
|
||||
: storage->allocTemporaryNativeHandle(numFds, numInts);
|
||||
|
||||
if (handle != nullptr) {
|
||||
env->GetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0]));
|
||||
env->GetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds]));
|
||||
} else {
|
||||
jniThrowException(env, "java/lang/OutOfMemoryError",
|
||||
"Failed to allocate memory for native_handle_t.");
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
jobjectArray JNativeHandle::AllocJavaNativeHandleObjArray(JNIEnv *env, jsize length) {
|
||||
return env->NewObjectArray(length, gNativeHandleFields.clazz, nullptr);
|
||||
}
|
||||
|
||||
int register_android_os_NativeHandle(JNIEnv *env) {
|
||||
jclass clazz = FindClassOrDie(env, CLASS_PATH);
|
||||
gNativeHandleFields.clazz = MakeGlobalRefOrDie(env, clazz);
|
||||
|
||||
gNativeHandleFields.constructID = GetMethodIDOrDie(env, clazz, "<init>", "([I[IZ)V");
|
||||
gNativeHandleFields.getFdsID = GetMethodIDOrDie(env, clazz, "getFdsAsIntArray", "()[I");
|
||||
gNativeHandleFields.getIntsID = GetMethodIDOrDie(env, clazz, "getInts", "()[I");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
52
core/jni/android_os_NativeHandle.h
Normal file
52
core/jni/android_os_NativeHandle.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_OS_NATIVE_HANDLE_H
|
||||
#define ANDROID_OS_NATIVE_HANDLE_H
|
||||
|
||||
#include "hwbinder/EphemeralStorage.h"
|
||||
|
||||
#include <cutils/native_handle.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
struct JNativeHandle {
|
||||
|
||||
/**
|
||||
* Returns a Java NativeHandle object representing the parameterized
|
||||
* native_handle_t instance.
|
||||
*/
|
||||
static jobject MakeJavaNativeHandleObj(JNIEnv *env, const native_handle_t *handle);
|
||||
|
||||
/**
|
||||
* Returns a heap-allocated native_handle_t instance representing the
|
||||
* parameterized Java object. Note that if no valid EphemeralStorage*
|
||||
* parameter is supplied (storage is nullptr), the return value must
|
||||
* be explicitly deallocated (using native_handle_delete).
|
||||
*/
|
||||
static native_handle_t* MakeCppNativeHandle(JNIEnv *env, jobject jHandle,
|
||||
EphemeralStorage *storage);
|
||||
|
||||
/**
|
||||
* Returns an (uninitialized) array of Java NativeHandle objects.
|
||||
*/
|
||||
static jobjectArray AllocJavaNativeHandleObjArray(JNIEnv *env, jsize length);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ANDROID_OS_NATIVE_HANDLE_H
|
||||
@@ -71,6 +71,17 @@ const hidl_string *EphemeralStorage::allocTemporaryString(
|
||||
return s;
|
||||
}
|
||||
|
||||
native_handle_t *EphemeralStorage::allocTemporaryNativeHandle(
|
||||
int numFds, int numInts) {
|
||||
Item item;
|
||||
item.mType = TYPE_NATIVE_HANDLE;
|
||||
item.mObj = nullptr;
|
||||
item.mPtr = native_handle_create(numFds, numInts);
|
||||
mItems.push_back(item);
|
||||
|
||||
return static_cast<native_handle_t*>(item.mPtr);
|
||||
}
|
||||
|
||||
#define DEFINE_ALLOC_VECTOR_METHODS(Suffix,Type,NewType) \
|
||||
const hidl_vec<Type> *EphemeralStorage::allocTemporary ## Suffix ## Vector( \
|
||||
JNIEnv *env, Type ## Array arrayObj) { \
|
||||
@@ -145,6 +156,13 @@ void EphemeralStorage::release(JNIEnv *env) {
|
||||
DEFINE_RELEASE_ARRAY_CASE(Float,jfloat,Float)
|
||||
DEFINE_RELEASE_ARRAY_CASE(Double,jdouble,Double)
|
||||
|
||||
case TYPE_NATIVE_HANDLE:
|
||||
{
|
||||
int err = native_handle_delete(static_cast<native_handle_t *>(item.mPtr));
|
||||
CHECK(err == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
CHECK(!"Should not be here");
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ struct EphemeralStorage {
|
||||
const ::android::hardware::hidl_string *allocTemporaryString(
|
||||
JNIEnv *env, jstring stringObj);
|
||||
|
||||
native_handle_t *allocTemporaryNativeHandle(int numFds, int numInts);
|
||||
|
||||
DECLARE_ALLOC_METHODS(Int8,jbyte)
|
||||
DECLARE_ALLOC_METHODS(Int16,jshort)
|
||||
DECLARE_ALLOC_METHODS(Int32,jint)
|
||||
@@ -61,6 +63,7 @@ private:
|
||||
TYPE_Int64_ARRAY,
|
||||
TYPE_Float_ARRAY,
|
||||
TYPE_Double_ARRAY,
|
||||
TYPE_NATIVE_HANDLE,
|
||||
};
|
||||
|
||||
struct Item {
|
||||
|
||||
Reference in New Issue
Block a user