diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-02-28 21:13:43 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-02-28 21:13:43 +0000 |
commit | f5bbc68d5500b2ecae8ef40b7acbdb16a708a817 (patch) | |
tree | 11cc912f8b1b2778f3b8003f4698c87c13aa1e94 | |
parent | b5510935039cae5758dae532a6c8031f3124df24 (diff) | |
parent | c2e69665235335d5964bc61b689f587193f95a05 (diff) | |
download | native-f5bbc68d5500b2ecae8ef40b7acbdb16a708a817.tar.gz |
Snap for 11510257 from c2e69665235335d5964bc61b689f587193f95a05 to simpleperf-release
Change-Id: I235c6e637add785f88478c0015f41d8f955e2c4a
32 files changed, 506 insertions, 122 deletions
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index ae0fb018ef..84ff9d74ef 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -320,6 +320,24 @@ cc_defaults { "ServiceManagerHost.cpp", ], }, + android: { + shared_libs: [ + "libapexsupport", + "libvndksupport", + ], + }, + recovery: { + exclude_shared_libs: [ + "libapexsupport", + "libvndksupport", + ], + }, + native_bridge: { + exclude_shared_libs: [ + "libapexsupport", + "libvndksupport", + ], + }, }, cflags: [ "-DBINDER_WITH_KERNEL_IPC", @@ -646,9 +664,7 @@ cc_library { // Do not expand the visibility. visibility: [ ":__subpackages__", - "//packages/modules/Virtualization/javalib/jni", - "//packages/modules/Virtualization/vm_payload", - "//packages/modules/Virtualization/demo_native", + "//packages/modules/Virtualization:__subpackages__", "//device/google/cuttlefish/shared/minidroid:__subpackages__", "//system/software_defined_vehicle:__subpackages__", ], diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index b92e504a9a..ef96f803c3 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -922,28 +922,10 @@ void IPCThreadState::decWeakHandle(int32_t handle) flushIfNeeded(); } -status_t IPCThreadState::attemptIncStrongHandle(int32_t handle) -{ -#if HAS_BC_ATTEMPT_ACQUIRE - LOG_REMOTEREFS("IPCThreadState::attemptIncStrongHandle(%d)\n", handle); - mOut.writeInt32(BC_ATTEMPT_ACQUIRE); - mOut.writeInt32(0); // xxx was thread priority - mOut.writeInt32(handle); - status_t result = UNKNOWN_ERROR; - - waitForResponse(NULL, &result); - -#if LOG_REFCOUNTS - ALOGV("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n", - handle, result == NO_ERROR ? "SUCCESS" : "FAILURE"); -#endif - - return result; -#else +status_t IPCThreadState::attemptIncStrongHandle(int32_t handle) { (void)handle; ALOGE("%s(%d): Not supported\n", __func__, handle); return INVALID_OPERATION; -#endif } void IPCThreadState::expungeHandle(int32_t handle, IBinder* binder) diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index fe566fccb2..39573ec54d 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -40,6 +40,11 @@ #include "ServiceManagerHost.h" #endif +#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) && !defined(__ANDROID_NATIVE_BRIDGE__) +#include <android/apexsupport.h> +#include <vndksupport/linker.h> +#endif + #include "Static.h" namespace android { @@ -259,6 +264,27 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid, bool logP } } +void* openDeclaredPassthroughHal(const String16& interface, const String16& instance, int flag) { +#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) && !defined(__ANDROID_NATIVE_BRIDGE__) + sp<IServiceManager> sm = defaultServiceManager(); + String16 name = interface + String16("/") + instance; + if (!sm->isDeclared(name)) { + return nullptr; + } + String16 libraryName = interface + String16(".") + instance + String16(".so"); + if (auto updatableViaApex = sm->updatableViaApex(name); updatableViaApex.has_value()) { + return AApexSupport_loadLibrary(String8(libraryName).c_str(), + String8(*updatableViaApex).c_str(), flag); + } + return android_load_sphal_library(String8(libraryName).c_str(), flag); +#else + (void)interface; + (void)instance; + (void)flag; + return nullptr; +#endif +} + #endif //__ANDROID_VNDK__ // ---------------------------------------------------------------------- diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp index 525ba2e9b9..de2a69f7cf 100644 --- a/libs/binder/RecordedTransaction.cpp +++ b/libs/binder/RecordedTransaction.cpp @@ -114,8 +114,8 @@ static_assert(PADDING8(8) == 0); RecordedTransaction::RecordedTransaction(RecordedTransaction&& t) noexcept { mData = t.mData; - mSent.setData(t.getDataParcel().data(), t.getDataParcel().dataSize()); - mReply.setData(t.getReplyParcel().data(), t.getReplyParcel().dataSize()); + mSentDataOnly.setData(t.getDataParcel().data(), t.getDataParcel().dataSize()); + mReplyDataOnly.setData(t.getReplyParcel().data(), t.getReplyParcel().dataSize()); } std::optional<RecordedTransaction> RecordedTransaction::fromDetails( @@ -136,12 +136,21 @@ std::optional<RecordedTransaction> RecordedTransaction::fromDetails( return std::nullopt; } - if (t.mSent.setData(dataParcel.data(), dataParcel.dataBufferSize()) != android::NO_ERROR) { + if (const auto* kernelFields = dataParcel.maybeKernelFields()) { + for (size_t i = 0; i < kernelFields->mObjectsSize; i++) { + uint64_t offset = kernelFields->mObjects[i]; + t.mData.mSentObjectData.push_back(offset); + } + } + + if (t.mSentDataOnly.setData(dataParcel.data(), dataParcel.dataBufferSize()) != + android::NO_ERROR) { ALOGE("Failed to set sent parcel data."); return std::nullopt; } - if (t.mReply.setData(replyParcel.data(), replyParcel.dataBufferSize()) != android::NO_ERROR) { + if (t.mReplyDataOnly.setData(replyParcel.data(), replyParcel.dataBufferSize()) != + android::NO_ERROR) { ALOGE("Failed to set reply parcel data."); return std::nullopt; } @@ -154,6 +163,7 @@ enum { DATA_PARCEL_CHUNK = 2, REPLY_PARCEL_CHUNK = 3, INTERFACE_NAME_CHUNK = 4, + DATA_PARCEL_OBJECT_CHUNK = 5, END_CHUNK = 0x00ffffff, }; @@ -265,21 +275,30 @@ std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd break; } case DATA_PARCEL_CHUNK: { - if (t.mSent.setData(reinterpret_cast<const unsigned char*>(payloadMap), - chunk.dataSize) != android::NO_ERROR) { + if (t.mSentDataOnly.setData(reinterpret_cast<const unsigned char*>(payloadMap), + chunk.dataSize) != android::NO_ERROR) { ALOGE("Failed to set sent parcel data."); return std::nullopt; } break; } case REPLY_PARCEL_CHUNK: { - if (t.mReply.setData(reinterpret_cast<const unsigned char*>(payloadMap), - chunk.dataSize) != android::NO_ERROR) { + if (t.mReplyDataOnly.setData(reinterpret_cast<const unsigned char*>(payloadMap), + chunk.dataSize) != android::NO_ERROR) { ALOGE("Failed to set reply parcel data."); return std::nullopt; } break; } + case DATA_PARCEL_OBJECT_CHUNK: { + const uint64_t* objects = reinterpret_cast<const uint64_t*>(payloadMap); + size_t metaDataSize = (chunk.dataSize / sizeof(uint64_t)); + ALOGI("Total objects found in saved parcel %zu", metaDataSize); + for (size_t index = 0; index < metaDataSize; ++index) { + t.mData.mSentObjectData.push_back(objects[index]); + } + break; + } case END_CHUNK: break; default: @@ -343,14 +362,26 @@ android::status_t RecordedTransaction::dumpToFile(const unique_fd& fd) const { return UNKNOWN_ERROR; } - if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataBufferSize(), mSent.data())) { + if (NO_ERROR != + writeChunk(fd, DATA_PARCEL_CHUNK, mSentDataOnly.dataBufferSize(), mSentDataOnly.data())) { ALOGE("Failed to write sent Parcel to fd %d", fd.get()); return UNKNOWN_ERROR; } - if (NO_ERROR != writeChunk(fd, REPLY_PARCEL_CHUNK, mReply.dataBufferSize(), mReply.data())) { + + if (NO_ERROR != + writeChunk(fd, REPLY_PARCEL_CHUNK, mReplyDataOnly.dataBufferSize(), + mReplyDataOnly.data())) { ALOGE("Failed to write reply Parcel to fd %d", fd.get()); return UNKNOWN_ERROR; } + + if (NO_ERROR != + writeChunk(fd, DATA_PARCEL_OBJECT_CHUNK, mData.mSentObjectData.size() * sizeof(uint64_t), + reinterpret_cast<const uint8_t*>(mData.mSentObjectData.data()))) { + ALOGE("Failed to write sent parcel object metadata to fd %d", fd.get()); + return UNKNOWN_ERROR; + } + if (NO_ERROR != writeChunk(fd, END_CHUNK, 0, NULL)) { ALOGE("Failed to write end chunk to fd %d", fd.get()); return UNKNOWN_ERROR; @@ -384,10 +415,14 @@ uint32_t RecordedTransaction::getVersion() const { return mData.mHeader.version; } +const std::vector<uint64_t>& RecordedTransaction::getObjectOffsets() const { + return mData.mSentObjectData; +} + const Parcel& RecordedTransaction::getDataParcel() const { - return mSent; + return mSentDataOnly; } const Parcel& RecordedTransaction::getReplyParcel() const { - return mReply; + return mReplyDataOnly; } diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index 55167a7db0..486bdfba78 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -207,6 +207,8 @@ status_t getService(const String16& name, sp<INTERFACE>* outService) return NAME_NOT_FOUND; } +void* openDeclaredPassthroughHal(const String16& interface, const String16& instance, int flag); + bool checkCallingPermission(const String16& permission); bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid); diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index 09da6e3c4a..d7096d8a75 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -55,6 +55,9 @@ class String8; class TextOutput; namespace binder { class Status; +namespace debug { +class RecordedTransaction; +} } class Parcel { @@ -1443,6 +1446,9 @@ private: // TODO(b/202029388): Remove 'getBlobAshmemSize' once no prebuilts reference // this size_t getBlobAshmemSize() const; + + // Needed so that we can save object metadata to the disk + friend class android::binder::debug::RecordedTransaction; }; // --------------------------------------------------------------------------- diff --git a/libs/binder/include/binder/RecordedTransaction.h b/libs/binder/include/binder/RecordedTransaction.h index 505c1992b9..f0bee7f39e 100644 --- a/libs/binder/include/binder/RecordedTransaction.h +++ b/libs/binder/include/binder/RecordedTransaction.h @@ -50,6 +50,7 @@ public: uint32_t getVersion() const; const Parcel& getDataParcel() const; const Parcel& getReplyParcel() const; + const std::vector<uint64_t>& getObjectOffsets() const; private: RecordedTransaction() = default; @@ -75,10 +76,11 @@ private: struct MovableData { // movable TransactionHeader mHeader; std::string mInterfaceName; + std::vector<uint64_t> mSentObjectData; /* Object Offsets */ }; MovableData mData; - Parcel mSent; - Parcel mReply; + Parcel mSentDataOnly; + Parcel mReplyDataOnly; }; } // namespace binder::debug diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h index 316a79cfee..a905dff4b1 100644 --- a/libs/binder/ndk/include_platform/android/binder_manager.h +++ b/libs/binder/ndk/include_platform/android/binder_manager.h @@ -243,6 +243,20 @@ void AServiceManager_getUpdatableApexName(const char* instance, void* context, __INTRODUCED_IN(__ANDROID_API_U__); /** + * Opens a declared passthrough HAL. + * + * \param instance identifier of the passthrough service (e.g. "mapper") + * \param instance identifier of the implemenatation (e.g. "default") + * \param flag passed to dlopen() + * + * \return the result of dlopen of the specified HAL + */ +void* AServiceManager_openDeclaredPassthroughHal(const char* interface, const char* instance, + int flag) + // TODO(b/302113279) use __INTRODUCED_LLNDK for vendor variants + __INTRODUCED_IN(__ANDROID_API_V__); + +/** * Prevent lazy services without client from shutting down their process * * This should only be used if it is every eventually set to false. If a diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 0843a8e648..de624e44f6 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -204,6 +204,7 @@ LIBBINDER_NDK35 { # introduced=VanillaIceCream APersistableBundle_getDoubleVectorKeys; APersistableBundle_getStringVectorKeys; APersistableBundle_getPersistableBundleKeys; + AServiceManager_openDeclaredPassthroughHal; # systemapi llndk }; LIBBINDER_NDK_PLATFORM { diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp index 3bfdc59ec2..5529455cc6 100644 --- a/libs/binder/ndk/service_manager.cpp +++ b/libs/binder/ndk/service_manager.cpp @@ -200,6 +200,13 @@ void AServiceManager_getUpdatableApexName(const char* instance, void* context, callback(String8(updatableViaApex.value()).c_str(), context); } } +void* AServiceManager_openDeclaredPassthroughHal(const char* interface, const char* instance, + int flag) { + LOG_ALWAYS_FATAL_IF(interface == nullptr, "interface == nullptr"); + LOG_ALWAYS_FATAL_IF(instance == nullptr, "instance == nullptr"); + + return openDeclaredPassthroughHal(String16(interface), String16(instance), flag); +} void AServiceManager_forceLazyServicesPersist(bool persist) { auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); serviceRegistrar.forcePersist(persist); diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index cab1a60370..966ec959b6 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -984,7 +984,7 @@ int main(int argc, char* argv[]) { return generatedFlaggedService(test_flags, kBinderNdkUnitTestServiceFlagged); } - ABinderProcess_setThreadPoolMaxThreadCount(1); // to receive death notifications/callbacks + ABinderProcess_setThreadPoolMaxThreadCount(0); ABinderProcess_startThreadPool(); return RUN_ALL_TESTS(); diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index dd2be94a76..2f0987fd1a 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -69,10 +69,14 @@ cc_test { cc_test { name: "binderRecordReplayTest", srcs: ["binderRecordReplayTest.cpp"], + cflags: [ + "-DBINDER_WITH_KERNEL_IPC", + ], shared_libs: [ "libbinder", "libcutils", "libutils", + "liblog", ], static_libs: [ "binderRecordReplayTestIface-cpp", @@ -96,6 +100,14 @@ aidl_interface { enabled: true, platform_apis: true, }, + + // TODO: switch from FileDescriptor to ParcelFileDescriptor + ndk: { + enabled: false, + }, + rust: { + enabled: false, + }, }, } diff --git a/libs/binder/tests/IBinderRecordReplayTest.aidl b/libs/binder/tests/IBinderRecordReplayTest.aidl index bd6b03c6e0..29267e91c6 100644 --- a/libs/binder/tests/IBinderRecordReplayTest.aidl +++ b/libs/binder/tests/IBinderRecordReplayTest.aidl @@ -69,4 +69,10 @@ interface IBinderRecordReplayTest { void setSingleDataParcelableArray(in SingleDataParcelable[] input); SingleDataParcelable[] getSingleDataParcelableArray(); + + void setBinder(in IBinder binder); + IBinder getBinder(); + + void setFileDescriptor(in FileDescriptor fd); + FileDescriptor getFileDescriptor(); } diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index cb1a1ee443..0ee96e7317 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -70,7 +70,7 @@ MATCHER_P(StatusEq, expected, (negation ? "not " : "") + statusToString(expected } static ::testing::AssertionResult IsPageAligned(void *buf) { - if (((unsigned long)buf & ((unsigned long)PAGE_SIZE - 1)) == 0) + if (((unsigned long)buf & ((unsigned long)getpagesize() - 1)) == 0) return ::testing::AssertionSuccess(); else return ::testing::AssertionFailure() << buf << " is not page aligned"; diff --git a/libs/binder/tests/binderRecordReplayTest.cpp b/libs/binder/tests/binderRecordReplayTest.cpp index 73c0a94ce2..b975fad2c9 100644 --- a/libs/binder/tests/binderRecordReplayTest.cpp +++ b/libs/binder/tests/binderRecordReplayTest.cpp @@ -24,7 +24,10 @@ #include <binder/RecordedTransaction.h> #include <binder/unique_fd.h> +#include <cutils/ashmem.h> + #include <fuzzbinder/libbinder_driver.h> +#include <fuzzbinder/random_binder.h> #include <fuzzer/FuzzedDataProvider.h> #include <fuzzseeds/random_parcel_seeds.h> @@ -37,6 +40,7 @@ using namespace android; using android::generateSeedsFromRecording; +using android::RandomBinder; using android::binder::borrowed_fd; using android::binder::Status; using android::binder::unique_fd; @@ -44,6 +48,7 @@ using android::binder::debug::RecordedTransaction; using parcelables::SingleDataParcelable; const String16 kServerName = String16("binderRecordReplay"); +extern std::string kRandomInterfaceName; #define GENERATE_GETTER_SETTER_PRIMITIVE(name, T) \ Status set##name(T input) { \ @@ -81,6 +86,7 @@ public: GENERATE_GETTER_SETTER(String, String16); GENERATE_GETTER_SETTER(SingleDataParcelable, SingleDataParcelable); + GENERATE_GETTER_SETTER(Binder, sp<IBinder>); GENERATE_GETTER_SETTER(BooleanArray, std::vector<bool>); GENERATE_GETTER_SETTER(ByteArray, std::vector<uint8_t>); @@ -91,12 +97,22 @@ public: GENERATE_GETTER_SETTER(DoubleArray, std::vector<double>); GENERATE_GETTER_SETTER(StringArray, std::vector<::android::String16>); GENERATE_GETTER_SETTER(SingleDataParcelableArray, std::vector<SingleDataParcelable>); + + Status setFileDescriptor(unique_fd input) { + mFd = std::move(unique_fd(dup(input))); + return Status::ok(); + } + + Status getFileDescriptor(unique_fd* output) { + *output = std::move(unique_fd(dup(mFd))); + return Status::ok(); + } + unique_fd mFd; }; std::vector<uint8_t> retrieveData(borrowed_fd fd) { struct stat fdStat; EXPECT_TRUE(fstat(fd.get(), &fdStat) != -1); - EXPECT_TRUE(fdStat.st_size != 0); std::vector<uint8_t> buffer(fdStat.st_size); auto readResult = android::base::ReadFully(fd, buffer.data(), fdStat.st_size); @@ -115,6 +131,7 @@ void replayFuzzService(const sp<BpBinder>& binder, const RecordedTransaction& tr // Read the data which has been written to seed corpus ASSERT_EQ(0, lseek(seedFd.get(), 0, SEEK_SET)); std::vector<uint8_t> seedData = retrieveData(seedFd); + EXPECT_TRUE(seedData.size() != 0); // use fuzzService to replay the corpus FuzzedDataProvider provider(seedData.data(), seedData.size()); @@ -148,7 +165,14 @@ public: template <typename T, typename U> void recordReplay(Status (IBinderRecordReplayTest::*set)(T), U recordedValue, Status (IBinderRecordReplayTest::*get)(U*), U changedValue) { - auto replayFunctions = {&replayBinder, &replayFuzzService}; + using ReplayFunc = decltype(&replayFuzzService); + vector<ReplayFunc> replayFunctions = {&replayFuzzService}; + if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) { + // Parcel retrieved from record replay doesn't have object information. use it for + // replaying primitive types only. + replayFunctions.push_back(&replayBinder); + } + for (auto replayFunc : replayFunctions) { unique_fd fd(open("/data/local/tmp/binderRecordReplayTest.rec", O_RDWR | O_CREAT | O_CLOEXEC, 0666)); @@ -156,7 +180,7 @@ public: // record a transaction mBpBinder->startRecordingBinder(fd); - auto status = (*mInterface.*set)(recordedValue); + auto status = (*mInterface.*set)(std::move(recordedValue)); EXPECT_TRUE(status.isOk()); mBpBinder->stopRecordingBinder(); @@ -164,16 +188,22 @@ public: U output; status = (*mInterface.*get)(&output); EXPECT_TRUE(status.isOk()); - EXPECT_EQ(output, recordedValue); + + // Expect this equal only if types are primitives + if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) { + EXPECT_EQ(output, recordedValue); + } // write over the existing state - status = (*mInterface.*set)(changedValue); + status = (*mInterface.*set)(std::move(changedValue)); EXPECT_TRUE(status.isOk()); status = (*mInterface.*get)(&output); EXPECT_TRUE(status.isOk()); - EXPECT_EQ(output, changedValue); + if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) { + EXPECT_EQ(output, changedValue); + } // replay transaction ASSERT_EQ(0, lseek(fd.get(), 0, SEEK_SET)); @@ -186,7 +216,23 @@ public: status = (*mInterface.*get)(&output); EXPECT_TRUE(status.isOk()); - EXPECT_EQ(output, recordedValue); + + // FDs and binders will be replaced with random fd and random binders + if constexpr (std::is_same_v<U, unique_fd>) { + // verify that replayed fd is /dev/null. This is being replayed from random_fd.cpp + // and choosing /dav/null while generating seed in binder2corpus + std::string fdPath = "/proc/self/fd/" + std::to_string(output.get()); + char path[PATH_MAX]; + ASSERT_GT(readlink(fdPath.c_str(), path, sizeof(path)), 0); + EXPECT_EQ(strcmp("/dev/null", path), 0); + } else if constexpr (std::is_same_v<U, sp<IBinder>>) { + // This is binder is replayed from random_binder.cpp using seed data which writes + // this interface. + EXPECT_EQ(String16(kRandomInterfaceName.c_str(), kRandomInterfaceName.size()), + output->getInterfaceDescriptor()); + } else { + ASSERT_EQ(recordedValue, output); + } } } @@ -319,6 +365,32 @@ TEST_F(BinderRecordReplayTest, ReplaySingleDataParcelableArray) { &IBinderRecordReplayTest::getSingleDataParcelableArray, changed); } +TEST_F(BinderRecordReplayTest, ReplayBinder) { + vector<uint8_t> data = {0x8A, 0x19, 0x0D, 0x44, 0x37, 0x0D, 0x38, 0x5E, 0x9B, 0xAA, 0xF3, 0xDA}; + sp<IBinder> saved = new RandomBinder(String16("random_interface"), std::move(data)); + sp<IBinder> changed = IInterface::asBinder(defaultServiceManager()); + recordReplay(&IBinderRecordReplayTest::setBinder, saved, &IBinderRecordReplayTest::getBinder, + changed); +} + +TEST_F(BinderRecordReplayTest, ReplayFd) { + // Write something to both fds we are setting + unique_fd saved(open("/data/local/tmp/test_fd", O_RDWR | O_CREAT | O_CLOEXEC, 0666)); + std::string contentSaved = "This will be never read again for recorded fd!"; + CHECK(android::base::WriteFully(saved, contentSaved.data(), contentSaved.size())) + << saved.get(); + + unique_fd changed(open("/data/local/tmp/test_des", O_RDWR | O_CREAT | O_CLOEXEC, 0666)); + std::string contentChanged = "This will be never read again from changed fd!"; + CHECK(android::base::WriteFully(changed, contentChanged.data(), contentChanged.size())) + << changed.get(); + + // When fds are replayed, it will be replaced by /dev/null..reading from it should yield + // null data + recordReplay(&IBinderRecordReplayTest::setFileDescriptor, std::move(unique_fd(dup(saved))), + &IBinderRecordReplayTest::getFileDescriptor, std::move(unique_fd(dup(changed)))); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp index 83db6c9b6d..fbab8f08a9 100644 --- a/libs/binder/tests/parcel_fuzzer/Android.bp +++ b/libs/binder/tests/parcel_fuzzer/Android.bp @@ -131,6 +131,13 @@ cc_library { "libcutils", "libutils", ], + static_libs: [ + "libbinder_random_parcel", + ], + include_dirs: [ + "bionic/libc/kernel/android/uapi/", + "bionic/libc/kernel/uapi/", + ], local_include_dirs: [ "include_random_parcel_seeds", ], @@ -140,8 +147,12 @@ cc_library { cc_binary_host { name: "binder2corpus", static_libs: [ + "libbinder_random_parcel", "libbinder_random_parcel_seeds", ], + cflags: [ + "-DBINDER_WITH_KERNEL_IPC", + ], srcs: [ "binder2corpus/binder2corpus.cpp", ], @@ -149,5 +160,6 @@ cc_binary_host { "libbase", "libbinder", "libutils", + "libcutils", ], } diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h index 8fc9263b98..7a1688b7b7 100644 --- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h +++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h @@ -16,11 +16,25 @@ #pragma once +#include <binder/Binder.h> #include <binder/IBinder.h> #include <fuzzer/FuzzedDataProvider.h> namespace android { +class RandomBinder : public BBinder { +public: + RandomBinder(const String16& descriptor, std::vector<uint8_t>&& bytes); + const String16& getInterfaceDescriptor() const override; + status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override; + +private: + String16 mDescriptor; + // note may not all be used + std::vector<uint8_t> mBytes; + FuzzedDataProvider mProvider; +}; + // Get a random binder object for use in fuzzing. // // May return nullptr. diff --git a/libs/binder/tests/parcel_fuzzer/random_binder.cpp b/libs/binder/tests/parcel_fuzzer/random_binder.cpp index 8a1fecb212..f41c35bfbe 100644 --- a/libs/binder/tests/parcel_fuzzer/random_binder.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_binder.cpp @@ -21,56 +21,52 @@ #include <binder/IInterface.h> #include <binder/IServiceManager.h> +size_t kRandomInterfaceLength = 50; namespace android { -class RandomBinder : public BBinder { -public: - RandomBinder(const String16& descriptor, std::vector<uint8_t>&& bytes) - : mDescriptor(descriptor), - mBytes(std::move(bytes)), - mProvider(mBytes.data(), mBytes.size()) {} - const String16& getInterfaceDescriptor() const override { return mDescriptor; } +RandomBinder::RandomBinder(const String16& descriptor, std::vector<uint8_t>&& bytes) + : mDescriptor(descriptor), + mBytes(std::move(bytes)), + mProvider(mBytes.data(), mBytes.size()) {} - status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override { - (void)code; - (void)data; - (void)reply; - (void)flags; // note - for maximum coverage even ignore if oneway +const String16& RandomBinder::getInterfaceDescriptor() const { + return mDescriptor; +} - if (mProvider.ConsumeBool()) { - return mProvider.ConsumeIntegral<status_t>(); - } +status_t RandomBinder::onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags) { + (void)code; + (void)data; + (void)reply; + (void)flags; // note - for maximum coverage even ignore if oneway - if (reply == nullptr) return OK; + if (mProvider.ConsumeBool()) { + return mProvider.ConsumeIntegral<status_t>(); + } - // TODO: things we could do to increase state space - // - also pull FDs and binders from 'data' - // (optionally combine these into random parcel 'options') - // - also pull FDs and binders from random parcel 'options' - RandomParcelOptions options; + if (reply == nullptr) return OK; - // random output - std::vector<uint8_t> subData = mProvider.ConsumeBytes<uint8_t>( - mProvider.ConsumeIntegralInRange<size_t>(0, mProvider.remaining_bytes())); - fillRandomParcel(reply, FuzzedDataProvider(subData.data(), subData.size()), &options); + // TODO: things we could do to increase state space + // - also pull FDs and binders from 'data' + // (optionally combine these into random parcel 'options') + // - also pull FDs and binders from random parcel 'options' + RandomParcelOptions options; - return OK; - } + // random output + std::vector<uint8_t> subData = mProvider.ConsumeBytes<uint8_t>( + mProvider.ConsumeIntegralInRange<size_t>(0, mProvider.remaining_bytes())); + fillRandomParcel(reply, FuzzedDataProvider(subData.data(), subData.size()), &options); -private: - String16 mDescriptor; - - // note may not all be used - std::vector<uint8_t> mBytes; - FuzzedDataProvider mProvider; -}; + return OK; +} sp<IBinder> getRandomBinder(FuzzedDataProvider* provider) { auto makeFunc = provider->PickValueInArray<const std::function<sp<IBinder>()>>({ [&]() { // descriptor is the length of a class name, e.g. // "some.package.Foo" - std::string str = provider->ConsumeRandomLengthString(100 /*max length*/); + std::string str = + provider->ConsumeRandomLengthString(kRandomInterfaceLength /*max length*/); // arbitrarily consume remaining data to create a binder that can return // random results - coverage guided fuzzer should ensure all of the remaining diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp index 4e58dc4899..62b84330cd 100644 --- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp @@ -73,7 +73,7 @@ void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOpti return; } - if (options->extraFds.size() > 0 && provider.ConsumeBool()) { + if (provider.ConsumeBool() && options->extraFds.size() > 0) { const unique_fd& fd = options->extraFds.at( provider.ConsumeIntegralInRange<size_t>(0, options->extraFds.size() - @@ -102,7 +102,7 @@ void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOpti } sp<IBinder> binder; - if (options->extraBinders.size() > 0 && provider.ConsumeBool()) { + if (provider.ConsumeBool() && options->extraBinders.size() > 0) { binder = options->extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, options->extraBinders diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp index 7b3c80642b..fd9777a916 100644 --- a/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp @@ -14,16 +14,26 @@ * limitations under the License. */ +#include <linux/android/binder.h> + #include <android-base/logging.h> +#include <binder/Parcel.h> #include <binder/RecordedTransaction.h> #include <fuzzseeds/random_parcel_seeds.h> +#include <stack> +#include <string> #include "../../file.h" using android::binder::borrowed_fd; using android::binder::WriteFully; +using std::stack; + +extern size_t kRandomInterfaceLength; +// Keep this in sync with max_length in random_binder.cpp while creating a RandomBinder +std::string kRandomInterfaceName(kRandomInterfaceLength, 'i'); namespace android { namespace impl { @@ -66,6 +76,162 @@ void writeReversedBuffer(std::vector<uint8_t>& integralBuffer, T val) { } // namespace impl +struct ProviderMetadata { + size_t position; + size_t value; + + ProviderMetadata() { + value = 0; + position = 0; + } +}; + +// Assuming current seed path is inside the fillRandomParcel function, start of the loop. +void writeRandomBinder(borrowed_fd fd, vector<uint8_t>& fillParcelBuffer, + stack<ProviderMetadata>& remainingPositions) { + // Choose 2 index in array + size_t fillFuncIndex = 2; + impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2), + fillFuncIndex); + + // navigate to getRandomBinder. provide consume bool false + bool flag = false; + impl::writeReversedBuffer(fillParcelBuffer, flag); + + // selecting RandomBinder, other binders in the list are not recorded as KernelObjects + size_t randomBinderIndex = 0; + impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2), + randomBinderIndex); + + // write random string of length 100 in actual buffer array. + CHECK(WriteFully(fd, kRandomInterfaceName.c_str(), kRandomInterfaceName.size())) << fd.get(); + + // These will be bytes which are used inside of RandomBinder + // simplest path for these bytes is going to be consume bool -> return random status + vector<uint8_t> randomBinderBuffer; + + bool returnRandomInt = true; + impl::writeReversedBuffer(randomBinderBuffer, returnRandomInt); + + status_t randomStatus = 0; + impl::writeReversedBuffer(randomBinderBuffer, randomStatus); + + // write integral in range to consume bytes for random binder + ProviderMetadata providerData; + providerData.position = fillParcelBuffer.size(); + providerData.value = randomBinderBuffer.size(); + remainingPositions.push(providerData); + + // Write to fd + CHECK(WriteFully(fd, randomBinderBuffer.data(), randomBinderBuffer.size())) << fd.get(); +} + +// Assuming current seed path is inside the fillRandomParcelFunction, start of the loop. +void writeRandomFd(vector<uint8_t>& fillParcelBuffer) { + // path to random fd + size_t fillFuncIndex = 1; + impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2), + fillFuncIndex); + + bool flag = false; + impl::writeReversedBuffer(fillParcelBuffer, flag); + + // go for /dev/null index 1 + size_t fdIndex = 1; + impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(3), + fdIndex); +} + +void writeParcelData(borrowed_fd fd, vector<uint8_t>& fillParcelBuffer, + stack<ProviderMetadata>& remainingPositions, const uint8_t* data, size_t start, + size_t length) { + // need to write parcel data till next offset with instructions to pick random bytes till offset + size_t fillFuncIndex = 0; + impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2), + fillFuncIndex); + + // provide how much bytes to read in control buffer + ProviderMetadata providerData; + providerData.position = fillParcelBuffer.size(); + providerData.value = length; + remainingPositions.push(providerData); + + // provide actual bytes + CHECK(WriteFully(fd, data + start, length)) << fd.get(); +} + +/** + * Generate sequence of copy data, write fd and write binder instructions and required data. + * Data which will be read using consumeBytes is written to fd directly. Data which is read in + * form integer is consumed from rear end FuzzedDataProvider. So insert it in fillParcelBuffer and + * then write to fd + */ +size_t regenerateParcel(borrowed_fd fd, vector<uint8_t>& fillParcelBuffer, const Parcel& p, + size_t dataSize, const vector<uint64_t>& objectOffsets) { + stack<ProviderMetadata> remainingPositions; + size_t copiedDataPosition = 0; + const uint8_t* parcelData = p.data(); + size_t numBinders = 0; + size_t numFds = 0; + + for (auto offset : objectOffsets) { + // Check what type of object is present here + const flat_binder_object* flatObject = + reinterpret_cast<const flat_binder_object*>(parcelData + offset); + // Copy till the object offset + writeParcelData(fd, fillParcelBuffer, remainingPositions, parcelData, copiedDataPosition, + offset - copiedDataPosition); + copiedDataPosition = offset; + if (flatObject->hdr.type == BINDER_TYPE_BINDER || + flatObject->hdr.type == BINDER_TYPE_HANDLE) { + writeRandomBinder(fd, fillParcelBuffer, remainingPositions); + numBinders++; + // In case of binder, stability is written after the binder object. + // We want to move the copiedDataPosition further to account for this stability field + copiedDataPosition += sizeof(int32_t) + sizeof(flat_binder_object); + } else if (flatObject->hdr.type == BINDER_TYPE_FD) { + writeRandomFd(fillParcelBuffer); + numFds++; + copiedDataPosition += sizeof(flat_binder_object); + } + } + + if (copiedDataPosition < dataSize) { + // copy remaining data from recorded parcel -> last Object to end of the data + writeParcelData(fd, fillParcelBuffer, remainingPositions, parcelData, copiedDataPosition, + dataSize - copiedDataPosition); + } + + // We need to write bytes for selecting integer within range of 0 to provide.remaining_bytes() + // is called. + size_t totalWrittenBytes = dataSize - (sizeof(flat_binder_object) * objectOffsets.size()) - + (sizeof(int32_t) * numBinders) + + (kRandomInterfaceName.size() /*Interface String*/ + sizeof(bool) + sizeof(status_t)) * + numBinders; + + // Code in fuzzService relies on provider.remaining_bytes() to select random bytes using + // consume integer. use the calculated remaining_bytes to generate byte buffer which can + // generate required fds and binders in fillRandomParcel function. + while (!remainingPositions.empty()) { + auto meta = remainingPositions.top(); + remainingPositions.pop(); + size_t remainingBytes = totalWrittenBytes + fillParcelBuffer.size() - meta.position; + + vector<uint8_t> remReversedBytes; + impl::writeReversedBuffer(remReversedBytes, static_cast<size_t>(0), remainingBytes, + meta.value); + // Check the order of buffer which is being written + fillParcelBuffer.insert(fillParcelBuffer.end() - meta.position, remReversedBytes.begin(), + remReversedBytes.end()); + } + + return totalWrittenBytes; +} + +/** + * Current corpus format + * |Reserved bytes(8)|parcel data|fillParcelBuffer|integralBuffer| + */ void generateSeedsFromRecording(borrowed_fd fd, const binder::debug::RecordedTransaction& transaction) { // Write Reserved bytes for future use @@ -123,17 +289,9 @@ void generateSeedsFromRecording(borrowed_fd fd, uint8_t writeHeaderInternal = 0; impl::writeReversedBuffer(fillParcelBuffer, writeHeaderInternal); - // Choose to write data in parcel - size_t fillFuncIndex = 0; - impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2), - fillFuncIndex); - - // Write parcel data size from recorded transaction - size_t toWrite = transaction.getDataParcel().dataBufferSize(); - impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), toWrite, toWrite); - - // Write parcel data with size towrite from recorded transaction - CHECK(WriteFully(fd, dataParcel.data(), toWrite)) << fd.get(); + auto objectMetadata = transaction.getObjectOffsets(); + size_t toWrite = regenerateParcel(fd, fillParcelBuffer, dataParcel, dataParcel.dataBufferSize(), + objectMetadata); // Write Fill Parcel buffer size in integralBuffer so that fuzzService knows size of data size_t subDataSize = toWrite + fillParcelBuffer.size(); diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index 462ce6e14f..15e8744713 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -3,6 +3,7 @@ // Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) // to integrate with auto-test framework. package { + default_team: "trendy_team_android_core_graphics_stack", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" diff --git a/libs/gui/tests/AndroidTest.xml b/libs/gui/tests/AndroidTest.xml index 31b10d7f54..b4ccf87349 100644 --- a/libs/gui/tests/AndroidTest.xml +++ b/libs/gui/tests/AndroidTest.xml @@ -18,6 +18,7 @@ <option name="cleanup" value="true" /> <option name="push" value="libgui_test->/data/local/tmp/libgui_test" /> </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device --> <option name="screen-always-on" value="on" /> diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 9c7c0c19ed..ccc83231fa 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -20,12 +20,14 @@ #include <unistd.h> #include <ctype.h> +#include <android-base/properties.h> #include <android-base/stringprintf.h> #include <ftl/enum.h> #include <gui/constants.h> #include <input/InputDevice.h> #include <input/InputEventLabels.h> +using android::base::GetProperty; using android::base::StringPrintf; namespace android { @@ -96,21 +98,22 @@ std::string getInputDeviceConfigurationFilePathByName( // Treblized input device config files will be located /product/usr, /system_ext/usr, // /odm/usr or /vendor/usr. - // These files may also be in the com.android.input.config APEX. - const char* rootsForPartition[]{ - "/product", - "/system_ext", - "/odm", - "/vendor", - "/apex/com.android.input.config/etc", - getenv("ANDROID_ROOT"), + std::vector<std::string> pathPrefixes{ + "/product/usr/", + "/system_ext/usr/", + "/odm/usr/", + "/vendor/usr/", }; - for (size_t i = 0; i < size(rootsForPartition); i++) { - if (rootsForPartition[i] == nullptr) { - continue; - } - path = rootsForPartition[i]; - path += "/usr/"; + // These files may also be in the APEX pointed by input_device.config_file.apex sysprop. + if (auto apex = GetProperty("input_device.config_file.apex", ""); !apex.empty()) { + pathPrefixes.push_back("/apex/" + apex + "/etc/usr/"); + } + // ANDROID_ROOT may not be set on host + if (auto android_root = getenv("ANDROID_ROOT"); android_root != nullptr) { + pathPrefixes.push_back(std::string(android_root) + "/usr/"); + } + for (const auto& prefix : pathPrefixes) { + path = prefix; appendInputDeviceConfigurationFileRelativePath(path, name, type); #if DEBUG_PROBE ALOGD("Probing for system provided input device configuration file: path='%s'", diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp index 16ed82af7c..82e5427317 100644 --- a/libs/ui/DisplayIdentification.cpp +++ b/libs/ui/DisplayIdentification.cpp @@ -21,6 +21,7 @@ #include <cctype> #include <numeric> #include <optional> +#include <span> #include <log/log.h> @@ -46,6 +47,7 @@ uint64_t shiftMix(uint64_t val) { return val ^ (val >> 47); } +__attribute__((no_sanitize("unsigned-integer-overflow"))) uint64_t hash64Len16(uint64_t u, uint64_t v) { constexpr uint64_t kMul = 0x9ddfea08eb382d69; uint64_t a = (u ^ v) * kMul; @@ -56,6 +58,7 @@ uint64_t hash64Len16(uint64_t u, uint64_t v) { return b; } +__attribute__((no_sanitize("unsigned-integer-overflow"))) uint64_t hash64Len0To16(const char* s, uint64_t len) { constexpr uint64_t k2 = 0x9ae16a3b2f90404f; constexpr uint64_t k3 = 0xc949d7c7509e6557; @@ -81,7 +84,7 @@ uint64_t hash64Len0To16(const char* s, uint64_t len) { return k2; } -using byte_view = std::basic_string_view<uint8_t>; +using byte_view = std::span<const uint8_t>; constexpr size_t kEdidBlockSize = 128; constexpr size_t kEdidHeaderLength = 5; @@ -89,7 +92,8 @@ constexpr size_t kEdidHeaderLength = 5; constexpr uint16_t kVirtualEdidManufacturerId = 0xffffu; std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) { - if (view.size() < kEdidHeaderLength || view[0] || view[1] || view[2] || view[4]) { + if (static_cast<size_t>(view.size()) < kEdidHeaderLength || view[0] || view[1] || view[2] || + view[4]) { return {}; } @@ -164,7 +168,7 @@ Cea861ExtensionBlock parseCea861Block(const byte_view& block) { constexpr size_t kDataBlockHeaderSize = 1; const size_t dataBlockSize = bodyLength + kDataBlockHeaderSize; - if (block.size() < dataBlockOffset + dataBlockSize) { + if (static_cast<size_t>(block.size()) < dataBlockOffset + dataBlockSize) { ALOGW("Invalid EDID: CEA 861 data block is truncated."); break; } @@ -264,7 +268,7 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { } byte_view view(edid.data(), edid.size()); - view.remove_prefix(kDescriptorOffset); + view = view.subspan(kDescriptorOffset); std::string_view displayName; std::string_view serialNumber; @@ -274,13 +278,13 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { constexpr size_t kDescriptorLength = 18; for (size_t i = 0; i < kDescriptorCount; i++) { - if (view.size() < kDescriptorLength) { + if (static_cast<size_t>(view.size()) < kDescriptorLength) { break; } if (const auto type = getEdidDescriptorType(view)) { byte_view descriptor(view.data(), kDescriptorLength); - descriptor.remove_prefix(kEdidHeaderLength); + descriptor = descriptor.subspan(kEdidHeaderLength); switch (*type) { case 0xfc: @@ -295,7 +299,7 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { } } - view.remove_prefix(kDescriptorLength); + view = view.subspan(kDescriptorLength); } std::string_view modelString = displayName; @@ -327,8 +331,8 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { const size_t numExtensions = edid[kNumExtensionsOffset]; view = byte_view(edid.data(), edid.size()); for (size_t blockNumber = 1; blockNumber <= numExtensions; blockNumber++) { - view.remove_prefix(kEdidBlockSize); - if (view.size() < kEdidBlockSize) { + view = view.subspan(kEdidBlockSize); + if (static_cast<size_t>(view.size()) < kEdidBlockSize) { ALOGW("Invalid EDID: block %zu is truncated.", blockNumber); break; } @@ -399,4 +403,4 @@ uint64_t cityHash64Len0To16(std::string_view sv) { return hash64Len0To16(sv.data(), len); } -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp index c3b2d3d808..123bef4a4f 100644 --- a/libs/ui/Gralloc5.cpp +++ b/libs/ui/Gralloc5.cpp @@ -83,10 +83,18 @@ static void *loadIMapperLibrary() { return nullptr; } - std::string lib_name = "mapper." + mapperSuffix + ".so"; - void *so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW); + void* so = nullptr; + // TODO(b/322384429) switch this to __ANDROID_API_V__ when V is finalized + // TODO(b/302113279) use __ANDROID_VENDOR_API__ for vendor variant + if (__builtin_available(android __ANDROID_API_FUTURE__, *)) { + so = AServiceManager_openDeclaredPassthroughHal("mapper", mapperSuffix.c_str(), + RTLD_LOCAL | RTLD_NOW); + } else { + std::string lib_name = "mapper." + mapperSuffix + ".so"; + so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW); + } if (!so) { - ALOGE("Failed to load %s", lib_name.c_str()); + ALOGE("Failed to load mapper.%s.so", mapperSuffix.c_str()); } return so; }(); diff --git a/libs/vibrator/fuzzer/Android.bp b/libs/vibrator/fuzzer/Android.bp index cb063af2f6..faa77ca9df 100644 --- a/libs/vibrator/fuzzer/Android.bp +++ b/libs/vibrator/fuzzer/Android.bp @@ -18,6 +18,7 @@ */ package { + default_team: "trendy_team_haptics_framework", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" diff --git a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h index 2d0a4ea6ec..371ed89fc9 100644 --- a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h +++ b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h @@ -17,12 +17,12 @@ namespace rpc { // C strings more efficient by avoiding unnecessary copies when remote method // signatures specify std::basic_string arguments or return values. template <typename CharT = std::string::value_type, - typename Traits = std::char_traits<CharT>> + typename Traits = std::char_traits<std::remove_cv_t<CharT>>> class StringWrapper { public: // Define types in the style of STL strings to support STL operators. typedef Traits traits_type; - typedef typename Traits::char_type value_type; + typedef CharT value_type; typedef std::size_t size_type; typedef value_type& reference; typedef const value_type& const_reference; diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp index 4e2a6fbf87..e5d2b705c3 100644 --- a/services/inputflinger/benchmarks/Android.bp +++ b/services/inputflinger/benchmarks/Android.bp @@ -1,4 +1,5 @@ package { + default_team: "trendy_team_input_framework", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index 1585fddfb3..a5564d2c7d 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -13,6 +13,7 @@ // limitations under the License. package { + default_team: "trendy_team_input_framework", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp index 47b0824fd0..59af4934fa 100644 --- a/services/inputflinger/tests/fuzzers/Android.bp +++ b/services/inputflinger/tests/fuzzers/Android.bp @@ -13,6 +13,7 @@ // limitations under the License. package { + default_team: "trendy_team_input_framework", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp index a468146bc0..5437995899 100644 --- a/services/vibratorservice/benchmarks/Android.bp +++ b/services/vibratorservice/benchmarks/Android.bp @@ -13,6 +13,7 @@ // limitations under the License. package { + default_team: "trendy_team_haptics_framework", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp index 32947246d8..be71dc2ce3 100644 --- a/services/vibratorservice/test/Android.bp +++ b/services/vibratorservice/test/Android.bp @@ -13,6 +13,7 @@ // limitations under the License. package { + default_team: "trendy_team_haptics_framework", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" |