Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a907efc3 authored by Ytai Ben-Tsvi's avatar Ytai Ben-Tsvi
Browse files

Add parceling support for HIDL memory in Java

This change adds support for reading/writing a HidlMemory
instance into / out of a HwParcel and HwBlob, in a format that
is compatible with the hidl_memory C++ type.
This paves the way to be able to exchange shared memory blocks
between native and Java via HwBinder, which will be exposed
as adding Java support for the HIDL 'memory' type.

Change-Id: I6cbbf852218c8a631f9014e7caa7a97d17e11889
Bug: 143566068
Merged-In: I6cbbf852218c8a631f9014e7caa7a97d17e11889
parent d87727f7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -816,11 +816,13 @@ java_library {
    srcs: [
        "core/java/android/os/HidlSupport.java",
        "core/java/android/annotation/IntDef.java",
        "core/java/android/annotation/IntRange.java",
        "core/java/android/annotation/NonNull.java",
        "core/java/android/annotation/Nullable.java",
        "core/java/android/annotation/SystemApi.java",
        "core/java/android/annotation/TestApi.java",
        "core/java/android/annotation/UnsupportedAppUsage.java",
        "core/java/android/os/HidlMemory.java",
        "core/java/android/os/HwBinder.java",
        "core/java/android/os/HwBlob.java",
        "core/java/android/os/HwParcel.java",
@@ -1358,8 +1360,10 @@ droidstubs {
    srcs: [
        "core/java/android/os/HidlSupport.java",
        "core/java/android/annotation/IntDef.java",
        "core/java/android/annotation/IntRange.java",
        "core/java/android/annotation/NonNull.java",
        "core/java/android/annotation/SystemApi.java",
        "core/java/android/os/HidlMemory.java",
        "core/java/android/os/HwBinder.java",
        "core/java/android/os/HwBlob.java",
        "core/java/android/os/HwParcel.java",
+16 −0
Original line number Diff line number Diff line
@@ -5219,6 +5219,17 @@ package android.os {
    method @NonNull public static java.io.File getVendorDirectory();
  }
  public class HidlMemory implements java.io.Closeable {
    ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle);
    method public void close() throws java.io.IOException;
    method @NonNull public android.os.HidlMemory dup() throws java.io.IOException;
    method protected void finalize();
    method @Nullable public android.os.NativeHandle getHandle();
    method @NonNull public String getName();
    method public long getSize();
    method @NonNull public android.os.NativeHandle releaseHandle();
  }
  public class HidlSupport {
    method public static boolean deepEquals(Object, Object);
    method public static int deepHashCode(Object);
@@ -5249,6 +5260,7 @@ package android.os {
    method public final void copyToInt8Array(long, byte[], int);
    method public final boolean getBool(long);
    method public final double getDouble(long);
    method public final long getFieldHandle(long);
    method public final float getFloat(long);
    method public final short getInt16(long);
    method public final int getInt32(long);
@@ -5263,6 +5275,7 @@ package android.os {
    method public final void putDoubleArray(long, double[]);
    method public final void putFloat(long, float);
    method public final void putFloatArray(long, float[]);
    method public final void putHidlMemory(long, @NonNull android.os.HidlMemory);
    method public final void putInt16(long, short);
    method public final void putInt16Array(long, short[]);
    method public final void putInt32(long, int);
@@ -5291,9 +5304,11 @@ 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 @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
    method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
    method public final float readFloat();
    method public final java.util.ArrayList<java.lang.Float> readFloatVector();
    method @NonNull public final android.os.HidlMemory readHidlMemory();
    method public final short readInt16();
    method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
    method public final int readInt32();
@@ -5318,6 +5333,7 @@ package android.os {
    method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
    method public final void writeFloat(float);
    method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
    method public final void writeHidlMemory(@NonNull android.os.HidlMemory);
    method public final void writeInt16(short);
    method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
    method public final void writeInt32(int);
+16 −0
Original line number Diff line number Diff line
@@ -1724,6 +1724,17 @@ package android.os {
    method public static boolean contains(java.io.File, java.io.File);
  }

  public class HidlMemory implements java.io.Closeable {
    ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle);
    method public void close() throws java.io.IOException;
    method @NonNull public android.os.HidlMemory dup() throws java.io.IOException;
    method protected void finalize();
    method @Nullable public android.os.NativeHandle getHandle();
    method @NonNull public String getName();
    method public long getSize();
    method @NonNull public android.os.NativeHandle releaseHandle();
  }

  public abstract class HwBinder implements android.os.IHwBinder {
    ctor public HwBinder();
    method public static final void configureRpcThreadpool(long, boolean);
@@ -1747,6 +1758,7 @@ package android.os {
    method public final void copyToInt8Array(long, byte[], int);
    method public final boolean getBool(long);
    method public final double getDouble(long);
    method public final long getFieldHandle(long);
    method public final float getFloat(long);
    method public final short getInt16(long);
    method public final int getInt32(long);
@@ -1761,6 +1773,7 @@ package android.os {
    method public final void putDoubleArray(long, double[]);
    method public final void putFloat(long, float);
    method public final void putFloatArray(long, float[]);
    method public final void putHidlMemory(long, @NonNull android.os.HidlMemory);
    method public final void putInt16(long, short);
    method public final void putInt16Array(long, short[]);
    method public final void putInt32(long, int);
@@ -1789,9 +1802,11 @@ 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 @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
    method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
    method public final float readFloat();
    method public final java.util.ArrayList<java.lang.Float> readFloatVector();
    method @NonNull public final android.os.HidlMemory readHidlMemory();
    method public final short readInt16();
    method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
    method public final int readInt32();
@@ -1816,6 +1831,7 @@ package android.os {
    method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
    method public final void writeFloat(float);
    method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
    method public final void writeHidlMemory(@NonNull android.os.HidlMemory);
    method public final void writeInt16(short);
    method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
    method public final void writeInt32(int);
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;

import java.io.Closeable;
import java.io.IOException;

/**
 * An abstract representation of a memory block, as representing by the HIDL system.
 *
 * The block is defined by a {name, size, handle} tuple, where the name is used to determine how to
 * interpret the handle. The underlying handle is assumed to be owned by this instance and will be
 * closed as soon as {@link #close()} is called on this instance, or this instance has been
 * finalized (the latter supports using it in a shared manner without having to worry about who owns
 * this instance, the former is more efficient resource-wise and is recommended for most use-cases).
 * Note, however, that ownership of the handle does not necessarily imply ownership of the
 * underlying file descriptors - the underlying handle may or may not own them. If you want the
 * underlying handle to outlive this instance, call {@link #releaseHandle()} to obtain the handle
 * and detach the ownership relationship.
 *
 * @hide
 */
@SystemApi
@TestApi
public class HidlMemory implements Closeable {
    private final @NonNull String mName;
    private final long mSize;
    private @Nullable NativeHandle mHandle;
    private long mNativeContext;  // For use of native code.

    /**
     * Constructor.
     *
     * @param name      The name of the IMapper service used to resolve the handle (e.g. "ashmem").
     * @param size      The (non-negative) size in bytes of the memory block.
     * @param handle    The handle. May be null. This instance will own the handle and will close it
     *                  as soon as {@link #close()} is called or the object is destroyed. This, this
     *                  handle instance should generally not be shared with other clients.
     */
    public HidlMemory(@NonNull String name, @IntRange(from = 0) long size,
            @Nullable NativeHandle handle) {
        mName = name;
        mSize = size;
        mHandle = handle;
    }

    /**
     * Create a copy of this instance, where the underlying handle (and its file descriptors) have
     * been duplicated.
     */
    @NonNull
    public HidlMemory dup() throws IOException {
        return new HidlMemory(mName, mSize, mHandle != null ? mHandle.dup() : null);
    }

    /**
     * Close the underlying native handle. No-op if handle is null or has been released using {@link
     * #releaseHandle()}.
     */
    @Override
    public void close() throws IOException {
        if (mHandle != null) {
            mHandle.close();
        }
    }

    /**
     * Disowns the underlying handle and returns it. This object becomes invalid.
     *
     * @return The underlying handle.
     */
    @NonNull
    public NativeHandle releaseHandle() {
        NativeHandle handle = mHandle;
        mHandle = null;
        return handle;
    }

    /**
     * Gets the name, which represents how the handle is to be interpreted.
     *
     * @return The name.
     */
    @NonNull
    public String getName() {
        return mName;
    }

    /**
     * Gets the size of the block, in bytes.
     *
     * @return The size.
     */
    public long getSize() {
        return mSize;
    }

    /**
     * Gets a native handle. The actual interpretation depends on the name and is implementation
     * defined.
     *
     * @return The native handle.
     */
    @Nullable
    public NativeHandle getHandle() {
        return mHandle;
    }

    @Override
    protected void finalize() {
        try {
            close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            nativeFinalize();
        }
    }

    private native void nativeFinalize();
}
+22 −0
Original line number Diff line number Diff line
@@ -92,6 +92,14 @@ public class HwBlob {
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final String getString(long offset);
    /**
     * For embedded fields that follow a two-step approach for reading, first obtain their field
     * handle using this method, and pass that field handle to the respective
     * HwParcel.readEmbedded*() method.
     * @param offset The field offset.
     * @return The field handle.
     */
    public native final long getFieldHandle(long offset);

    /**
     * Copy the blobs data starting from the given byte offset into the range, copying
@@ -311,6 +319,20 @@ public class HwBlob {
     */
    public native final void putBlob(long offset, HwBlob blob);

    /**
     * Writes a HidlMemory instance (without duplicating the underlying file descriptors) at an
     * offset.
     *
     * @param offset location to write value
     * @param mem    a {@link HidlMemory} instance to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range
     */
    public final void putHidlMemory(long offset, @NonNull HidlMemory mem) {
        putNativeHandle(offset + 0  /* offset of 'handle' field. */, mem.getHandle());
        putInt64(offset + 16  /* offset of 'size' field. */, mem.getSize());
        putString(offset + 24  /* offset of 'name' field. */, mem.getName());
    }

    /**
     * @return current handle of HwBlob for reference in a parcelled binder transaction
     */
Loading