diff options
| author | Steven Moreland <smoreland@google.com> | 2018-08-14 10:16:06 -0700 |
|---|---|---|
| committer | android-build-merger <android-build-merger@google.com> | 2018-08-14 10:16:06 -0700 |
| commit | bc600d328220cfa788e09df551c3053399841071 (patch) | |
| tree | dd1dba99a10bb5ec37931dd871ea2aa72803d2dc /core/java | |
| parent | 6e68dc711ea8f0ddacf45bc1ac7280401c908399 (diff) | |
| parent | 4a6566440f1af2ba7955aef527bfa4c183bd4a1b (diff) | |
Merge "Implementing support for HIDL native handles in Java" am: 1e1d8d2485 am: 6580802918
am: 4a6566440f
Change-Id: I649a10172d93beae9063ec2170e60aa4967ba0be
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/os/HwBlob.java | 8 | ||||
| -rw-r--r-- | core/java/android/os/HwParcel.java | 59 | ||||
| -rw-r--r-- | core/java/android/os/NativeHandle.java | 191 |
3 files changed, 258 insertions, 0 deletions
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java index 405651e992a3..6a5bb1c0a988 100644 --- a/core/java/android/os/HwBlob.java +++ b/core/java/android/os/HwBlob.java @@ -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. diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java index 0eb62c95ed71..7a51db2dc5f9 100644 --- a/core/java/android/os/HwParcel.java +++ b/core/java/android/os/HwParcel.java @@ -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. @@ -267,6 +279,14 @@ public class HwParcel { } /** + * 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. @@ -465,6 +515,15 @@ public class HwParcel { } /** + * 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 * @throws IllegalArgumentException if the parcel has no more data diff --git a/core/java/android/os/NativeHandle.java b/core/java/android/os/NativeHandle.java new file mode 100644 index 000000000000..f3dc5c8bc309 --- /dev/null +++ b/core/java/android/os/NativeHandle.java @@ -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; + } +} |
