libbinder_ndk: stability settings

Allow apex/vendor users to set stability.

Bug: 136027762
Test: binderStabilityTest
Test: manually creating a vendor service and
    checking for expected behavior
Change-Id: Icbf8b2fdb8af00a64fcbf7a1c2c29e640ac9da29
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 6da3086..1beacdf 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -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"],
     },
 }
 
diff --git a/libs/binder/ndk/include_apex/android/binder_stability.h b/libs/binder/ndk/include_apex/android/binder_stability.h
new file mode 100644
index 0000000..e6aeb04
--- /dev/null
+++ b/libs/binder/ndk/include_apex/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..abafe1f
--- /dev/null
+++ b/libs/binder/ndk/stability.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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
+
+// 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/tests/Android.bp b/libs/binder/tests/Android.bp
index 724cb15..d59a40d 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -138,18 +138,31 @@
     test_suites: ["device-tests"],
 }
 
+aidl_interface {
+    name: "binderStabilityTestIface",
+    srcs: [
+        "IBinderStabilityTest.aidl",
+        "IBinderStabilityTestSub.aidl",
+    ],
+}
+
 cc_test {
     name: "binderStabilityTest",
     defaults: ["binder_test_defaults"],
     srcs: [
         "binderStabilityTest.cpp",
-        "IBinderStabilityTest.aidl",
-        "IBinderStabilityTestSub.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/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 52595e0..936b821 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,47 +26,53 @@
 
 #include <sys/prctl.h>
 
+#include "aidl/BnBinderStabilityTestSub.h"
+#include "aidl/BnBinderStabilityTest.h"
 #include "BnBinderStabilityTestSub.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 kCompilationUnitNdkServer = String16("binder_stability_test_service_compl");
+
 class BadStabilityTestSub : public BnBinderStabilityTestSub {
+public:
     Status userDefinedTransaction() {
         return Status::ok();
     }
+
+    static sp<IBinderStabilityTestSub> system() {
+        sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
+        // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
+        // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
+        Stability::markCompilationUnit(iface.get()); // <- BAD, NO! DO NOT COPY
+        return iface;
+    }
+
+    static sp<IBinderStabilityTestSub> vintf() {
+        sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
+        // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
+        // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
+        Stability::markVintf(iface.get()); // <- BAD, NO! DO NOT COPY
+        return iface;
+    }
+
+    static sp<IBinderStabilityTestSub> vendor() {
+        sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
+        // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
+        // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
+        Stability::markVndk(iface.get()); // <- BAD, NO! DO NOT COPY
+        return iface;
+    }
 };
 
-sp<IBinderStabilityTestSub> getCompilationUnitStability() {
-    sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
-    // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
-    // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
-    internal::Stability::markCompilationUnit(iface.get()); // <- BAD, NO! DO NOT COPY
-    return iface;
-}
-
-sp<IBinderStabilityTestSub> getVintfStability() {
-    sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
-    // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
-    // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
-    internal::Stability::markVintf(iface.get()); // <- BAD, NO! DO NOT COPY
-    return iface;
-}
-
-sp<IBinderStabilityTestSub> getVendorStability() {
-    sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
-    // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
-    // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
-    internal::Stability::markVndk(iface.get()); // <- BAD, NO! DO NOT COPY
-    return iface;
-}
-
 // 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!
@@ -74,6 +82,7 @@
         return Status::ok();
     }
     Status sendAndCallBinder(const sp<IBinderStabilityTestSub>& binder) override {
+        Stability::debugLogStability("sendAndCallBinder got binder", IInterface::asBinder(binder));
         return binder->userDefinedTransaction();
     }
     Status returnNoStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
@@ -81,31 +90,31 @@
         return Status::ok();
     }
     Status returnLocalStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
-        *_aidl_return = getCompilationUnitStability();
+        *_aidl_return = BadStabilityTestSub::system();
         return Status::ok();
     }
     Status returnVintfStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
-        *_aidl_return = getVintfStability();
+        *_aidl_return = BadStabilityTestSub::vintf();
         return Status::ok();
     }
     Status returnVendorStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
-        *_aidl_return = getVendorStability();
+        *_aidl_return = BadStabilityTestSub::vendor();
         return Status::ok();
     }
 };
 
 void checkSystemStabilityBinder(const sp<IBinderStabilityTest>& complServer) {
     EXPECT_TRUE(complServer->sendBinder(new BadStabilityTestSub()).isOk());
-    EXPECT_TRUE(complServer->sendBinder(getCompilationUnitStability()).isOk());
-    EXPECT_TRUE(complServer->sendBinder(getVintfStability()).isOk());
-    EXPECT_TRUE(complServer->sendBinder(getVendorStability()).isOk());
+    EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::system()).isOk());
+    EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::vintf()).isOk());
+    EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::vendor()).isOk());
 
     EXPECT_TRUE(complServer->sendAndCallBinder(new BadStabilityTestSub()).isOk());
-    EXPECT_TRUE(complServer->sendAndCallBinder(getCompilationUnitStability()).isOk());
-    EXPECT_TRUE(complServer->sendAndCallBinder(getVintfStability()).isOk());
+    EXPECT_TRUE(complServer->sendAndCallBinder(BadStabilityTestSub::system()).isOk());
+    EXPECT_TRUE(complServer->sendAndCallBinder(BadStabilityTestSub::vintf()).isOk());
 
     // !!! user-defined transaction may not be stable for remote server !!!
-    EXPECT_FALSE(complServer->sendAndCallBinder(getVendorStability()).isOk());
+    EXPECT_FALSE(complServer->sendAndCallBinder(BadStabilityTestSub::vendor()).isOk());
 
     sp<IBinderStabilityTestSub> out;
     EXPECT_TRUE(complServer->returnNoStabilityBinder(&out).isOk());
@@ -163,12 +172,39 @@
     checkSystemStabilityBinder(remoteServer);
 }
 
+class NdkBadStabilityTestSub : public aidl::BnBinderStabilityTestSub {
+    ScopedAStatus userDefinedTransaction() {
+        return ScopedAStatus::ok();
+    }
+};
+// for testing only to get around __ANDROID_VNDK__ guard.
+extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY
+
+TEST(BinderStability, NdkClientOfRemoteServer) {
+    SpAIBinder binder = SpAIBinder(AServiceManager_getService(
+        String8(kCompilationUnitServer).c_str()));
+
+    std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
+        aidl::IBinderStabilityTest::fromBinder(binder);
+
+    ASSERT_NE(nullptr, remoteServer.get());
+
+    std::shared_ptr<aidl::IBinderStabilityTestSub> vendor = SharedRefBase::make<NdkBadStabilityTestSub>();
+
+    // TODO: not ideal: binder must be held once it is marked
+    SpAIBinder vendorBinder = vendor->asBinder();
+    AIBinder_markVendorStability(vendorBinder.get());
+
+    EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk());
+    EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk());
+}
+
 class MarksStabilityInConstructor : public BBinder {
 public:
     static bool gDestructed;
 
     MarksStabilityInConstructor() {
-        internal::Stability::markCompilationUnit(this);
+        Stability::markCompilationUnit(this);
     }
     ~MarksStabilityInConstructor() {
         gDestructed = true;
@@ -202,11 +238,11 @@
         android::defaultServiceManager()->addService(kNoStabilityServer, noStability);
 
         sp<IBinder> compil = new BadStabilityTester;
-        internal::Stability::markCompilationUnit(compil.get());
+        Stability::markCompilationUnit(compil.get());
         android::defaultServiceManager()->addService(kCompilationUnitServer, compil);
 
         sp<IBinder> vintf = new BadStabilityTester;
-        internal::Stability::markVintf(vintf.get());
+        Stability::markVintf(vintf.get());
         android::defaultServiceManager()->addService(kVintfServer, vintf);
 
         IPCThreadState::self()->joinThreadPool(true);