Reland "Binder: support storing interface stability"
This reverts commit e9495af181d56a4ba359539e3ff07d092d6d0a51.
Relanding original change 5981dcbe4a6701c1776e9ece08aa83fe01655da1
Reason for revert: reland feature
Change-Id: I4be143706996ba7ab19a3e1446fece7b5d18f205
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
new file mode 100644
index 0000000..2b27a81
--- /dev/null
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -0,0 +1,245 @@
+/*
+ * 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/os/IServiceManager.h>
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+#include <gtest/gtest.h>
+
+#include <sys/prctl.h>
+
+#include "BnBinderStabilityTest.h"
+#include "BpBinderStabilityTest.h"
+
+using namespace android;
+using android::binder::Status;
+using android::os::IServiceManager;
+
+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");
+
+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;
+}
+
+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;
+}
+
+// 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 {
+public:
+ Status sendBinder(const sp<IBinder>& /*binder*/) override {
+ return Status::ok();
+ }
+ Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override {
+ *_aidl_return = new BBinder();
+ return Status::ok();
+ }
+ Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override {
+ *_aidl_return = getCompilationUnitStability();
+ return Status::ok();
+ }
+ Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override {
+ *_aidl_return = getVintfStability();
+ 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);
+ }
+};
+
+void checkNoStabilityServer(const sp<IBinderStabilityTest>& unkemptServer) {
+ EXPECT_TRUE(unkemptServer->sendBinder(new BBinder()).isOk());
+ EXPECT_TRUE(unkemptServer->sendBinder(getCompilationUnitStability()).isOk());
+ EXPECT_TRUE(unkemptServer->sendBinder(getVintfStability()).isOk());
+
+ sp<IBinder> out;
+ EXPECT_TRUE(unkemptServer->returnNoStabilityBinder(&out).isOk());
+ EXPECT_NE(nullptr, out.get());
+
+ EXPECT_TRUE(unkemptServer->returnLocalStabilityBinder(&out).isOk());
+ EXPECT_NE(nullptr, out.get());
+
+ EXPECT_TRUE(unkemptServer->returnVintfStabilityBinder(&out).isOk());
+ EXPECT_NE(nullptr, out.get());
+}
+
+void checkLowStabilityServer(const sp<IBinderStabilityTest>& complServer) {
+ EXPECT_FALSE(complServer->sendBinder(new BBinder()).isOk());
+ EXPECT_TRUE(complServer->sendBinder(getCompilationUnitStability()).isOk());
+ EXPECT_TRUE(complServer->sendBinder(getVintfStability()).isOk());
+
+ sp<IBinder> out;
+ EXPECT_FALSE(complServer->returnNoStabilityBinder(&out).isOk());
+ EXPECT_EQ(nullptr, out.get());
+
+ EXPECT_TRUE(complServer->returnLocalStabilityBinder(&out).isOk());
+ EXPECT_NE(nullptr, out.get());
+
+ EXPECT_TRUE(complServer->returnVintfStabilityBinder(&out).isOk());
+ EXPECT_NE(nullptr, out.get());
+}
+
+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());
+
+ sp<IBinder> out;
+ EXPECT_FALSE(highStability->returnNoStabilityBinder(&out).isOk());
+ EXPECT_EQ(nullptr, out.get());
+
+ EXPECT_FALSE(highStability->returnLocalStabilityBinder(&out).isOk());
+ EXPECT_EQ(nullptr, out.get());
+
+ EXPECT_TRUE(highStability->returnVintfStabilityBinder(&out).isOk());
+ EXPECT_NE(nullptr, out.get());
+}
+
+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());
+ checkNoStabilityServer(server);
+}
+
+TEST(BinderStability, LocalLowStabilityServer) {
+ auto server = BadStabilityTester::getCompilationUnitStabilityServer();
+ ASSERT_NE(nullptr, IInterface::asBinder(server)->localBinder());
+ checkLowStabilityServer(server);
+}
+
+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);
+
+ ASSERT_NE(nullptr, remoteServer.get());
+ ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());
+
+ checkNoStabilityServer(remoteServer);
+}
+
+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());
+
+ checkLowStabilityServer(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);
+}
+
+class MarksStabilityInConstructor : public BBinder {
+public:
+ static bool gDestructed;
+
+ MarksStabilityInConstructor() {
+ internal::Stability::markCompilationUnit(this);
+ }
+ ~MarksStabilityInConstructor() {
+ gDestructed = true;
+ }
+};
+bool MarksStabilityInConstructor::gDestructed = false;
+
+TEST(BinderStability, MarkingObjectNoDestructTest) {
+ ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
+
+ // best practice is to put this directly in an sp, but for this test, we
+ // want to explicitly check what happens before that happens
+ MarksStabilityInConstructor* binder = new MarksStabilityInConstructor();
+ ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
+
+ sp<MarksStabilityInConstructor> binderSp = binder;
+ ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
+
+ binderSp = nullptr;
+ ASSERT_TRUE(MarksStabilityInConstructor::gDestructed);
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ if (fork() == 0) {
+ // 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);
+
+ IPCThreadState::self()->joinThreadPool(true);
+ exit(1); // should not reach
+ }
+
+ // This is not racey. Just giving these services some time to register before we call
+ // getService which sleeps for much longer...
+ usleep(10000);
+
+ return RUN_ALL_TESTS();
+}