Merge "libbinder_ndk_unit_test: set threadpool max to 0" into main
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 71a8740..9399c73 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -4029,24 +4029,37 @@
return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Received a null auth token");
}
- // Authenticate to check the targeting file is the same inode as the authFd.
+ // Authenticate to check the targeting file is the same inode as the authFd. With O_PATH, we
+ // prevent a malicious client from blocking installd by providing a path to FIFO. After the
+ // authentication, the actual open is safe.
sp<IBinder> authTokenBinder = IInterface::asBinder(authToken)->localBinder();
if (authTokenBinder == nullptr) {
return exception(binder::Status::EX_SECURITY, "Received a non-local auth token");
}
- auto authTokenInstance = sp<FsveritySetupAuthToken>::cast(authTokenBinder);
- unique_fd rfd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
- struct stat stFromPath;
- if (fstat(rfd.get(), &stFromPath) < 0) {
- *_aidl_return = errno;
+ unique_fd pathFd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_PATH));
+ // Returns a constant errno to avoid one app probing file existence of the others, before the
+ // authentication is done.
+ const int kFixedErrno = EPERM;
+ if (pathFd.get() < 0) {
+ PLOG(DEBUG) << "Failed to open the path";
+ *_aidl_return = kFixedErrno;
return ok();
}
+ std::string procFdPath(StringPrintf("/proc/self/fd/%d", pathFd.get()));
+ struct stat stFromPath;
+ if (stat(procFdPath.c_str(), &stFromPath) < 0) {
+ PLOG(DEBUG) << "Failed to stat proc fd " << pathFd.get() << " -> " << filePath;
+ *_aidl_return = kFixedErrno;
+ return ok();
+ }
+ auto authTokenInstance = sp<FsveritySetupAuthToken>::cast(authTokenBinder);
if (!authTokenInstance->isSameStat(stFromPath)) {
LOG(DEBUG) << "FD authentication failed";
- *_aidl_return = EPERM;
+ *_aidl_return = kFixedErrno;
return ok();
}
+ unique_fd rfd(open(procFdPath.c_str(), O_RDONLY | O_CLOEXEC));
fsverity_enable_arg arg = {};
arg.version = 1;
arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index f2b578a..023491f 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -194,6 +194,12 @@
});
}
+static void unlink_path(const std::string& path) {
+ if (unlink(path.c_str()) < 0) {
+ PLOG(DEBUG) << "Failed to unlink " + path;
+ }
+}
+
class ServiceTest : public testing::Test {
protected:
InstalldNativeService* service;
@@ -555,7 +561,7 @@
TEST_F(FsverityTest, enableFsverity) {
const std::string path = kTestPath + "/foo";
create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
- UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+ UniqueFile raii(/*fd=*/-1, path, &unlink_path);
// Expect to fs-verity setup to succeed
sp<IFsveritySetupAuthToken> authToken;
@@ -573,7 +579,7 @@
TEST_F(FsverityTest, enableFsverity_nullAuthToken) {
const std::string path = kTestPath + "/foo";
create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
- UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+ UniqueFile raii(/*fd=*/-1, path, &unlink_path);
// Verity null auth token fails
sp<IFsveritySetupAuthToken> authToken;
@@ -586,7 +592,7 @@
TEST_F(FsverityTest, enableFsverity_differentFile) {
const std::string path = kTestPath + "/foo";
create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
- UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+ UniqueFile raii(/*fd=*/-1, path, &unlink_path);
// Expect to fs-verity setup to succeed
sp<IFsveritySetupAuthToken> authToken;
@@ -597,17 +603,36 @@
// Verity auth token does not work for a different file
const std::string anotherPath = kTestPath + "/bar";
ASSERT_TRUE(android::base::WriteStringToFile("content", anotherPath));
- UniqueFile raii2(/*fd=*/-1, anotherPath, [](const std::string& path) { unlink(path.c_str()); });
+ UniqueFile raii2(/*fd=*/-1, anotherPath, &unlink_path);
int32_t errno_local;
status = service->enableFsverity(authToken, anotherPath, "fake.package.name", &errno_local);
EXPECT_TRUE(status.isOk());
EXPECT_NE(errno_local, 0);
}
+TEST_F(FsverityTest, enableFsverity_errnoBeforeAuthenticated) {
+ const std::string path = kTestPath + "/foo";
+ create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
+ UniqueFile raii(/*fd=*/-1, path, &unlink_path);
+
+ // Expect to fs-verity setup to succeed
+ sp<IFsveritySetupAuthToken> authToken;
+ binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
+ EXPECT_TRUE(status.isOk());
+ EXPECT_TRUE(authToken != nullptr);
+
+ // Verity errno before the fd authentication is constant (EPERM)
+ int32_t errno_local;
+ status = service->enableFsverity(authToken, path + "-non-exist", "fake.package.name",
+ &errno_local);
+ EXPECT_TRUE(status.isOk());
+ EXPECT_EQ(errno_local, EPERM);
+}
+
TEST_F(FsverityTest, createFsveritySetupAuthToken_ReadonlyFdDoesNotAuthenticate) {
const std::string path = kTestPath + "/foo";
create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
- UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+ UniqueFile raii(/*fd=*/-1, path, &unlink_path);
// Expect the fs-verity setup to fail
sp<IFsveritySetupAuthToken> authToken;
@@ -619,7 +644,7 @@
const std::string path = kTestPath + "/foo";
// Simulate world-writable file owned by another app
create_with_content(path, kTestAppUid + 1, kTestAppUid + 1, 0666, "content");
- UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+ UniqueFile raii(/*fd=*/-1, path, &unlink_path);
// Expect the fs-verity setup to fail
sp<IFsveritySetupAuthToken> authToken;
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 6115da7..5cdcb23 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -232,6 +232,11 @@
return static_cast<HelpCommand*>(help)->usageOfCommand(mCommand);
}
+ // After Lshal::main() finishes, caller may call _exit(), causing debug
+ // information to prematurely ends. Hence flush().
+ err().flush();
+ out().flush();
+
return status;
}
diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h
index 7cffcf8..1576486 100644
--- a/cmds/lshal/NullableOStream.h
+++ b/cmds/lshal/NullableOStream.h
@@ -59,6 +59,11 @@
operator bool() const { // NOLINT(google-explicit-constructor)
return mOs != nullptr;
}
+ void flush() {
+ if (mOs) {
+ mOs->flush();
+ }
+ }
private:
template<typename>
friend class NullableOStream;
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index e00c2a2..3897197 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -95,6 +95,16 @@
static_libs: ["libgmock"],
}
+cc_test_host {
+ name: "servicemanager_unittest",
+ test_suites: ["general-tests"],
+ defaults: ["servicemanager_defaults"],
+ srcs: [
+ "ServiceManagerUnittest.cpp",
+ ],
+ static_libs: ["libgmock"],
+}
+
cc_fuzz {
name: "servicemanager_fuzzer",
defaults: [
diff --git a/cmds/servicemanager/NameUtil.h b/cmds/servicemanager/NameUtil.h
new file mode 100644
index 0000000..b080939
--- /dev/null
+++ b/cmds/servicemanager/NameUtil.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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 <string>
+#include <string_view>
+
+#include <android-base/strings.h>
+
+namespace android {
+
+#ifndef VENDORSERVICEMANAGER
+
+struct NativeName {
+ std::string package;
+ std::string instance;
+
+ // Parse {package}/{instance}
+ static bool fill(std::string_view name, NativeName* nname) {
+ size_t slash = name.find('/');
+ if (slash == std::string_view::npos) {
+ return false;
+ }
+ // no extra slashes
+ if (name.find('/', slash + 1) != std::string_view::npos) {
+ return false;
+ }
+ // every part should be non-empty
+ if (slash == 0 || slash + 1 == name.size()) {
+ return false;
+ }
+ // no dots in package
+ if (name.rfind('.', slash) != std::string_view::npos) {
+ return false;
+ }
+ nname->package = name.substr(0, slash);
+ nname->instance = name.substr(slash + 1);
+ return true;
+ }
+};
+
+#endif
+
+} // namespace android
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 77989d1..bf85e61 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -35,6 +35,8 @@
#include <vintf/constants.h>
#endif // !VENDORSERVICEMANAGER
+#include "NameUtil.h"
+
using ::android::binder::Status;
using ::android::internal::Stability;
@@ -84,6 +86,10 @@
return false;
}
+static std::string getNativeInstanceName(const vintf::ManifestInstance& instance) {
+ return instance.package() + "/" + instance.instance();
+}
+
struct AidlName {
std::string package;
std::string iface;
@@ -105,7 +111,26 @@
}
};
+static std::string getAidlInstanceName(const vintf::ManifestInstance& instance) {
+ return instance.package() + "." + instance.interface() + "/" + instance.instance();
+}
+
static bool isVintfDeclared(const std::string& name) {
+ NativeName nname;
+ if (NativeName::fill(name, &nname)) {
+ bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
+ if (mwd.manifest->hasNativeInstance(nname.package, nname.instance)) {
+ ALOGI("Found %s in %s VINTF manifest.", name.c_str(), mwd.description);
+ return true; // break
+ }
+ return false; // continue
+ });
+ if (!found) {
+ ALOGI("Could not find %s in the VINTF manifest.", name.c_str());
+ }
+ return found;
+ }
+
AidlName aname;
if (!AidlName::fill(name, &aname)) return false;
@@ -144,13 +169,31 @@
}
static std::optional<std::string> getVintfUpdatableApex(const std::string& name) {
+ NativeName nname;
+ if (NativeName::fill(name, &nname)) {
+ std::optional<std::string> updatableViaApex;
+
+ forEachManifest([&](const ManifestWithDescription& mwd) {
+ bool cont = mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+ if (manifestInstance.format() != vintf::HalFormat::NATIVE) return true;
+ if (manifestInstance.package() != nname.package) return true;
+ if (manifestInstance.instance() != nname.instance) return true;
+ updatableViaApex = manifestInstance.updatableViaApex();
+ return false; // break (libvintf uses opposite convention)
+ });
+ return !cont;
+ });
+
+ return updatableViaApex;
+ }
+
AidlName aname;
if (!AidlName::fill(name, &aname)) return std::nullopt;
std::optional<std::string> updatableViaApex;
forEachManifest([&](const ManifestWithDescription& mwd) {
- mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+ bool cont = mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
if (manifestInstance.package() != aname.package) return true;
if (manifestInstance.interface() != aname.iface) return true;
@@ -158,31 +201,31 @@
updatableViaApex = manifestInstance.updatableViaApex();
return false; // break (libvintf uses opposite convention)
});
- if (updatableViaApex.has_value()) return true; // break (found match)
- return false; // continue
+ return !cont;
});
return updatableViaApex;
}
-static std::vector<std::string> getVintfUpdatableInstances(const std::string& apexName) {
- std::vector<std::string> instances;
+static std::vector<std::string> getVintfUpdatableNames(const std::string& apexName) {
+ std::vector<std::string> names;
forEachManifest([&](const ManifestWithDescription& mwd) {
mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
- if (manifestInstance.format() == vintf::HalFormat::AIDL &&
- manifestInstance.updatableViaApex().has_value() &&
+ if (manifestInstance.updatableViaApex().has_value() &&
manifestInstance.updatableViaApex().value() == apexName) {
- std::string aname = manifestInstance.package() + "." +
- manifestInstance.interface() + "/" + manifestInstance.instance();
- instances.push_back(aname);
+ if (manifestInstance.format() == vintf::HalFormat::NATIVE) {
+ names.push_back(getNativeInstanceName(manifestInstance));
+ } else if (manifestInstance.format() == vintf::HalFormat::AIDL) {
+ names.push_back(getAidlInstanceName(manifestInstance));
+ }
}
return true; // continue (libvintf uses opposite convention)
});
return false; // continue
});
- return instances;
+ return names;
}
static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
@@ -217,6 +260,18 @@
static std::vector<std::string> getVintfInstances(const std::string& interface) {
size_t lastDot = interface.rfind('.');
if (lastDot == std::string::npos) {
+ // This might be a package for native instance.
+ std::vector<std::string> ret;
+ (void)forEachManifest([&](const ManifestWithDescription& mwd) {
+ auto instances = mwd.manifest->getNativeInstances(interface);
+ ret.insert(ret.end(), instances.begin(), instances.end());
+ return false; // continue
+ });
+ // If found, return it without error log.
+ if (!ret.empty()) {
+ return ret;
+ }
+
ALOGE("VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) "
"but got: %s",
interface.c_str());
@@ -594,20 +649,20 @@
std::vector<std::string>* outReturn) {
auto ctx = mAccess->getCallingContext();
- std::vector<std::string> apexUpdatableInstances;
+ std::vector<std::string> apexUpdatableNames;
#ifndef VENDORSERVICEMANAGER
- apexUpdatableInstances = getVintfUpdatableInstances(apexName);
+ apexUpdatableNames = getVintfUpdatableNames(apexName);
#endif
outReturn->clear();
- for (const std::string& instance : apexUpdatableInstances) {
- if (mAccess->canFind(ctx, instance)) {
- outReturn->push_back(instance);
+ for (const std::string& name : apexUpdatableNames) {
+ if (mAccess->canFind(ctx, name)) {
+ outReturn->push_back(name);
}
}
- if (outReturn->size() == 0 && apexUpdatableInstances.size() != 0) {
+ if (outReturn->size() == 0 && apexUpdatableNames.size() != 0) {
return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
diff --git a/cmds/servicemanager/ServiceManagerUnittest.cpp b/cmds/servicemanager/ServiceManagerUnittest.cpp
new file mode 100644
index 0000000..39d20b0
--- /dev/null
+++ b/cmds/servicemanager/ServiceManagerUnittest.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 <gtest/gtest.h>
+
+#include "NameUtil.h"
+
+namespace android {
+
+TEST(ServiceManager, NativeName) {
+ NativeName nname;
+ EXPECT_TRUE(NativeName::fill("mapper/default", &nname));
+ EXPECT_EQ("mapper", nname.package);
+ EXPECT_EQ("default", nname.instance);
+}
+
+TEST(ServiceManager, NativeName_Malformed) {
+ NativeName nname;
+ EXPECT_FALSE(NativeName::fill("mapper", &nname));
+ EXPECT_FALSE(NativeName::fill("mapper/", &nname));
+ EXPECT_FALSE(NativeName::fill("/default", &nname));
+ EXPECT_FALSE(NativeName::fill("mapper/default/0", &nname));
+ EXPECT_FALSE(NativeName::fill("aidl.like.IType/default", &nname));
+}
+
+} // namespace android
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index 97e500d..b575053 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -361,6 +361,24 @@
EXPECT_EQ(std::vector<std::string>{}, names);
}
+TEST(Vintf, IsDeclared_native) {
+ if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
+
+ auto sm = getPermissiveServiceManager();
+ bool declared = false;
+ EXPECT_TRUE(sm->isDeclared("mapper/minigbm", &declared).isOk());
+ EXPECT_TRUE(declared);
+}
+
+TEST(Vintf, GetDeclaredInstances_native) {
+ if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
+
+ auto sm = getPermissiveServiceManager();
+ std::vector<std::string> instances;
+ EXPECT_TRUE(sm->getDeclaredInstances("mapper", &instances).isOk());
+ EXPECT_EQ(std::vector<std::string>{"minigbm"}, instances);
+}
+
class CallbackHistorian : public BnServiceCallback {
Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
registrations.push_back(name);
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index ae0fb01..941e091 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -320,6 +320,24 @@
"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",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index fe566fc..39573ec 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 @@
}
}
+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/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 7de94e3..fb2781b 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -492,6 +492,7 @@
if (read(fd, &on, sizeof(on)) == -1) {
ALOGE("%s: error reading to %s: %s", __func__,
names[static_cast<int>(feature)], strerror(errno));
+ close(fd);
return false;
}
close(fd);
diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp
index 525ba2e..de2a69f 100644
--- a/libs/binder/RecordedTransaction.cpp
+++ b/libs/binder/RecordedTransaction.cpp
@@ -114,8 +114,8 @@
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 @@
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 @@
DATA_PARCEL_CHUNK = 2,
REPLY_PARCEL_CHUNK = 3,
INTERFACE_NAME_CHUNK = 4,
+ DATA_PARCEL_OBJECT_CHUNK = 5,
END_CHUNK = 0x00ffffff,
};
@@ -265,21 +275,30 @@
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 @@
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 @@
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 55167a7..486bdfb 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -207,6 +207,8 @@
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 09da6e3..d7096d8 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -55,6 +55,9 @@
class TextOutput;
namespace binder {
class Status;
+namespace debug {
+class RecordedTransaction;
+}
}
class Parcel {
@@ -1443,6 +1446,9 @@
// 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 505c199..f0bee7f 100644
--- a/libs/binder/include/binder/RecordedTransaction.h
+++ b/libs/binder/include/binder/RecordedTransaction.h
@@ -50,6 +50,7 @@
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 @@
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 316a79c..b34b30d 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -243,6 +243,18 @@
__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()
+ */
+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 0843a8e..de624e4 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -204,6 +204,7 @@
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 3bfdc59..5529455 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -200,6 +200,13 @@
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/tests/Android.bp b/libs/binder/tests/Android.bp
index dd2be94..2f0987f 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -69,10 +69,14 @@
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 @@
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 bd6b03c..29267e9 100644
--- a/libs/binder/tests/IBinderRecordReplayTest.aidl
+++ b/libs/binder/tests/IBinderRecordReplayTest.aidl
@@ -69,4 +69,10 @@
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 cb1a1ee..0ee96e7 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -70,7 +70,7 @@
}
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 73c0a94..b975fad 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 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
&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 83db6c9..fbab8f0 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -131,6 +131,13 @@
"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_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 @@
"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 8fc9263..7a1688b 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 8a1fecb..f41c35b 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;
-
- // 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;
-
- // 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);
-
- return OK;
+ if (mProvider.ConsumeBool()) {
+ return mProvider.ConsumeIntegral<status_t>();
}
-private:
- String16 mDescriptor;
+ if (reply == nullptr) return OK;
- // note may not all be used
- std::vector<uint8_t> mBytes;
- FuzzedDataProvider mProvider;
-};
+ // 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;
+
+ // 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);
+
+ 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 4e58dc4..62b8433 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -73,7 +73,7 @@
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 @@
}
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 7b3c806..fd9777a 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 @@
} // 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 @@
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/Choreographer.cpp b/libs/gui/Choreographer.cpp
index 46fb068..a52f68e 100644
--- a/libs/gui/Choreographer.cpp
+++ b/libs/gui/Choreographer.cpp
@@ -116,7 +116,7 @@
std::lock_guard<std::mutex> _l(gChoreographers.lock);
gChoreographers.ptrs.erase(std::remove_if(gChoreographers.ptrs.begin(),
gChoreographers.ptrs.end(),
- [=](Choreographer* c) { return c == this; }),
+ [=, this](Choreographer* c) { return c == this; }),
gChoreographers.ptrs.end());
// Only poke DisplayManagerGlobal to unregister if we previously registered
// callbacks.
@@ -394,4 +394,4 @@
return iter->second;
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 462ce6e..15e8744 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/input/input_verifier.rs b/libs/input/input_verifier.rs
index f8dda3c..767865c 100644
--- a/libs/input/input_verifier.rs
+++ b/libs/input/input_verifier.rs
@@ -184,7 +184,7 @@
logger::init(
logger::Config::default()
.with_tag_on_device("InputVerifier")
- .with_min_level(log::Level::Trace),
+ .with_max_level(log::LevelFilter::Trace),
);
Self { name: name.to_owned(), touching_pointer_ids_by_device: HashMap::new() }
}
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index d71e55f..a733fd0 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -1022,7 +1022,7 @@
.fakeOutputDataspace = fakeDataspace}));
// Turn on dithering when dimming beyond this (arbitrary) threshold...
- static constexpr float kDimmingThreshold = 0.2f;
+ static constexpr float kDimmingThreshold = 0.9f;
// ...or we're rendering an HDR layer down to an 8-bit target
// Most HDR standards require at least 10-bits of color depth for source content, so we
// can just extract the transfer function rather than dig into precise gralloc layout.
diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp
index 16ed82a..a45ffe1 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>
@@ -81,7 +82,7 @@
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 +90,8 @@
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 +166,7 @@
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 +266,7 @@
}
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 +276,13 @@
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 +297,7 @@
}
}
- view.remove_prefix(kDescriptorLength);
+ view = view.subspan(kDescriptorLength);
}
std::string_view modelString = displayName;
@@ -327,8 +329,8 @@
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;
}
diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp
index c3b2d3d..123bef4 100644
--- a/libs/ui/Gralloc5.cpp
+++ b/libs/ui/Gralloc5.cpp
@@ -83,10 +83,18 @@
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 cb063af..faa77ca 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 2d0a4ea..371ed89 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 @@
// 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/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 7fd9c3a..f73fa5d 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -22,8 +22,10 @@
mkdir -p out/javax/microedition/khronos/opengles
mkdir -p out/com/google/android/gles_jni
+mkdir -p out/android/annotation
mkdir -p out/android/app
mkdir -p out/android/graphics
+mkdir -p out/android/hardware
mkdir -p out/android/view
mkdir -p out/android/opengl
mkdir -p out/android/content
@@ -34,18 +36,20 @@
echo "package android.graphics;" > out/android/graphics/Canvas.java
echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
+echo "package android.annotation; public @interface NonNull {}" > out/android/annotation/NonNull.java
echo "package android.app; import android.content.pm.IPackageManager; public class AppGlobals { public static IPackageManager getPackageManager() { return null;} }" > out/android/app/AppGlobals.java
# echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags, java.lang.String userId) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
-echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;}; }" > out/android/os/Build.java
+echo "package android.hardware; import android.os.ParcelFileDescriptor; public class SyncFence { public static SyncFence create(ParcelFileDescriptor w) { return null; } public static SyncFence createEmpty() { return null; } }" > out/android/hardware/SyncFence.java
+echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 0; public static final int R = 0; }; }" > out/android/os/Build.java
+echo "package android.os; public class ParcelFileDescriptor { public static ParcelFileDescriptor adoptFd(int fd) { return null; } }" > out/android/os/ParcelFileDescriptor.java
echo "package android.os; public class UserHandle {public static String myUserId() { return \"\"; } }" > out/android/os/UserHandle.java
echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
-echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
+echo "package android.util; public class Log {public static void d(String a, String b) {} public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
echo "package android.opengl; public abstract class EGLObjectHandle { public int getHandle() { return 0; } }" > out/android/opengl/EGLObjectHandle.java
-
echo "package android.graphics;" > out/android/graphics/SurfaceTexture.java
echo "public interface SurfaceTexture {}" >> out/android/graphics/SurfaceTexture.java
echo "package android.view;" > out/android/view/SurfaceView.java
diff --git a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
index 951ecff..695b571 100644
--- a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
+++ b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
@@ -20,6 +20,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.SurfaceTexture;
+import android.os.Build;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
diff --git a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
index b2ea041..ea55179 100644
--- a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
diff --git a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
index 6dffac5..8e452fb 100644
--- a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
index 523bc57..75e1704 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
+++ b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
@@ -18,6 +18,11 @@
package android.opengl;
+import android.annotation.NonNull;
+import android.hardware.SyncFence;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
/**
* EGL Extensions
*/
@@ -30,8 +35,44 @@
public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
public static final int EGL_RECORDABLE_ANDROID = 0x3142;
+ // EGL_ANDROID_native_fence_sync
+ public static final int EGL_SYNC_NATIVE_FENCE_ANDROID = 0x3144;
+ public static final int EGL_SYNC_NATIVE_FENCE_FD_ANDROID = 0x3145;
+ public static final int EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID = 0x3146;
+ public static final int EGL_NO_NATIVE_FENCE_FD_ANDROID = -1;
+
native private static void _nativeClassInit();
static {
_nativeClassInit();
}
+ /**
+ * Retrieves the SyncFence for an EGLSync created with EGL_SYNC_NATIVE_FENCE_ANDROID
+ *
+ * See <a href="https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_native_fence_sync.txt">
+ * EGL_ANDROID_native_fence_sync</a> extension for more details
+ * @param display The EGLDisplay connection
+ * @param sync The EGLSync to fetch the SyncFence from
+ * @return A SyncFence representing the native fence.
+ * * If <sync> is not a valid sync object for <display>,
+ * an {@link SyncFence#isValid() invalid} SyncFence is returned and an EGL_BAD_PARAMETER
+ * error is generated.
+ * * If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute of <sync> is
+ * EGL_NO_NATIVE_FENCE_FD_ANDROID, an {@link SyncFence#isValid() invalid} SyncFence is
+ * returned and an EGL_BAD_PARAMETER error is generated.
+ * * If <display> does not match the display passed to eglCreateSync
+ * when <sync> was created, the behaviour is undefined.
+ */
+ public static @NonNull SyncFence eglDupNativeFenceFDANDROID(@NonNull EGLDisplay display,
+ @NonNull EGLSync sync) {
+ int fd = eglDupNativeFenceFDANDROIDImpl(display, sync);
+ Log.d("EGL", "eglDupNativeFence returned " + fd);
+ if (fd >= 0) {
+ return SyncFence.create(ParcelFileDescriptor.adoptFd(fd));
+ } else {
+ return SyncFence.createEmpty();
+ }
+ }
+
+ private static native int eglDupNativeFenceFDANDROIDImpl(EGLDisplay display, EGLSync sync);
+
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
index be8b3e3..f1f0ac5 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
@@ -37,25 +38,12 @@
#include <ui/ANativeObjectBase.h>
static jclass egldisplayClass;
-static jclass eglcontextClass;
static jclass eglsurfaceClass;
-static jclass eglconfigClass;
+static jclass eglsyncClass;
static jmethodID egldisplayGetHandleID;
-static jmethodID eglcontextGetHandleID;
static jmethodID eglsurfaceGetHandleID;
-static jmethodID eglconfigGetHandleID;
-
-static jmethodID egldisplayConstructor;
-static jmethodID eglcontextConstructor;
-static jmethodID eglsurfaceConstructor;
-static jmethodID eglconfigConstructor;
-
-static jobject eglNoContextObject;
-static jobject eglNoDisplayObject;
-static jobject eglNoSurfaceObject;
-
-
+static jmethodID eglsyncGetHandleID;
/* Cache method IDs each time the class is loaded. */
@@ -64,37 +52,14 @@
{
jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay");
egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal);
- jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext");
- eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal);
jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface");
eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal);
- jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
- eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
+ jclass eglsyncClassLocal = _env->FindClass("android/opengl/EGLSync");
+ eglsyncClass = (jclass) _env->NewGlobalRef(eglsyncClassLocal);
egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
- eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
- eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
-
-
- egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
- eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
- eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
- eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
-
-
- jclass eglClass = _env->FindClass("android/opengl/EGL14");
- jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;");
- jobject localeglNoContextObject = _env->GetStaticObjectField(eglClass, noContextFieldID);
- eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-
- jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;");
- jobject localeglNoDisplayObject = _env->GetStaticObjectField(eglClass, noDisplayFieldID);
- eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-
- jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;");
- jobject localeglNoSurfaceObject = _env->GetStaticObjectField(eglClass, noSurfaceFieldID);
- eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
+ eglsyncGetHandleID = _env->GetMethodID(eglsyncClass, "getNativeHandle", "()J");
}
static void *
@@ -108,24 +73,12 @@
return reinterpret_cast<void*>(_env->CallLongMethod(obj, mid));
}
-static jobject
-toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void * handle) {
- if (cls == eglcontextClass &&
- (EGLContext)handle == EGL_NO_CONTEXT) {
- return eglNoContextObject;
- }
+// TODO: this should be generated from the .spec file, but needs to be renamed and made private
+static jint android_eglDupNativeFenceFDANDROID(JNIEnv *env, jobject, jobject dpy, jobject sync) {
+ EGLDisplay dpy_native = (EGLDisplay)fromEGLHandle(env, egldisplayGetHandleID, dpy);
+ EGLSync sync_native = (EGLSync)fromEGLHandle(env, eglsyncGetHandleID, sync);
- if (cls == egldisplayClass &&
- (EGLDisplay)handle == EGL_NO_DISPLAY) {
- return eglNoDisplayObject;
- }
-
- if (cls == eglsurfaceClass &&
- (EGLSurface)handle == EGL_NO_SURFACE) {
- return eglNoSurfaceObject;
- }
-
- return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
+ return eglDupNativeFenceFDANDROID(dpy_native, sync_native);
}
// --------------------------------------------------------------------------
diff --git a/opengl/tools/glgen/stubs/egl/eglGetDisplay.java b/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
index 85f743d..78b0819 100755
--- a/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
+++ b/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
@@ -7,7 +7,7 @@
/**
* {@hide}
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static native EGLDisplay eglGetDisplay(
long display_id
);
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
index b2bbdf6..4004a7d 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES2/gl2.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
index b039bc9..c5bdf32 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES3/gl3.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
index dd00e92..2260a80 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES3/gl31.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
index 88e00be..130612d 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <stdint.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
index 3e7ec8b..5446fc2 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <stdint.h>
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 9cab1d6..c3534bf 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index 4e2a6fb..e5d2b70 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 1585fdd..a5564d2 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 47b0824..59af493 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/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index c0eb36d..3cda334 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -325,7 +325,9 @@
}
mAidlComposerCallback = ndk::SharedRefBase::make<AidlIComposerCallbackWrapper>(callback);
- AIBinder_setMinSchedulerPolicy(mAidlComposerCallback->asBinder().get(), SCHED_FIFO, 2);
+
+ ndk::SpAIBinder binder = mAidlComposerCallback->asBinder();
+ AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_FIFO, 2);
const auto status = mAidlComposerClient->registerCallback(mAidlComposerCallback);
if (!status.isOk()) {
diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp
index a468146..5437995 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 3294724..be71dc2 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"