describeContents() returns CONTENTS_FILE_DESCRIPTOR

Parcelable.describeContents() returns CONTENTS_FILE_DESCRIPTOR when the
contents hold a file descriptor.

Bug: 170677046
Test: aidl_unittests / aidl_integration_test
Change-Id: Idb06123def25c78f7e4ed5317e61ddee8ca39d5d
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 9dc2af0..16356ae 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -76,7 +76,7 @@
 p/Foo.aidl :
 )";
 
-const char kExpectedJavaParcelableOutputContests[] =
+const char kExpectedJavaParcelableOutputContents[] =
     R"(/*
  * This file is auto-generated.  DO NOT MODIFY.
  */
@@ -93,6 +93,8 @@
   public int y = 0;
 
   public android.os.ParcelFileDescriptor fd;
+
+  public java.util.List<android.os.ParcelFileDescriptor> fds;
   public static final android.os.Parcelable.Creator<Rect> CREATOR = new android.os.Parcelable.Creator<Rect>() {
     @Override
     public Rect createFromParcel(android.os.Parcel _aidl_source) {
@@ -140,6 +142,7 @@
         fd = null;
       }
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
     } finally {
       if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {
         throw new android.os.BadParcelableException("Overflow in the size of parcelable");
@@ -147,9 +150,12 @@
       _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
     }
   }
-  @Override public int describeContents()
-  {
-    return 0;
+  @Override
+  public int describeContents() {
+    int _mask = 0;
+    if (fd != null) _mask |= fd.describeContents();
+    if (fds != null) for (ParcelFileDescriptor _v0: fds) if (_v0 != null) _mask |= _v0.describeContents();
+    return _mask;
   }
 }
 )";
@@ -765,6 +771,7 @@
       "+ \"y\")\n"
       "  int y;\n"
       "  ParcelFileDescriptor fd;\n"
+      "  List<ParcelFileDescriptor> fds;\n"
       "}");
 
   vector<string> args{"aidl", "Rect.aidl"};
@@ -773,7 +780,7 @@
 
   string output;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("Rect.java", &output));
-  EXPECT_EQ(kExpectedJavaParcelableOutputContests, output);
+  EXPECT_EQ(kExpectedJavaParcelableOutputContents, output);
 }
 
 TEST_F(AidlTest, CppHeaderIncludes) {
@@ -2699,6 +2706,7 @@
 
 #include <a/ByteEnum.h>
 #include <binder/Parcel.h>
+#include <binder/ParcelFileDescriptor.h>
 #include <binder/Status.h>
 #include <cstdint>
 #include <type_traits>
@@ -2732,6 +2740,7 @@
   enum Tag : int32_t {
     ns = 0,  // int[] ns;
     e,  // a.ByteEnum e;
+    pfd,  // ParcelFileDescriptor pfd;
   };
 
   template<typename _Tp>
@@ -2789,7 +2798,7 @@
     return DESCIPTOR;
   }
 private:
-  std::variant<::std::vector<int32_t>, ::a::ByteEnum> _value;
+  std::variant<::std::vector<int32_t>, ::a::ByteEnum, ::android::os::ParcelFileDescriptor> _value;
 };  // class Foo
 
 }  // namespace a
@@ -2814,6 +2823,11 @@
     if ((_aidl_ret_status = _aidl_parcel->readByte(reinterpret_cast<int8_t *>(&_aidl_value))) != ::android::OK) return _aidl_ret_status;
     set<e>(std::move(_aidl_value));
     return ::android::OK; }
+  case pfd: {
+    ::android::os::ParcelFileDescriptor _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readParcelable(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    set<pfd>(std::move(_aidl_value));
+    return ::android::OK; }
   }
   return ::android::BAD_VALUE;
 }
@@ -2824,6 +2838,7 @@
   switch (getTag()) {
   case ns: return _aidl_parcel->writeInt32Vector(get<ns>());
   case e: return _aidl_parcel->writeByte(static_cast<int8_t>(get<e>()));
+  case pfd: return _aidl_parcel->writeParcelable(get<pfd>());
   }
   abort();
 }
@@ -2857,6 +2872,7 @@
   enum Tag : int32_t {
     ns = 0,  // int[] ns;
     e,  // a.ByteEnum e;
+    pfd,  // ParcelFileDescriptor pfd;
   };
 
   template<typename _Tp>
@@ -2911,7 +2927,7 @@
   binder_status_t writeToParcel(AParcel* _parcel) const;
   static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
 private:
-  std::variant<std::vector<int32_t>, ::aidl::a::ByteEnum> _value;
+  std::variant<std::vector<int32_t>, ::aidl::a::ByteEnum, ::ndk::ScopedFileDescriptor> _value;
 };
 }  // namespace a
 }  // namespace aidl
@@ -2940,6 +2956,11 @@
     if ((_aidl_ret_status = AParcel_readByte(_parcel, reinterpret_cast<int8_t*>(&_aidl_value))) != STATUS_OK) return _aidl_ret_status;
     set<e>(std::move(_aidl_value));
     return STATUS_OK; }
+  case pfd: {
+    ::ndk::ScopedFileDescriptor _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readRequiredParcelFileDescriptor(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    set<pfd>(std::move(_aidl_value));
+    return STATUS_OK; }
   }
   return STATUS_BAD_VALUE;
 }
@@ -2949,6 +2970,7 @@
   switch (getTag()) {
   case ns: return ::ndk::AParcel_writeVector(_parcel, get<ns>());
   case e: return AParcel_writeByte(_parcel, static_cast<int8_t>(get<e>()));
+  case pfd: return ::ndk::AParcel_writeRequiredParcelFileDescriptor(_parcel, get<pfd>());
   }
   abort();
 }
@@ -2967,6 +2989,7 @@
   // tags for union fields
   public final static int ns = 0;  // int[] ns;
   public final static int e = 1;  // a.ByteEnum e;
+  public final static int pfd = 2;  // ParcelFileDescriptor pfd;
 
   private int _tag;
   private Object _value;
@@ -3018,6 +3041,21 @@
     _set(e, _value);
   }
 
+  // ParcelFileDescriptor pfd;
+
+  public static Foo pfd(android.os.ParcelFileDescriptor _value) {
+    return new Foo(pfd, _value);
+  }
+
+  public android.os.ParcelFileDescriptor getPfd() {
+    _assertTag(pfd);
+    return (android.os.ParcelFileDescriptor) _value;
+  }
+
+  public void setPfd(android.os.ParcelFileDescriptor _value) {
+    _set(pfd, _value);
+  }
+
   public static final android.os.Parcelable.Creator<Foo> CREATOR = new android.os.Parcelable.Creator<Foo>() {
     @Override
     public Foo createFromParcel(android.os.Parcel _aidl_source) {
@@ -3039,6 +3077,15 @@
     case e:
       _aidl_parcel.writeByte(getE());
       break;
+    case pfd:
+      if ((getPfd()!=null)) {
+        _aidl_parcel.writeInt(1);
+        getPfd().writeToParcel(_aidl_parcel, 0);
+      }
+      else {
+        _aidl_parcel.writeInt(0);
+      }
+      break;
     }
   }
 
@@ -3056,13 +3103,29 @@
       _aidl_value = _aidl_parcel.readByte();
       _set(_aidl_tag, _aidl_value);
       return; }
+    case pfd: {
+      android.os.ParcelFileDescriptor _aidl_value;
+      if ((0!=_aidl_parcel.readInt())) {
+        _aidl_value = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(_aidl_parcel);
+      }
+      else {
+        _aidl_value = null;
+      }
+      _set(_aidl_tag, _aidl_value);
+      return; }
     }
     throw new RuntimeException("union: out of range: " + _aidl_tag);
   }
 
   @Override
   public int describeContents() {
-    return 0;
+    int _mask = 0;
+    switch (getTag()) {
+    case pfd:
+      if (getPfd() != null) _mask |= getPfd().describeContents();
+      break;
+    }
+    return _mask;
   }
 
   private void _assertTag(int tag) {
@@ -3075,6 +3138,7 @@
     switch (_tag) {
     case ns: return "ns";
     case e: return "e";
+    case pfd: return "pfd";
     }
     throw new IllegalStateException("unknown field: " + _tag);
   }
@@ -3094,6 +3158,7 @@
 union Foo {
   int[] ns = {42};
   ByteEnum  e;
+  ParcelFileDescriptor pfd;
 }
 )");
     io_delegate_.SetFileContents("a/ByteEnum.aidl", R"(