diff options
-rw-r--r-- | data/etc/android.software.ipsec_tunnel_migration.xml | 24 | ||||
-rw-r--r-- | libs/binder/BpBinder.cpp | 17 | ||||
-rw-r--r-- | libs/binder/ndk/ibinder.cpp | 94 | ||||
-rw-r--r-- | libs/binder/ndk/ibinder_internal.h | 8 | ||||
-rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_ibinder.h | 5 | ||||
-rw-r--r-- | libs/binder/ndk/tests/iface.cpp | 5 | ||||
-rw-r--r-- | libs/binder/ndk/tests/include/iface/iface.h | 5 | ||||
-rw-r--r-- | libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp | 52 | ||||
-rw-r--r-- | libs/binder/tests/binderAllocationLimits.cpp | 18 | ||||
-rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 4 | ||||
-rw-r--r-- | libs/binder/tests/rpc_fuzzer/main.cpp | 7 | ||||
-rw-r--r-- | libs/binder/trusty/kernel/rules.mk | 83 |
12 files changed, 255 insertions, 67 deletions
diff --git a/data/etc/android.software.ipsec_tunnel_migration.xml b/data/etc/android.software.ipsec_tunnel_migration.xml new file mode 100644 index 0000000000..c405e1efd6 --- /dev/null +++ b/data/etc/android.software.ipsec_tunnel_migration.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2022 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. +--> + +<!-- + This is the feature indicating that the device has support for updating + source and destination addresses of IPsec tunnels +--> + +<permissions> + <feature name="android.software.ipsec_tunnel_migration" /> +</permissions> diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 54d24457d4..1c470a11d3 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -47,6 +47,8 @@ std::atomic_bool BpBinder::sCountByUidEnabled(false); binder_proxy_limit_callback BpBinder::sLimitCallback; bool BpBinder::sBinderProxyThrottleCreate = false; +static StaticString16 kDescriptorUninit(u"<uninit descriptor>"); + // Arbitrarily high value that probably distinguishes a bad behaving app uint32_t BpBinder::sBinderProxyCountHighWatermark = 2500; // Another arbitrary value a binder count needs to drop below before another callback will be called @@ -211,6 +213,7 @@ BpBinder::BpBinder(Handle&& handle) mAlive(true), mObitsSent(false), mObituaries(nullptr), + mDescriptorCache(kDescriptorUninit), mTrackedUid(-1) { extendObjectLifetime(OBJECT_LIFETIME_WEAK); } @@ -258,12 +261,12 @@ std::optional<int32_t> BpBinder::getDebugBinderHandle() const { bool BpBinder::isDescriptorCached() const { Mutex::Autolock _l(mLock); - return mDescriptorCache.size() ? true : false; + return mDescriptorCache.string() != kDescriptorUninit.string(); } const String16& BpBinder::getInterfaceDescriptor() const { - if (isDescriptorCached() == false) { + if (!isDescriptorCached()) { sp<BpBinder> thiz = sp<BpBinder>::fromExisting(const_cast<BpBinder*>(this)); Parcel data; @@ -276,8 +279,7 @@ const String16& BpBinder::getInterfaceDescriptor() const Mutex::Autolock _l(mLock); // mDescriptorCache could have been assigned while the lock was // released. - if (mDescriptorCache.size() == 0) - mDescriptorCache = res; + if (mDescriptorCache.string() == kDescriptorUninit.string()) mDescriptorCache = res; } } @@ -369,10 +371,7 @@ status_t BpBinder::transact( if (data.dataSize() > LOG_TRANSACTIONS_OVER_SIZE) { Mutex::Autolock _l(mLock); ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d", - data.dataSize(), - mDescriptorCache.size() ? String8(mDescriptorCache).c_str() - : "<uncached descriptor>", - code); + data.dataSize(), String8(mDescriptorCache).c_str(), code); } if (status == DEAD_OBJECT) mAlive = 0; @@ -647,7 +646,7 @@ void BpBinder::onLastStrongRef(const void* /*id*/) { if(obits != nullptr) { if (!obits->isEmpty()) { ALOGI("onLastStrongRef automatically unlinking death recipients: %s", - mDescriptorCache.size() ? String8(mDescriptorCache).c_str() : "<uncached descriptor>"); + String8(mDescriptorCache).c_str()); } if (ipc) ipc->clearDeathNotification(binderHandle(), this); diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp index 28d1f16d64..d0de7b96b5 100644 --- a/libs/binder/ndk/ibinder.cpp +++ b/libs/binder/ndk/ibinder.cpp @@ -75,12 +75,48 @@ void clean(const void* id, void* obj, void* cookie) { AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {} AIBinder::~AIBinder() {} -std::optional<bool> AIBinder::associateClassInternal(const AIBinder_Class* clazz, - const String16& newDescriptor, bool set) { +// b/175635923 libcxx causes "implicit-conversion" with a string with invalid char +static std::string SanitizeString(const String16& str) { + std::string sanitized{String8(str)}; + for (auto& c : sanitized) { + if (!isprint(c)) { + c = '?'; + } + } + return sanitized; +} + +bool AIBinder::associateClass(const AIBinder_Class* clazz) { + if (clazz == nullptr) return false; + + // If mClazz is non-null, this must have been called and cached + // already. So, we can safely call this first. Due to the implementation + // of getInterfaceDescriptor (at time of writing), two simultaneous calls + // may lead to extra binder transactions, but this is expected to be + // exceedingly rare. Once we have a binder, when we get it again later, + // we won't make another binder transaction here. + const String16& descriptor = getBinder()->getInterfaceDescriptor(); + const String16& newDescriptor = clazz->getInterfaceDescriptor(); + std::lock_guard<std::mutex> lock(mClazzMutex); if (mClazz == clazz) return true; - if (mClazz != nullptr) { + // If this is an ABpBinder, the first class object becomes the canonical one. The implication + // of this is that no API can require a proxy information to get information on how to behave. + // from the class itself - which should only store the interface descriptor. The functionality + // should be implemented by adding AIBinder_* APIs to set values on binders themselves, by + // setting things on AIBinder_Class which get transferred along with the binder, so that they + // can be read along with the BpBinder, or by modifying APIs directly (e.g. an option in + // onTransact). + // + // While this check is required to support linkernamespaces, one downside of it is that + // you may parcel code to communicate between things in the same process. However, comms + // between linkernamespaces like this already happen for cross-language calls like Java<->C++ + // or Rust<->Java, and there are good stability guarantees here. This interacts with + // binder Stability checks exactly like any other in-process call. The stability is known + // to the IBinder object, so that it doesn't matter if a class object comes from + // a different stability level. + if (mClazz != nullptr && !asABpBinder()) { const String16& currentDescriptor = mClazz->getInterfaceDescriptor(); if (newDescriptor == currentDescriptor) { LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor @@ -97,37 +133,10 @@ std::optional<bool> AIBinder::associateClassInternal(const AIBinder_Class* clazz return false; } - if (set) { - // if this is a local object, it's not one known to libbinder_ndk - mClazz = clazz; - return true; - } - - return {}; -} - -// b/175635923 libcxx causes "implicit-conversion" with a string with invalid char -static std::string SanitizeString(const String16& str) { - std::string sanitized{String8(str)}; - for (auto& c : sanitized) { - if (!isprint(c)) { - c = '?'; - } - } - return sanitized; -} - -bool AIBinder::associateClass(const AIBinder_Class* clazz) { - if (clazz == nullptr) return false; - - const String16& newDescriptor = clazz->getInterfaceDescriptor(); - - auto result = associateClassInternal(clazz, newDescriptor, false); - if (result.has_value()) return *result; - - CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor - - const String16& descriptor = getBinder()->getInterfaceDescriptor(); + // This will always be an O(n) comparison, but it's expected to be extremely rare. + // since it's an error condition. Do the comparison after we take the lock and + // check the pointer equality fast path. By always taking the lock, it's also + // more flake-proof. However, the check is not dependent on the lock. if (descriptor != newDescriptor) { if (getBinder()->isBinderAlive()) { LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor @@ -141,7 +150,14 @@ bool AIBinder::associateClass(const AIBinder_Class* clazz) { return false; } - return associateClassInternal(clazz, newDescriptor, true).value(); + // A local binder being set for the first time OR + // ignoring a proxy binder which is set multiple time, by considering the first + // associated class as the canonical one. + if (mClazz == nullptr) { + mClazz = clazz; + } + + return true; } ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData) @@ -325,6 +341,10 @@ bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs) { return lhs->binder < rhs->binder; } +// WARNING: When multiple classes exist with the same interface descriptor in different +// linkernamespaces, the first one to be associated with mClazz becomes the canonical one +// and the only requirement on this is that the interface descriptors match. If this +// is an ABpBinder, no other state can be referenced from mClazz. AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate, AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact) @@ -632,6 +652,10 @@ binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) { (*in)->get()->markForBinder(binder->getBinder()); status_t status = android::OK; + + // note - this is the only read of a value in clazz, and it comes with a warning + // on the API itself. Do not copy this design. Instead, attach data in a new + // version of the prepareTransaction function. if (clazz->writeHeader) { status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor()); } diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h index d7098e85bf..67bb092f0f 100644 --- a/libs/binder/ndk/ibinder_internal.h +++ b/libs/binder/ndk/ibinder_internal.h @@ -53,12 +53,14 @@ struct AIBinder : public virtual ::android::RefBase { } private: - std::optional<bool> associateClassInternal(const AIBinder_Class* clazz, - const ::android::String16& newDescriptor, bool set); - // AIBinder instance is instance of this class for a local object. In order to transact on a // remote object, this also must be set for simplicity (although right now, only the // interfaceDescriptor from it is used). + // + // WARNING: When multiple classes exist with the same interface descriptor in different + // linkernamespaces, the first one to be associated with mClazz becomes the canonical one + // and the only requirement on this is that the interface descriptors match. If this + // is an ABpBinder, no other state can be referenced from mClazz. const AIBinder_Class* mClazz; std::mutex mClazzMutex; }; diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h index 1af211975f..05677a8e5d 100644 --- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h +++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h @@ -229,6 +229,11 @@ void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __I * * Available since API level 33. * + * WARNING: this API interacts badly with linkernamespaces. For correct behavior, you must + * use it on all instances of a class in the same process which share the same interface + * descriptor. In general, it is recommended you do not use this API, because it is disabling + * type safety. + * * \param clazz class to disable interface header on. */ void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) __INTRODUCED_IN(33); diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp index 2afe5d2058..76acff50bf 100644 --- a/libs/binder/ndk/tests/iface.cpp +++ b/libs/binder/ndk/tests/iface.cpp @@ -72,6 +72,11 @@ binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate, IFoo_Class_onDestroy, IFoo_Class_onTransact); +// Defines the same class. Ordinarly, you would never want to do this, but it's done here +// to simulate what would happen when multiple linker namespaces interact. +AIBinder_Class* IFoo::kClassDupe = AIBinder_Class_define( + kIFooDescriptor, IFoo_Class_onCreate, IFoo_Class_onDestroy, IFoo_Class_onTransact); + class BpFoo : public IFoo { public: explicit BpFoo(AIBinder* binder) : mBinder(binder) {} diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h index 7408d0c5a9..0a562f085d 100644 --- a/libs/binder/ndk/tests/include/iface/iface.h +++ b/libs/binder/ndk/tests/include/iface/iface.h @@ -30,8 +30,13 @@ class IFoo : public virtual ::android::RefBase { static const char* kIFooDescriptor; static AIBinder_Class* kClass; + static AIBinder_Class* kClassDupe; // binder representing this interface with one reference count + // NOTE - this will create a new binder if it already exists. If you use + // getService for instance, you must pull outBinder. Don't use this without + // verifying isRemote or pointer equality. This is not a very good testing API - don't + // copy it - consider the AIDL-generated APIs instead. AIBinder* getBinder(); // Takes ownership of IFoo diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index 9d5ef6805a..5b2532ab4e 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -55,6 +55,18 @@ constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestS constexpr unsigned int kShutdownWaitTime = 10; constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715; +class MyTestFoo : public IFoo { + binder_status_t doubleNumber(int32_t in, int32_t* out) override { + *out = 2 * in; + LOG(INFO) << "doubleNumber (" << in << ") => " << *out; + return STATUS_OK; + } + binder_status_t die() override { + ADD_FAILURE() << "die called on local instance"; + return STATUS_OK; + } +}; + class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) { *out = in; @@ -296,11 +308,10 @@ TEST(NdkBinder, RegisterForServiceNotificationsExisting) { } TEST(NdkBinder, UnimplementedDump) { - sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName); + ndk::SpAIBinder binder; + sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName, binder.getR()); ASSERT_NE(foo, nullptr); - AIBinder* binder = foo->getBinder(); - EXPECT_EQ(OK, AIBinder_dump(binder, STDOUT_FILENO, nullptr, 0)); - AIBinder_decStrong(binder); + EXPECT_EQ(OK, AIBinder_dump(binder.get(), STDOUT_FILENO, nullptr, 0)); } TEST(NdkBinder, UnimplementedShell) { @@ -324,6 +335,24 @@ TEST(NdkBinder, DoubleNumber) { EXPECT_EQ(2, out); } +TEST(NdkBinder, ReassociateBpBinderWithSameDescriptor) { + ndk::SpAIBinder binder; + sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName, binder.getR()); + + EXPECT_TRUE(AIBinder_isRemote(binder.get())); + + EXPECT_TRUE(AIBinder_associateClass(binder.get(), IFoo::kClassDupe)); +} + +TEST(NdkBinder, CantHaveTwoLocalBinderClassesWithSameDescriptor) { + sp<IFoo> foo = sp<MyTestFoo>::make(); + ndk::SpAIBinder binder(foo->getBinder()); + + EXPECT_FALSE(AIBinder_isRemote(binder.get())); + + EXPECT_FALSE(AIBinder_associateClass(binder.get(), IFoo::kClassDupe)); +} + TEST(NdkBinder, GetTestServiceStressTest) { // libbinder has some complicated logic to make sure only one instance of // ABpBinder is associated with each binder. @@ -545,18 +574,6 @@ TEST(NdkBinder, LinkToDeath) { AIBinder_decStrong(binder); } -class MyTestFoo : public IFoo { - binder_status_t doubleNumber(int32_t in, int32_t* out) override { - *out = 2 * in; - LOG(INFO) << "doubleNumber (" << in << ") => " << *out; - return STATUS_OK; - } - binder_status_t die() override { - ADD_FAILURE() << "die called on local instance"; - return STATUS_OK; - } -}; - TEST(NdkBinder, SetInheritRt) { // functional test in binderLibTest sp<IFoo> foo = sp<MyTestFoo>::make(); @@ -597,7 +614,8 @@ TEST(NdkBinder, GetServiceInProcess) { sp<IFoo> foo = new MyTestFoo; EXPECT_EQ(EX_NONE, foo->addService(kInstanceName)); - sp<IFoo> getFoo = IFoo::getService(kInstanceName); + ndk::SpAIBinder binder; + sp<IFoo> getFoo = IFoo::getService(kInstanceName, binder.getR()); EXPECT_EQ(foo.get(), getFoo.get()); int32_t out; diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp index 55a3916112..6a6e0080a4 100644 --- a/libs/binder/tests/binderAllocationLimits.cpp +++ b/libs/binder/tests/binderAllocationLimits.cpp @@ -172,6 +172,24 @@ TEST(BinderAllocation, PingTransaction) { a_binder->pingBinder(); } +TEST(BinderAllocation, InterfaceDescriptorTransaction) { + sp<IBinder> a_binder = GetRemoteBinder(); + + size_t mallocs = 0; + const auto on_malloc = OnMalloc([&](size_t bytes) { + mallocs++; + // Happens to be SM package length. We could switch to forking + // and registering our own service if it became an issue. + EXPECT_EQ(bytes, 78); + }); + + a_binder->getInterfaceDescriptor(); + a_binder->getInterfaceDescriptor(); + a_binder->getInterfaceDescriptor(); + + EXPECT_EQ(mallocs, 1); +} + TEST(BinderAllocation, SmallTransaction) { String16 empty_descriptor = String16(""); sp<IServiceManager> manager = defaultServiceManager(); diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 739c2171f3..8afa49b911 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -372,12 +372,12 @@ TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) { ts.push_back(std::thread([&] { proc.rootIface->lockUnlock(); })); } - usleep(10000); // give chance for calls on other threads + usleep(100000); // give chance for calls on other threads // other calls still work EXPECT_EQ(OK, proc.rootBinder->pingBinder()); - constexpr size_t blockTimeMs = 50; + constexpr size_t blockTimeMs = 100; size_t epochMsBefore = epochMillis(); // after this, we should never see a response within this time EXPECT_OK(proc.rootIface->unlockInMsAsync(blockTimeMs)); diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp index f68a56144d..b8ae84d5c0 100644 --- a/libs/binder/tests/rpc_fuzzer/main.cpp +++ b/libs/binder/tests/rpc_fuzzer/main.cpp @@ -133,8 +133,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { bool hangupBeforeShutdown = provider.ConsumeBool(); + // b/260736889 - limit arbitrarily, due to thread resource exhaustion, which currently + // aborts. Servers should consider RpcServer::setConnectionFilter instead. + constexpr size_t kMaxConnections = 1000; + while (provider.remaining_bytes() > 0) { - if (connections.empty() || provider.ConsumeBool()) { + if (connections.empty() || + (connections.size() < kMaxConnections && provider.ConsumeBool())) { base::unique_fd fd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0))); CHECK_NE(fd.get(), -1); CHECK_EQ(0, diff --git a/libs/binder/trusty/kernel/rules.mk b/libs/binder/trusty/kernel/rules.mk new file mode 100644 index 0000000000..ab7a50d3f7 --- /dev/null +++ b/libs/binder/trusty/kernel/rules.mk @@ -0,0 +1,83 @@ +# Copyright (C) 2022 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. +# + +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +LIBBINDER_DIR := frameworks/native/libs/binder +LIBBASE_DIR := system/libbase +LIBCUTILS_DIR := system/core/libcutils +LIBUTILS_DIR := system/core/libutils +FMTLIB_DIR := external/fmtlib + +MODULE_SRCS := \ + $(LOCAL_DIR)/../logging.cpp \ + $(LOCAL_DIR)/../TrustyStatus.cpp \ + $(LIBBINDER_DIR)/Binder.cpp \ + $(LIBBINDER_DIR)/BpBinder.cpp \ + $(LIBBINDER_DIR)/FdTrigger.cpp \ + $(LIBBINDER_DIR)/IInterface.cpp \ + $(LIBBINDER_DIR)/IResultReceiver.cpp \ + $(LIBBINDER_DIR)/Parcel.cpp \ + $(LIBBINDER_DIR)/Stability.cpp \ + $(LIBBINDER_DIR)/Status.cpp \ + $(LIBBINDER_DIR)/Utils.cpp \ + $(LIBBASE_DIR)/hex.cpp \ + $(LIBBASE_DIR)/stringprintf.cpp \ + $(LIBUTILS_DIR)/Errors.cpp \ + $(LIBUTILS_DIR)/misc.cpp \ + $(LIBUTILS_DIR)/RefBase.cpp \ + $(LIBUTILS_DIR)/StrongPointer.cpp \ + $(LIBUTILS_DIR)/Unicode.cpp \ + +# TODO: remove the following when libbinder supports std::string +# instead of String16 and String8 for Status and descriptors +MODULE_SRCS += \ + $(LIBUTILS_DIR)/SharedBuffer.cpp \ + $(LIBUTILS_DIR)/String16.cpp \ + $(LIBUTILS_DIR)/String8.cpp \ + +# TODO: disable dump() transactions to get rid of Vector +MODULE_SRCS += \ + $(LIBUTILS_DIR)/VectorImpl.cpp \ + +MODULE_DEFINES += \ + LK_DEBUGLEVEL_NO_ALIASES=1 \ + +MODULE_INCLUDES += \ + $(LOCAL_DIR)/.. \ + +GLOBAL_INCLUDES += \ + $(LOCAL_DIR)/include \ + $(LOCAL_DIR)/../include \ + $(LIBBINDER_DIR)/include \ + $(LIBBINDER_DIR)/ndk/include_cpp \ + $(LIBBASE_DIR)/include \ + $(LIBCUTILS_DIR)/include \ + $(LIBUTILS_DIR)/include \ + $(FMTLIB_DIR)/include \ + +GLOBAL_COMPILEFLAGS += \ + -DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION \ + -DBINDER_NO_KERNEL_IPC \ + -DBINDER_RPC_SINGLE_THREADED \ + -D__ANDROID_VNDK__ \ + +MODULE_DEPS += \ + trusty/kernel/lib/libcxx-trusty \ + trusty/kernel/lib/libcxxabi-trusty \ + +include make/module.mk |