NativeHandle.java: set Nullable/NonNull

Fixes: 126700972
Test: hidl_test_java
Test: atest android.os.cts.HwBinderTest
Change-Id: Id45c6d0757913014028f7629db78b64f27cad084
diff --git a/Android.bp b/Android.bp
index b274552..a711fc6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1048,6 +1048,7 @@
         "core/java/android/os/HidlSupport.java",
         "core/java/android/annotation/IntDef.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/os/HwBinder.java",
diff --git a/api/system-current.txt b/api/system-current.txt
index 1f58de8..333d8be 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4100,7 +4100,7 @@
     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 putNativeHandle(long, @Nullable android.os.NativeHandle);
     method public final void putString(long, String);
     method public static Boolean[] wrapArray(@NonNull boolean[]);
     method public static Long[] wrapArray(@NonNull long[]);
@@ -4120,7 +4120,7 @@
     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 @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 public final short readInt16();
@@ -4131,8 +4131,8 @@
     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 @Nullable public final android.os.NativeHandle readNativeHandle();
+    method @NonNull public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
     method public final String readString();
     method public final java.util.ArrayList<java.lang.String> readStringVector();
     method public final android.os.IHwBinder readStrongBinder();
@@ -4156,8 +4156,8 @@
     method public final void writeInt8(byte);
     method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
     method public final void writeInterfaceToken(String);
-    method public final void writeNativeHandle(android.os.NativeHandle);
-    method public final void writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>);
+    method public final void writeNativeHandle(@Nullable android.os.NativeHandle);
+    method public final void writeNativeHandleVector(@NonNull java.util.ArrayList<android.os.NativeHandle>);
     method public final void writeStatus(int);
     method public final void writeString(String);
     method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
@@ -4207,10 +4207,10 @@
     ctor public NativeHandle(@NonNull java.io.FileDescriptor, boolean);
     ctor public NativeHandle(@NonNull java.io.FileDescriptor[], @NonNull 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 @NonNull public android.os.NativeHandle dup() throws java.io.IOException;
+    method @NonNull public java.io.FileDescriptor getFileDescriptor();
+    method @NonNull public java.io.FileDescriptor[] getFileDescriptors();
+    method @NonNull public int[] getInts();
     method public boolean hasSingleFileDescriptor();
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 2300906..6038e30 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -995,7 +995,7 @@
     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 putNativeHandle(long, @Nullable android.os.NativeHandle);
     method public final void putString(long, String);
     method public static Boolean[] wrapArray(@NonNull boolean[]);
     method public static Long[] wrapArray(@NonNull long[]);
@@ -1015,7 +1015,7 @@
     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 @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 public final short readInt16();
@@ -1026,8 +1026,8 @@
     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 @Nullable public final android.os.NativeHandle readNativeHandle();
+    method @NonNull public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
     method public final String readString();
     method public final java.util.ArrayList<java.lang.String> readStringVector();
     method public final android.os.IHwBinder readStrongBinder();
@@ -1051,8 +1051,8 @@
     method public final void writeInt8(byte);
     method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
     method public final void writeInterfaceToken(String);
-    method public final void writeNativeHandle(android.os.NativeHandle);
-    method public final void writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>);
+    method public final void writeNativeHandle(@Nullable android.os.NativeHandle);
+    method public final void writeNativeHandleVector(@NonNull java.util.ArrayList<android.os.NativeHandle>);
     method public final void writeStatus(int);
     method public final void writeString(String);
     method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
@@ -1102,10 +1102,10 @@
     ctor public NativeHandle(@NonNull java.io.FileDescriptor, boolean);
     ctor public NativeHandle(@NonNull java.io.FileDescriptor[], @NonNull 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 @NonNull public android.os.NativeHandle dup() throws java.io.IOException;
+    method @NonNull public java.io.FileDescriptor getFileDescriptor();
+    method @NonNull public java.io.FileDescriptor[] getFileDescriptors();
+    method @NonNull public int[] getInts();
     method public boolean hasSingleFileDescriptor();
   }
 
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 0ec63b5..2c453bf 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 
@@ -241,7 +242,7 @@
      * @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);
+    public native final void putNativeHandle(long offset, @Nullable 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 7919a00..dc640c9 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -17,6 +17,8 @@
 package android.os;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 
@@ -123,7 +125,7 @@
      *
      * @param val to write
      */
-    public native final void writeNativeHandle(NativeHandle val);
+    public native final void writeNativeHandle(@Nullable NativeHandle val);
 
     /**
      * Writes an array of boolean values to the end of the parcel.
@@ -170,6 +172,9 @@
     private native final void writeStringVector(String[] val);
     /**
      * Writes an array of native handles to the end of the parcel.
+     *
+     * Individual elements may be null but not the whole array.
+     *
      * @param val array of {@link NativeHandle} objects to write
      */
     private native final void writeNativeHandleVector(NativeHandle[] val);
@@ -284,7 +289,7 @@
      * 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) {
+    public final void writeNativeHandleVector(@NonNull ArrayList<NativeHandle> val) {
         writeNativeHandleVector(val.toArray(new NativeHandle[val.size()]));
     }
 
@@ -359,7 +364,7 @@
      * @return a {@link NativeHandle} instance parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
-    public native final NativeHandle readNativeHandle();
+    public native final @Nullable NativeHandle readNativeHandle();
     /**
      * Reads an embedded native handle (without duplicating the underlying
      * file descriptors) from the parcel. These file descriptors will only
@@ -372,7 +377,7 @@
      * @return a {@link NativeHandle} instance parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
-    public native final NativeHandle readEmbeddedNativeHandle(
+    public native final @Nullable NativeHandle readEmbeddedNativeHandle(
             long parentHandle, long offset);
 
     /**
@@ -521,7 +526,7 @@
      * @return array of {@link NativeHandle} objects.
      * @throws IllegalArgumentException if the parcel has no more data
      */
-    public final ArrayList<NativeHandle> readNativeHandleVector() {
+    public final @NonNull ArrayList<NativeHandle> readNativeHandleVector() {
         return new ArrayList<NativeHandle>(Arrays.asList(readNativeHandleAsArray()));
     }
 
diff --git a/core/java/android/os/NativeHandle.java b/core/java/android/os/NativeHandle.java
index f13bf5f..8d341b6 100644
--- a/core/java/android/os/NativeHandle.java
+++ b/core/java/android/os/NativeHandle.java
@@ -99,6 +99,8 @@
      * @return a boolean value
      */
     public boolean hasSingleFileDescriptor() {
+        checkOpen();
+
         return mFds.length == 1 && mInts.length == 0;
     }
 
@@ -108,7 +110,7 @@
      * If this method is called, this must also be explicitly closed with
      * {@link #close()}.
      */
-    public NativeHandle dup() throws java.io.IOException {
+    public @NonNull NativeHandle dup() throws java.io.IOException {
         FileDescriptor[] fds = new FileDescriptor[mFds.length];
         try {
             for (int i = 0; i < mFds.length; i++) {
@@ -123,6 +125,12 @@
         return new NativeHandle(fds, mInts, true /*own*/);
     }
 
+    private void checkOpen() {
+        if (mFds == null) {
+            throw new IllegalStateException("NativeHandle is invalidated after close.");
+        }
+    }
+
     /**
      * Closes the file descriptors if they are owned by this object.
      *
@@ -130,19 +138,20 @@
      */
     @Override
     public void close() throws java.io.IOException {
-        if (!mOwn) {
-            return;
-        }
+        checkOpen();
 
-        try {
-            for (FileDescriptor fd : mFds) {
-                Os.close(fd);
+        if (mOwn) {
+            try {
+                for (FileDescriptor fd : mFds) {
+                    Os.close(fd);
+                }
+            } catch (ErrnoException e) {
+                e.rethrowAsIOException();
             }
-        } catch (ErrnoException e) {
-            e.rethrowAsIOException();
+
+            mOwn = false;
         }
 
-        mOwn = false;
         mFds = null;
         mInts = null;
     }
@@ -154,7 +163,9 @@
      * @throws IllegalStateException if this object contains either zero or
      *         more than one file descriptor, or a non-empty data stream.
      */
-    public FileDescriptor getFileDescriptor() {
+    public @NonNull FileDescriptor getFileDescriptor() {
+        checkOpen();
+
         if (!hasSingleFileDescriptor()) {
             throw new IllegalStateException(
                     "NativeHandle is not single file descriptor. Contents must"
@@ -171,6 +182,8 @@
      * @hide
      */
     private int[] getFdsAsIntArray() {
+        checkOpen();
+
         int numFds = mFds.length;
         int[] fds = new int[numFds];
 
@@ -182,11 +195,13 @@
     }
 
     /**
-     * Fetch file descriptors.
+     * Fetch file descriptors
      *
      * @return the fds.
      */
-    public FileDescriptor[] getFileDescriptors() {
+    public @NonNull FileDescriptor[] getFileDescriptors() {
+        checkOpen();
+
         return mFds;
     }
 
@@ -195,7 +210,9 @@
      *
      * @return the opaque data stream.
      */
-    public int[] getInts() {
+    public @NonNull int[] getInts() {
+        checkOpen();
+
         return mInts;
     }
 }