Merge "installd_dexopt_test: fix close of owned file descriptor."
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 985d817..9e55c2c 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -124,7 +124,6 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     data.setDataPosition(0);
-    data.setTransactingBinder(this);
 
     status_t err = NO_ERROR;
     switch (code) {
@@ -139,7 +138,6 @@
     // In case this is being transacted on in the same process.
     if (reply != nullptr) {
         reply->setDataPosition(0);
-        reply->setTransactingBinder(this);
     }
 
     return err;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 57440d5..425ece3 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -21,6 +21,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/IResultReceiver.h>
+#include <binder/Stability.h>
 #include <cutils/compiler.h>
 #include <utils/Log.h>
 
@@ -213,14 +214,22 @@
 {
     // Once a binder has died, it will never come back to life.
     if (mAlive) {
+        // user transactions require a given stability level
+        // Cannot add requirement w/o SM update
+        // if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
+        //     using android::internal::Stability;
+
+        //     auto stability = Stability::get(this);
+
+        //     if (CC_UNLIKELY(!Stability::check(stability, Stability::kLocalStability))) {
+        //         return BAD_TYPE;
+        //     }
+        // }
+
         status_t status = IPCThreadState::self()->transact(
             mHandle, code, data, reply, flags);
         if (status == DEAD_OBJECT) mAlive = 0;
 
-        if (reply != nullptr) {
-            reply->setTransactingBinder(this);
-        }
-
         return status;
     }
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index a2333ae..c75f036 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -35,6 +35,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
+#include <binder/Stability.h>
 #include <binder/Status.h>
 #include <binder/TextOutput.h>
 
@@ -167,11 +168,10 @@
 status_t Parcel::finishFlattenBinder(
     const sp<IBinder>& /*binder*/, const flat_binder_object& flat)
 {
-    // internal::Stability::tryMarkCompilationUnit(binder.get());
-
     status_t status = writeObject(flat, false);
     if (status != OK) return status;
 
+    // internal::Stability::tryMarkCompilationUnit(binder.get());
     // Cannot change wire protocol w/o SM update
     // return writeInt32(internal::Stability::get(binder.get()));
     return OK;
@@ -185,10 +185,6 @@
     // status_t status = readInt32(&stability);
     // if (status != OK) return status;
 
-    // if (binder != nullptr && !internal::Stability::check(stability, mRequiredStability)) {
-    //     return BAD_TYPE;
-    // }
-
     // status = internal::Stability::set(binder.get(), stability, true /*log*/);
     // if (status != OK) return status;
 
@@ -356,10 +352,6 @@
     return NO_ERROR;
 }
 
-void Parcel::setTransactingBinder(const sp<IBinder>& binder) const {
-    mRequiredStability = internal::Stability::get(binder.get());
-}
-
 status_t Parcel::setData(const uint8_t* buffer, size_t len)
 {
     if (len > INT32_MAX) {
@@ -2615,10 +2607,9 @@
     mObjectsCapacity = 0;
     mNextObjectHint = 0;
     mObjectsSorted = false;
-    mAllowFds = true;
     mHasFds = false;
     mFdsKnown = true;
-    mRequiredStability = internal::Stability::UNDECLARED;
+    mAllowFds = true;
     mOwner = nullptr;
     mOpenAshmemSize = 0;
 
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 1e1bc3a..07db50f 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -21,6 +21,7 @@
 #include <binder/BpBinder.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/Stability.h>
 #include <cutils/atomic.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -109,7 +110,13 @@
 
 sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
 {
-    return getStrongProxyForHandle(0);
+    sp<IBinder> context = getStrongProxyForHandle(0);
+
+    // The root object is special since we get it directly from the driver, it is never
+    // written by Parcell::writeStrongBinder.
+    internal::Stability::tryMarkCompilationUnit(context.get());
+
+    return context;
 }
 
 void ProcessState::startThreadPool()
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 0a10a1d..b6f10c8 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -32,6 +32,11 @@
     ALOGE("%s: stability is %s", tag.c_str(), stabilityString(get(binder.get())).c_str());
 }
 
+void Stability::markVndk(IBinder* binder) {
+    status_t result = set(binder, Level::VENDOR, true /*log*/);
+    LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
+}
+
 void Stability::tryMarkCompilationUnit(IBinder* binder) {
     (void) set(binder, kLocalStability, false /*log*/);
 }
@@ -95,9 +100,9 @@
     }
 
     if (!stable) {
-        ALOGE("Interface with %s cannot accept interface with %s.",
-            stabilityString(required).c_str(),
-            stabilityString(provided).c_str());
+        ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
+            stabilityString(provided).c_str(),
+            stabilityString(required).c_str());
     }
 
     return stable;
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 1537e69..dec75f5 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -38,7 +38,7 @@
     virtual status_t    transact(   uint32_t code,
                                     const Parcel& data,
                                     Parcel* reply,
-                                    uint32_t flags = 0);
+                                    uint32_t flags = 0) final;
 
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index e71541b..28599f4 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -45,7 +45,7 @@
     virtual status_t    transact(   uint32_t code,
                                     const Parcel& data,
                                     Parcel* reply,
-                                    uint32_t flags = 0);
+                                    uint32_t flags = 0) final;
 
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index a0a91d7..c8f82a3 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -33,7 +33,6 @@
 
 #include <binder/IInterface.h>
 #include <binder/Parcelable.h>
-#include <binder/Stability.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -69,8 +68,6 @@
     void                setDataPosition(size_t pos) const;
     status_t            setDataCapacity(size_t size);
 
-    void                setTransactingBinder(const sp<IBinder>& binder) const;
-
     status_t            setData(const uint8_t* buffer, size_t len);
 
     status_t            appendFrom(const Parcel *parcel,
@@ -464,12 +461,10 @@
     size_t              mObjectsCapacity;
     mutable size_t      mNextObjectHint;
     mutable bool        mObjectsSorted;
-    bool                mAllowFds;
 
     mutable bool        mFdsKnown;
     mutable bool        mHasFds;
-
-    mutable internal::Stability::Level mRequiredStability;
+    bool                mAllowFds;
 
     release_func        mOwner;
     void*               mOwnerCookie;
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 9d98c7f..f8240e4 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -20,6 +20,10 @@
 #include <string>
 
 namespace android {
+
+class BpBinder;
+class ProcessState;
+
 namespace internal {
 
 // WARNING: These APIs are only ever expected to be called by auto-generated code.
@@ -43,14 +47,30 @@
     // WARNING: for debugging only
     static void debugLogStability(const std::string& tag, const sp<IBinder>& binder);
 
+    // WARNING: This is only ever expected to be called by auto-generated code or tests.
+    // You likely want to change or modify the stability of the interface you are using.
+    // This must be called as soon as the binder in question is constructed. No thread safety
+    // is provided.
+    // E.g. stability is according to libbinder_ndk or Java SDK AND the interface
+    //     expressed here is guaranteed to be stable for multiple years (Stable AIDL)
+    // If this is called when __ANDROID_VNDK__ is not defined, then it is UB and will likely
+    // break the device during GSI or other tests.
+    static void markVndk(IBinder* binder);
+
 private:
-    // Parcel needs to store stability level since this is more efficient than storing and looking
-    // up the efficiency level of a binder object. So, we expose the underlying type.
+    // Parcel needs to read/write stability level in an unstable format.
     friend ::android::Parcel;
 
+    // only expose internal APIs inside of libbinder, for checking stability
+    friend ::android::BpBinder;
+
+    // so that it can mark the context object (only the root object doesn't go
+    // through Parcel)
+    friend ::android::ProcessState;
+
     static void tryMarkCompilationUnit(IBinder* binder);
 
-    enum Level : int16_t {
+    enum Level : int32_t {
         UNDECLARED = 0,
 
         VENDOR = 0b000011,
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 6da3086..734a928 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-cc_library {
+cc_library_shared {
     name: "libbinder_ndk",
 
     export_include_dirs: [
         "include_ndk",
-        "include_apex",
+        "include_platform",
     ],
 
     cflags: [
@@ -33,6 +33,7 @@
         "ibinder_jni.cpp",
         "parcel.cpp",
         "process.cpp",
+        "stability.cpp",
         "status.cpp",
         "service_manager.cpp",
     ],
@@ -54,7 +55,7 @@
     version_script: "libbinder_ndk.map.txt",
     stubs: {
         symbol_file: "libbinder_ndk.map.txt",
-        versions: ["29"],
+        versions: ["29", "30"],
     },
 }
 
@@ -79,6 +80,6 @@
     symbol_file: "libbinder_ndk.map.txt",
     export_include_dirs: [
         "include_ndk",
-        "include_apex",
+        "include_platform",
     ],
 }
diff --git a/libs/binder/ndk/include_apex/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
similarity index 100%
rename from libs/binder/ndk/include_apex/android/binder_manager.h
rename to libs/binder/ndk/include_platform/android/binder_manager.h
diff --git a/libs/binder/ndk/include_apex/android/binder_process.h b/libs/binder/ndk/include_platform/android/binder_process.h
similarity index 100%
rename from libs/binder/ndk/include_apex/android/binder_process.h
rename to libs/binder/ndk/include_platform/android/binder_process.h
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
new file mode 100644
index 0000000..e6aeb04
--- /dev/null
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+
+__BEGIN_DECLS
+
+#ifdef __ANDROID_VNDK__
+
+/**
+ * This interface has the stability of the vendor image.
+ */
+void AIBinder_markVendorStability(AIBinder* binder);
+
+static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
+    AIBinder_markVendorStability(binder);
+}
+
+#else  // ndef defined __ANDROID_VNDK__
+
+/**
+ * This interface has the stability of the system image.
+ */
+void AIBinder_markSystemStability(AIBinder* binder);
+
+static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
+    AIBinder_markSystemStability(binder);
+}
+
+#endif  // ifdef __ANDROID_VNDK__
+
+/**
+ * This interface has system<->vendor stability
+ */
+void AIBinder_markVintfStability(AIBinder* binder);
+
+__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 4f685d1..feedde6 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -98,3 +98,12 @@
   local:
     *;
 };
+
+LIBBINDER_NDK30 { # introduced=30
+  global:
+    AIBinder_markSystemStability; # apex
+    AIBinder_markVendorStability; # vndk
+    AIBinder_markVintfStability; # apex vndk
+  local:
+    *;
+};
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
new file mode 100644
index 0000000..a5b3ece
--- /dev/null
+++ b/libs/binder/ndk/stability.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_stability.h>
+
+#include <binder/Stability.h>
+#include "ibinder_internal.h"
+
+#include <log/log.h>
+
+using ::android::internal::Stability;
+
+#ifdef __ANDROID_VNDK__
+#error libbinder_ndk should only be built in a system context
+#endif
+
+#ifdef __ANDROID_NDK__
+#error libbinder_ndk should only be built in a system context
+#endif
+
+// explicit extern because symbol is only declared in header when __ANDROID_VNDK__
+extern "C" void AIBinder_markVendorStability(AIBinder* binder) {
+    Stability::markVndk(binder->getBinder().get());
+}
+
+void AIBinder_markSystemStability(AIBinder* binder) {
+    Stability::markCompilationUnit(binder->getBinder().get());
+}
+
+void AIBinder_markVintfStability(AIBinder* binder) {
+    Stability::markVintf(binder->getBinder().get());
+}
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index 8cd4e03..bb1fe2f 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -44,10 +44,10 @@
         "libandroid_runtime_lazy",
         "libbase",
         "libbinder",
+        "libbinder_ndk",
         "libutils",
     ],
     static_libs: [
-        "libbinder_ndk",
         "test_libbinder_ndk_library",
     ],
 }
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 05db81e..bc457ce 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -138,17 +138,30 @@
     test_suites: ["device-tests"],
 }
 
+aidl_interface {
+    name: "binderStabilityTestIface",
+    srcs: [
+        "IBinderStabilityTest.aidl",
+    ],
+}
+
 cc_test {
     name: "binderStabilityTest",
     defaults: ["binder_test_defaults"],
     srcs: [
         "binderStabilityTest.cpp",
-        "IBinderStabilityTest.aidl",
     ],
 
     shared_libs: [
+        "libbinder_ndk",
         "libbinder",
+        "liblog",
         "libutils",
     ],
+    static_libs: [
+        "binderStabilityTestIface-cpp",
+        "binderStabilityTestIface-ndk_platform",
+    ],
+
     test_suites: ["device-tests"],
 }
diff --git a/libs/binder/tests/IBinderStabilityTest.aidl b/libs/binder/tests/IBinderStabilityTest.aidl
index 7540ec9..36e1c2c 100644
--- a/libs/binder/tests/IBinderStabilityTest.aidl
+++ b/libs/binder/tests/IBinderStabilityTest.aidl
@@ -23,6 +23,10 @@
 
     // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
     // THIS IS ONLY FOR TESTING!
+    void sendAndCallBinder(IBinder binder);
+
+    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+    // THIS IS ONLY FOR TESTING!
     IBinder returnNoStabilityBinder();
 
     // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
@@ -32,6 +36,10 @@
     // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
     // THIS IS ONLY FOR TESTING!
     IBinder returnVintfStabilityBinder();
+
+    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+    // THIS IS ONLY FOR TESTING!
+    IBinder returnVendorStabilityBinder();
 }
 // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
 // THIS IS ONLY FOR TESTING!
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index d8159e3..490850e 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <android/binder_manager.h>
+#include <android/binder_stability.h>
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
 #include <binder/IPCThreadState.h>
@@ -24,154 +26,225 @@
 
 #include <sys/prctl.h>
 
+#include "aidl/BnBinderStabilityTest.h"
 #include "BnBinderStabilityTest.h"
-#include "BpBinderStabilityTest.h"
 
 using namespace android;
+using namespace ndk;
 using android::binder::Status;
+using android::internal::Stability; // for testing only!
 
-const String16 kNoStabilityServer = String16("binder_stability_test_service_low");
-const String16 kCompilationUnitServer = String16("binder_stability_test_service_compl");
-const String16 kVintfServer = String16("binder_stability_test_service_vintf");
+const String16 kSystemStabilityServer = String16("binder_stability_test_service_system");
 
-sp<IBinder> getCompilationUnitStability() {
-    sp<IBinder> binder = new BBinder();
-    // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
-    // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
-    internal::Stability::markCompilationUnit(binder.get()); // <- BAD, NO! DO NOT COPY
-    return binder;
-}
+// This is handwritten so that we can test different stability levels w/o having the AIDL
+// compiler assign them. Hand-writing binder interfaces is considered a bad practice
+// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
+class BadStableBinder : public BBinder {
+public:
+    static constexpr uint32_t USER_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION;
+    static String16 kDescriptor;
 
-sp<IBinder> getVintfStability() {
-    sp<IBinder> binder = new BBinder();
-    // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
-    // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
-    internal::Stability::markVintf(binder.get()); // <- BAD, NO! DO NOT COPY
-    return binder;
-}
+    bool gotUserTransaction = false;
+
+    static status_t doUserTransaction(const sp<IBinder>& binder) {
+        Parcel data, reply;
+        data.writeInterfaceToken(kDescriptor);
+        return binder->transact(USER_TRANSACTION, data, &reply, 0/*flags*/);
+    }
+
+    status_t onTransact(uint32_t code,
+            const Parcel& data, Parcel* reply, uint32_t flags) override {
+        if (code == USER_TRANSACTION) {
+            // not interested in this kind of stability. Make sure
+            // we have a test failure
+            LOG_ALWAYS_FATAL_IF(!data.enforceInterface(kDescriptor));
+
+            gotUserTransaction = true;
+
+            ALOGE("binder stability: Got user transaction");
+            return OK;
+        }
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+
+    static sp<BadStableBinder> undef() {
+        sp<BadStableBinder> iface = new BadStableBinder();
+        return iface;
+    }
+
+    static sp<BadStableBinder> system() {
+        sp<BadStableBinder> iface = new BadStableBinder();
+        Stability::markCompilationUnit(iface.get()); // <- for test only
+        return iface;
+    }
+
+    static sp<BadStableBinder> vintf() {
+        sp<BadStableBinder> iface = new BadStableBinder();
+        Stability::markVintf(iface.get()); // <- for test only
+        return iface;
+    }
+
+    static sp<BadStableBinder> vendor() {
+        sp<BadStableBinder> iface = new BadStableBinder();
+        Stability::markVndk(iface.get()); // <- for test only
+        return iface;
+    }
+};
+String16 BadStableBinder::kDescriptor = String16("BadStableBinder.test");
 
 // NO! NO! NO! Do not even think of doing something like this!
 // This is for testing! If a class like this was actually used in production,
 // it would ruin everything!
-class BadStabilityTester : public BnBinderStabilityTest {
+class MyBinderStabilityTest : public BnBinderStabilityTest {
 public:
     Status sendBinder(const sp<IBinder>& /*binder*/) override {
         return Status::ok();
     }
+    Status sendAndCallBinder(const sp<IBinder>& binder) override {
+        Stability::debugLogStability("sendAndCallBinder got binder", binder);
+        return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder));
+    }
     Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override {
-        *_aidl_return = new BBinder();
+        *_aidl_return = BadStableBinder::undef();
         return Status::ok();
     }
     Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override {
-        *_aidl_return = getCompilationUnitStability();
+        *_aidl_return = BadStableBinder::system();
         return Status::ok();
     }
     Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override {
-        *_aidl_return = getVintfStability();
+        *_aidl_return = BadStableBinder::vintf();
         return Status::ok();
     }
-
-    static sp<IBinderStabilityTest> getNoStabilityServer() {
-        sp<IBinder> remote = new BadStabilityTester;
-        return new BpBinderStabilityTest(remote);
-    }
-    static sp<IBinderStabilityTest> getCompilationUnitStabilityServer() {
-        sp<IBinder> remote = new BadStabilityTester;
-        internal::Stability::markCompilationUnit(remote.get());
-        return new BpBinderStabilityTest(remote);
-    }
-    static sp<IBinderStabilityTest> getVintfStabilityServer() {
-        sp<IBinder> remote = new BadStabilityTester;
-        internal::Stability::markVintf(remote.get()); // <- BAD, NO! DO NOT COPY
-        return new BpBinderStabilityTest(remote);
+    Status returnVendorStabilityBinder(sp<IBinder>* _aidl_return) override {
+        *_aidl_return = BadStableBinder::vendor();
+        return Status::ok();
     }
 };
 
-void checkLocalStabilityBinder(const sp<IBinderStabilityTest>& complServer) {
-    // this binder should automatically be set to local stability
-    EXPECT_TRUE(complServer->sendBinder(new BBinder()).isOk());
-    EXPECT_TRUE(complServer->sendBinder(getCompilationUnitStability()).isOk());
-    EXPECT_TRUE(complServer->sendBinder(getVintfStability()).isOk());
+TEST(BinderStability, CantCallVendorBinderInSystemContext) {
+    sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
+    auto server = interface_cast<IBinderStabilityTest>(serverBinder);
+
+    ASSERT_NE(nullptr, server.get());
+    ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder());
+
+    EXPECT_TRUE(server->sendBinder(BadStableBinder::undef()).isOk());
+    EXPECT_TRUE(server->sendBinder(BadStableBinder::system()).isOk());
+    EXPECT_TRUE(server->sendBinder(BadStableBinder::vintf()).isOk());
+    EXPECT_TRUE(server->sendBinder(BadStableBinder::vendor()).isOk());
+
+    {
+        sp<BadStableBinder> binder = BadStableBinder::undef();
+        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+        EXPECT_TRUE(binder->gotUserTransaction);
+    }
+    {
+        sp<BadStableBinder> binder = BadStableBinder::system();
+        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+        EXPECT_TRUE(binder->gotUserTransaction);
+    }
+    {
+        sp<BadStableBinder> binder = BadStableBinder::vintf();
+        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+        EXPECT_TRUE(binder->gotUserTransaction);
+    }
+    {
+        // !!! user-defined transaction may not be stable for remote server !!!
+        // !!! so, it does not work !!!
+        sp<BadStableBinder> binder = BadStableBinder::vendor();
+        EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode());
+        EXPECT_FALSE(binder->gotUserTransaction);
+    }
 
     sp<IBinder> out;
-    // should automatically be set to local stability
-    EXPECT_TRUE(complServer->returnNoStabilityBinder(&out).isOk());
-    EXPECT_NE(nullptr, out.get());
+    EXPECT_TRUE(server->returnNoStabilityBinder(&out).isOk());
+    ASSERT_NE(nullptr, out.get());
+    EXPECT_EQ(OK, out->pingBinder());
+    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
 
-    EXPECT_TRUE(complServer->returnLocalStabilityBinder(&out).isOk());
-    EXPECT_NE(nullptr, out.get());
+    EXPECT_TRUE(server->returnLocalStabilityBinder(&out).isOk());
+    ASSERT_NE(nullptr, out.get());
+    EXPECT_EQ(OK, out->pingBinder());
+    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
 
-    EXPECT_TRUE(complServer->returnVintfStabilityBinder(&out).isOk());
-    EXPECT_NE(nullptr, out.get());
+    EXPECT_TRUE(server->returnVintfStabilityBinder(&out).isOk());
+    ASSERT_NE(nullptr, out.get());
+    EXPECT_EQ(OK, out->pingBinder());
+    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
+
+    EXPECT_TRUE(server->returnVendorStabilityBinder(&out).isOk());
+    ASSERT_NE(nullptr, out.get());
+
+    // !!! libbinder-defined transaction works !!!
+    EXPECT_EQ(OK, out->pingBinder());
+
+    // !!! user-defined transaction may not be stable !!!
+    // !!! so, it does not work !!!
+    EXPECT_EQ(BAD_TYPE, BadStableBinder::doUserTransaction(out));
 }
 
-void checkHighStabilityServer(const sp<IBinderStabilityTest>& highStability) {
-    EXPECT_FALSE(highStability->sendBinder(new BBinder()).isOk());
-    EXPECT_FALSE(highStability->sendBinder(getCompilationUnitStability()).isOk());
-    EXPECT_TRUE(highStability->sendBinder(getVintfStability()).isOk());
+// This is handwritten so that we can test different stability levels w/o having the AIDL
+// compiler assign them. Hand-writing binder interfaces is considered a bad practice
+// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
 
-    sp<IBinder> out;
-    EXPECT_FALSE(highStability->returnNoStabilityBinder(&out).isOk());
-    EXPECT_EQ(nullptr, out.get());
+struct NdkBinderStable_DataClass {
+    bool gotUserTransaction = false;
+};
+void* NdkBadStableBinder_Class_onCreate(void* args) {
+    LOG_ALWAYS_FATAL_IF(args != nullptr, "Takes no args");
+    return static_cast<void*>(new NdkBinderStable_DataClass);
+}
+void NdkBadStableBinder_Class_onDestroy(void* userData) {
+    delete static_cast<NdkBinderStable_DataClass*>(userData);
+}
+NdkBinderStable_DataClass* NdkBadStableBinder_getUserData(AIBinder* binder) {
+    LOG_ALWAYS_FATAL_IF(binder == nullptr);
+    void* userData = AIBinder_getUserData(binder);
+    LOG_ALWAYS_FATAL_IF(userData == nullptr, "null data - binder is remote?");
 
-    EXPECT_FALSE(highStability->returnLocalStabilityBinder(&out).isOk());
-    EXPECT_EQ(nullptr, out.get());
+    return static_cast<NdkBinderStable_DataClass*>(userData);
+}
+binder_status_t NdkBadStableBinder_Class_onTransact(
+    AIBinder* binder, transaction_code_t code, const AParcel* /*in*/, AParcel* /*out*/) {
 
-    EXPECT_TRUE(highStability->returnVintfStabilityBinder(&out).isOk());
-    EXPECT_NE(nullptr, out.get());
+    if (code == BadStableBinder::USER_TRANSACTION) {
+        ALOGE("ndk binder stability: Got user transaction");
+        NdkBadStableBinder_getUserData(binder)->gotUserTransaction = true;
+        return STATUS_OK;
+    }
+
+    return STATUS_UNKNOWN_TRANSACTION;
 }
 
-TEST(BinderStability, LocalNoStabilityServer) {
-    // in practice, a low stability server is probably one that hasn't been rebuilt
-    // or was written by hand.
-    auto server = BadStabilityTester::getNoStabilityServer();
-    ASSERT_NE(nullptr, IInterface::asBinder(server)->localBinder());
+static AIBinder_Class* kNdkBadStableBinder =
+    AIBinder_Class_define(String8(BadStableBinder::kDescriptor).c_str(),
+                          NdkBadStableBinder_Class_onCreate,
+                          NdkBadStableBinder_Class_onDestroy,
+                          NdkBadStableBinder_Class_onTransact);
 
-    // it should be considered to have local stability
-    checkLocalStabilityBinder(server);
-}
+// for testing only to get around __ANDROID_VNDK__ guard.
+extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY
 
-TEST(BinderStability, LocalLowStabilityServer) {
-    auto server = BadStabilityTester::getCompilationUnitStabilityServer();
-    ASSERT_NE(nullptr, IInterface::asBinder(server)->localBinder());
-    checkLocalStabilityBinder(server);
-}
+TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) {
+    SpAIBinder binder = SpAIBinder(AServiceManager_getService(
+        String8(kSystemStabilityServer).c_str()));
 
-TEST(BinderStability, LocalHighStabilityServer) {
-    auto server = BadStabilityTester::getVintfStabilityServer();
-    ASSERT_NE(nullptr, IInterface::asBinder(server)->localBinder());
-    checkHighStabilityServer(server);
-}
-
-TEST(BinderStability, RemoteNoStabilityServer) {
-    sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kNoStabilityServer);
-    auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);
+    std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
+        aidl::IBinderStabilityTest::fromBinder(binder);
 
     ASSERT_NE(nullptr, remoteServer.get());
-    ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());
 
-    // it should be considered to have local stability
-    checkLocalStabilityBinder(remoteServer);
-}
+    SpAIBinder comp = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
+    EXPECT_TRUE(remoteServer->sendBinder(comp).isOk());
+    EXPECT_TRUE(remoteServer->sendAndCallBinder(comp).isOk());
+    EXPECT_TRUE(NdkBadStableBinder_getUserData(comp.get())->gotUserTransaction);
 
-TEST(BinderStability, RemoteLowStabilityServer) {
-    sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kCompilationUnitServer);
-    auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);
-
-    ASSERT_NE(nullptr, remoteServer.get());
-    ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());
-
-    checkLocalStabilityBinder(remoteServer);
-}
-
-TEST(BinderStability, RemoteVintfServer) {
-    sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kVintfServer);
-    auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);
-
-    ASSERT_NE(nullptr, remoteServer.get());
-    ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());
-
-    checkHighStabilityServer(remoteServer);
+    SpAIBinder vendor = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
+    AIBinder_markVendorStability(vendor.get());
+    EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk());
+    EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk());
+    EXPECT_FALSE(NdkBadStableBinder_getUserData(vendor.get())->gotUserTransaction);
 }
 
 class MarksStabilityInConstructor : public BBinder {
@@ -179,7 +252,7 @@
     static bool gDestructed;
 
     MarksStabilityInConstructor() {
-        internal::Stability::markCompilationUnit(this);
+        Stability::markCompilationUnit(this);
     }
     ~MarksStabilityInConstructor() {
         gDestructed = true;
@@ -209,16 +282,8 @@
         // child process
         prctl(PR_SET_PDEATHSIG, SIGHUP);
 
-        sp<IBinder> noStability = new BadStabilityTester;
-        android::defaultServiceManager()->addService(kNoStabilityServer, noStability);
-
-        sp<IBinder> compil = new BadStabilityTester;
-        internal::Stability::markCompilationUnit(compil.get());
-        android::defaultServiceManager()->addService(kCompilationUnitServer, compil);
-
-        sp<IBinder> vintf = new BadStabilityTester;
-        internal::Stability::markVintf(vintf.get());
-        android::defaultServiceManager()->addService(kVintfServer, vintf);
+        sp<IBinder> server = new MyBinderStabilityTest;
+        android::defaultServiceManager()->addService(kSystemStabilityServer, server);
 
         IPCThreadState::self()->joinThreadPool(true);
         exit(1);  // should not reach