Merge "Move pgo rules to afdo"
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 7027a4b..6fb189c 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -739,6 +739,17 @@
     }
 }
 
+binder::Status Parcel::enforceNoDataAvail() const {
+    const auto n = dataAvail();
+    if (n == 0) {
+        return binder::Status::ok();
+    }
+    return binder::Status::
+            fromExceptionCode(binder::Status::Exception::EX_BAD_PARCELABLE,
+                              String8::format("Parcel data not fully consumed, unread size: %zu",
+                                              n));
+}
+
 size_t Parcel::objectsCount() const
 {
     return mObjectsSize;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 8dbdc1d..450e388 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -54,6 +54,9 @@
 class RpcSession;
 class String8;
 class TextOutput;
+namespace binder {
+class Status;
+}
 
 class Parcel {
     friend class IPCThreadState;
@@ -131,6 +134,10 @@
                                          IPCThreadState* threadState = nullptr) const;
     bool                checkInterface(IBinder*) const;
 
+    // Verify there are no bytes left to be read on the Parcel.
+    // Returns Status(EX_BAD_PARCELABLE) when the Parcel is not consumed.
+    binder::Status enforceNoDataAvail() const;
+
     void                freeData();
 
     size_t              objectsCount() const;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 6949c2c..28e3ff4 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -799,3 +799,12 @@
 void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) {
     binder->asABBinder()->setMinSchedulerPolicy(policy, priority);
 }
+
+void AIBinder_setInheritRt(AIBinder* binder, bool inheritRt) {
+    ABBinder* localBinder = binder->asABBinder();
+    if (localBinder == nullptr) {
+        LOG(FATAL) << "AIBinder_setInheritRt must be called on a local binder";
+    }
+
+    localBinder->setInheritRt(inheritRt);
+}
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index b0217c4..89f21dd 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -68,4 +68,16 @@
  */
 void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) __INTRODUCED_IN(33);
 
+/**
+ * Allow the binder to inherit realtime scheduling policies from its caller.
+ *
+ * This must be called before the object is sent to another process. Not thread
+ * safe.
+ *
+ * \param binder local server binder to set the policy for
+ * \param inheritRt whether to inherit realtime scheduling policies (default is
+ *     false).
+ */
+void AIBinder_setInheritRt(AIBinder* binder, bool inheritRt) __INTRODUCED_IN(33);
+
 __END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 197c0a1..3824a1b 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -146,6 +146,7 @@
     AIBinder_Class_disableInterfaceTokenHeader;
     AIBinder_DeathRecipient_setOnUnlinked;
     AIBinder_isHandlingTransaction;
+    AIBinder_setInheritRt; # llndk
     AIBinder_setMinSchedulerPolicy; # llndk
     AParcel_marshal;
     AParcel_unmarshal;
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 499f88e..58fa13a 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -505,6 +505,31 @@
     }
 };
 
+TEST(NdkBinder, SetInheritRt) {
+    // functional test in binderLibTest
+    sp<IFoo> foo = sp<MyTestFoo>::make();
+    AIBinder* binder = foo->getBinder();
+
+    // does not abort
+    AIBinder_setInheritRt(binder, true);
+    AIBinder_setInheritRt(binder, false);
+    AIBinder_setInheritRt(binder, true);
+
+    AIBinder_decStrong(binder);
+}
+
+TEST(NdkBinder, SetInheritRtNonLocal) {
+    AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+    ASSERT_NE(binder, nullptr);
+
+    ASSERT_TRUE(AIBinder_isRemote(binder));
+
+    EXPECT_DEATH(AIBinder_setInheritRt(binder, true), "");
+    EXPECT_DEATH(AIBinder_setInheritRt(binder, false), "");
+
+    AIBinder_decStrong(binder);
+}
+
 TEST(NdkBinder, AddNullService) {
     EXPECT_EQ(EX_ILLEGAL_ARGUMENT, AServiceManager_addService(nullptr, "any-service-name"));
 }
diff --git a/libs/binder/tests/binderParcelUnitTest.cpp b/libs/binder/tests/binderParcelUnitTest.cpp
index 4950b23..aee15d8 100644
--- a/libs/binder/tests/binderParcelUnitTest.cpp
+++ b/libs/binder/tests/binderParcelUnitTest.cpp
@@ -16,15 +16,17 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
+#include <binder/Status.h>
 #include <cutils/ashmem.h>
 #include <gtest/gtest.h>
 
 using android::IPCThreadState;
 using android::OK;
 using android::Parcel;
+using android::status_t;
 using android::String16;
 using android::String8;
-using android::status_t;
+using android::binder::Status;
 
 TEST(Parcel, NonNullTerminatedString8) {
     String8 kTestString = String8("test-is-good");
@@ -60,6 +62,19 @@
     EXPECT_EQ(output.size(), 0);
 }
 
+TEST(Parcel, EnforceNoDataAvail) {
+    const int32_t kTestInt = 42;
+    const String8 kTestString = String8("test-is-good");
+    Parcel p;
+    p.writeInt32(kTestInt);
+    p.writeString8(kTestString);
+    p.setDataPosition(0);
+    EXPECT_EQ(kTestInt, p.readInt32());
+    EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_BAD_PARCELABLE);
+    EXPECT_EQ(kTestString, p.readString8());
+    EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_NONE);
+}
+
 // Tests a second operation results in a parcel at the same location as it
 // started.
 void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) {
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 077d915..13f7195 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -22,6 +22,7 @@
 #include <android/os/IServiceManager.h>
 #include <binder/ParcelableHolder.h>
 #include <binder/PersistableBundle.h>
+#include <binder/Status.h>
 
 using ::android::status_t;
 using ::android::base::HexString;
@@ -100,6 +101,7 @@
     PARCEL_READ_NO_STATUS(size_t, dataAvail),
     PARCEL_READ_NO_STATUS(size_t, dataPosition),
     PARCEL_READ_NO_STATUS(size_t, dataCapacity),
+    PARCEL_READ_NO_STATUS(::android::binder::Status, enforceNoDataAvail),
     [] (const ::android::Parcel& p, uint8_t pos) {
         FUZZ_LOG() << "about to setDataPosition: " << pos;
         p.setDataPosition(pos);