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