Merge "binder_parcel_fuzzer: avoid timeouts"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 657dfb6..b87582e 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2526,6 +2526,8 @@
return RunStatus::OK;
}
+ MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
+ calling_uid, calling_package.c_str());
if (options_->bugreport_fd.get() != -1) {
// If the output needs to be copied over to the caller's fd, get user consent.
android::String16 package(calling_package.c_str());
@@ -2703,10 +2705,10 @@
FinalizeFile();
}
- // Share the final file with the caller if the user has consented.
+ // Share the final file with the caller if the user has consented or Shell is the caller.
Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
if (options_->bugreport_fd.get() != -1) {
- status = CopyBugreportIfUserConsented();
+ status = CopyBugreportIfUserConsented(calling_uid);
if (status != Dumpstate::RunStatus::OK &&
status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
// Do an early return if there were errors. We make an exception for consent
@@ -2776,6 +2778,9 @@
}
void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
+ if (calling_uid == AID_SHELL) {
+ return;
+ }
consent_callback_ = new ConsentCallback();
const String16 incidentcompanion("incidentcompanion");
sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
@@ -2810,10 +2815,15 @@
return USER_CONSENT_DENIED;
}
-Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
+Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
// If the caller has asked to copy the bugreport over to their directory, we need explicit
- // user consent.
- UserConsentResult consent_result = consent_callback_->getResult();
+ // user consent (unless the caller is Shell).
+ UserConsentResult consent_result;
+ if (calling_uid == AID_SHELL) {
+ consent_result = UserConsentResult::APPROVED;
+ } else {
+ consent_result = consent_callback_->getResult();
+ }
if (consent_result == UserConsentResult::UNAVAILABLE) {
// User has not responded yet.
uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 5ba84ca..430936e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -498,8 +498,9 @@
RunStatus HandleUserConsentDenied();
- // Copies bugreport artifacts over to the caller's directories provided there is user consent.
- RunStatus CopyBugreportIfUserConsented();
+ // Copies bugreport artifacts over to the caller's directories provided there is user consent or
+ // called by Shell.
+ RunStatus CopyBugreportIfUserConsented(int32_t calling_uid);
// Used by GetInstance() only.
explicit Dumpstate(const std::string& version = VERSION_CURRENT);
diff --git a/headers/media_plugin/media/openmax/OMX_VideoExt.h b/headers/media_plugin/media/openmax/OMX_VideoExt.h
index 435fcc8..dc37bbd 100644
--- a/headers/media_plugin/media/openmax/OMX_VideoExt.h
+++ b/headers/media_plugin/media/openmax/OMX_VideoExt.h
@@ -291,18 +291,19 @@
/** Dolby Vision Profile enum type */
typedef enum OMX_VIDEO_DOLBYVISIONPROFILETYPE {
- OMX_VIDEO_DolbyVisionProfileUnknown = 0x0,
- OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1,
- OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2,
- OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4,
- OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8,
- OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
- OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
- OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
- OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
- OMX_VIDEO_DolbyVisionProfileDvheSt = 0x100,
- OMX_VIDEO_DolbyVisionProfileDvavSe = 0x200,
- OMX_VIDEO_DolbyVisionProfileMax = 0x7FFFFFFF
+ OMX_VIDEO_DolbyVisionProfileUnknown = 0x0,
+ OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1,
+ OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2,
+ OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4,
+ OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8,
+ OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
+ OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
+ OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
+ OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
+ OMX_VIDEO_DolbyVisionProfileDvheSt = 0x100,
+ OMX_VIDEO_DolbyVisionProfileDvavSe = 0x200,
+ OMX_VIDEO_DolbyVisionProfileDvav110 = 0x400,
+ OMX_VIDEO_DolbyVisionProfileMax = 0x7FFFFFFF
} OMX_VIDEO_DOLBYVISIONPROFILETYPE;
/** Dolby Vision Level enum type */
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 643a956..e5646ef 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -73,6 +73,7 @@
// or dessert updates. Instead, apex users should use libbinder_ndk.
apex_available: [
"//apex_available:platform",
+ "com.android.vndk.current",
// TODO(b/139016109) remove these three
"com.android.media.swcodec",
"test_com.android.media.swcodec",
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 50c7053..238c9dc 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -214,16 +214,21 @@
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
+ bool privateVendor = flags & FLAG_PRIVATE_VENDOR;
+ // don't send userspace flags to the kernel
+ flags = flags & ~FLAG_PRIVATE_VENDOR;
+
// user transactions require a given stability level
if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
using android::internal::Stability;
auto stability = Stability::get(this);
+ auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability;
- if (CC_UNLIKELY(!Stability::check(stability, Stability::kLocalStability))) {
+ if (CC_UNLIKELY(!Stability::check(stability, required))) {
ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
Stability::stabilityString(stability).c_str(),
- Stability::stabilityString(Stability::kLocalStability).c_str());
+ Stability::stabilityString(required).c_str());
return BAD_TYPE;
}
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 573a038..7d9846a 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -50,10 +50,6 @@
#include <private/binder/binder_module.h>
#include "Static.h"
-#ifndef INT32_MAX
-#define INT32_MAX ((int32_t)(2147483647))
-#endif
-
#define LOG_REFS(...)
//#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOG_ALLOC(...)
@@ -509,7 +505,7 @@
}
}
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
constexpr int32_t kHeader = B_PACK_CHARS('V', 'N', 'D', 'R');
#else
constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T');
@@ -750,61 +746,37 @@
return writeUtf8AsUtf16(*str);
}
-namespace {
-
-template<typename T>
-status_t writeByteVectorInternal(Parcel* parcel, const std::vector<T>& val)
-{
- status_t status;
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- status = BAD_VALUE;
- return status;
+status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) {
+ if (size > std::numeric_limits<int32_t>::max()) {
+ return BAD_VALUE;
}
- status = parcel->writeInt32(val.size());
+ status_t status = writeInt32(size);
if (status != OK) {
return status;
}
- void* data = parcel->writeInplace(val.size());
- if (!data) {
- status = BAD_VALUE;
- return status;
- }
-
- memcpy(data, val.data(), val.size());
- return status;
+ return write(data, size);
}
-template<typename T>
-status_t writeByteVectorInternalPtr(Parcel* parcel,
- const std::unique_ptr<std::vector<T>>& val)
-{
- if (!val) {
- return parcel->writeInt32(-1);
- }
-
- return writeByteVectorInternal(parcel, *val);
-}
-
-} // namespace
-
status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
- return writeByteVectorInternal(this, val);
+ return writeByteVectorInternal(val.data(), val.size());
}
status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
{
- return writeByteVectorInternalPtr(this, val);
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(val->data(), val->size());
}
status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
- return writeByteVectorInternal(this, val);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
}
status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
{
- return writeByteVectorInternalPtr(this, val);
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
}
status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
@@ -1477,81 +1449,41 @@
return err;
}
-namespace {
-
-template<typename T>
-status_t readByteVectorInternal(const Parcel* parcel,
- std::vector<T>* val) {
- val->clear();
-
- int32_t size;
- status_t status = parcel->readInt32(&size);
-
- if (status != OK) {
- return status;
+status_t Parcel::readByteVectorInternal(int8_t* data, size_t size) const {
+ if (size_t(size) > dataAvail()) {
+ return BAD_VALUE;
}
-
- if (size < 0) {
- status = UNEXPECTED_NULL;
- return status;
- }
- if (size_t(size) > parcel->dataAvail()) {
- status = BAD_VALUE;
- return status;
- }
-
- T* data = const_cast<T*>(reinterpret_cast<const T*>(parcel->readInplace(size)));
- if (!data) {
- status = BAD_VALUE;
- return status;
- }
- val->reserve(size);
- val->insert(val->end(), data, data + size);
-
- return status;
+ return read(data, size);
}
-template<typename T>
-status_t readByteVectorInternalPtr(
- const Parcel* parcel,
- std::unique_ptr<std::vector<T>>* val) {
- const int32_t start = parcel->dataPosition();
- int32_t size;
- status_t status = parcel->readInt32(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- parcel->setDataPosition(start);
- val->reset(new (std::nothrow) std::vector<T>());
-
- status = readByteVectorInternal(parcel, val->get());
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
-}
-
-} // namespace
-
status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
- return readByteVectorInternal(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(val->data(), val->size());
}
status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
- return readByteVectorInternal(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
- return readByteVectorInternalPtr(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null byte vector.
+ return OK;
+ }
+ return readByteVectorInternal((*val)->data(), (*val)->size());
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
- return readByteVectorInternalPtr(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null byte vector.
+ return OK;
+ }
+ return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
}
status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 136bdb0..8ae7e7a 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "binderSafeInterfaceTest"
},
{
+ "name": "binderVendorDoubleLoadTest"
+ },
+ {
"name": "binderDriverInterfaceTest"
},
{
diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp
index 5a6955f..a9d2b75 100644
--- a/libs/binder/fuzzer/Android.bp
+++ b/libs/binder/fuzzer/Android.bp
@@ -1,5 +1,5 @@
-cc_defaults {
- name: "binder_parcel_fuzzer_defaults",
+cc_fuzz {
+ name: "binder_parcel_fuzzer",
defaults: ["libbinder_ndk_host_user"],
host_supported: true,
srcs: [
@@ -36,16 +36,8 @@
],
},
},
- defaults_visibility: [":__subpackages__"],
-}
-
-cc_fuzz {
- name: "binder_parcel_fuzzer",
- defaults: ["binder_parcel_fuzzer_defaults"],
-}
-
-cc_fuzz {
- name: "binder_parcel_fuzzer_logs",
- defaults: ["binder_parcel_fuzzer_defaults"],
- cflags: ["-DENABLE_LOG_FUZZ"],
+ // This flag enables verbose output in the fuzz target, and is very useful
+ // for debugging a failure. If you are trying to diagnose how a crash was
+ // produced, you may find uncommenting the below line very useful.
+ // cflags: ["-DENABLE_LOG_FUZZ"],
}
diff --git a/libs/binder/fuzzer/binder.cpp b/libs/binder/fuzzer/binder.cpp
index 04fe0e7..52c730c 100644
--- a/libs/binder/fuzzer/binder.cpp
+++ b/libs/binder/fuzzer/binder.cpp
@@ -22,6 +22,10 @@
using ::android::status_t;
+enum ByteEnum : int8_t {};
+enum IntEnum : int32_t {};
+enum LongEnum : int64_t {};
+
class ExampleParcelable : public android::Parcelable {
public:
status_t writeToParcel(android::Parcel* /*parcel*/) const override {
@@ -80,6 +84,7 @@
PARCEL_READ_WITH_STATUS(T, FUN), \
PARCEL_READ_NO_STATUS(T, FUN)
+// clang-format off
std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS {
PARCEL_READ_NO_STATUS(size_t, dataSize),
PARCEL_READ_NO_STATUS(size_t, dataAvail),
@@ -148,6 +153,14 @@
PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readStrongBinder),
PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readNullableStrongBinder),
+ // TODO(b/131868573): can force read of arbitrarily sized vector
+ // PARCEL_READ_WITH_STATUS(std::vector<ByteEnum>, readEnumVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<ByteEnum>>, readEnumVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<IntEnum>, readEnumVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<IntEnum>>, readEnumVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<LongEnum>, readEnumVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<LongEnum>>, readEnumVector),
+
// only reading one parcelable type for now
// TODO(b/131868573): can force read of arbitrarily sized vector
// PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<ExampleParcelable>>>, readParcelableVector),
@@ -239,3 +252,4 @@
PARCEL_READ_NO_STATUS(size_t, getBlobAshmemSize),
PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize),
};
+// clang-format on
diff --git a/libs/binder/fuzzer/hwbinder.cpp b/libs/binder/fuzzer/hwbinder.cpp
index b8cce72..0fec393 100644
--- a/libs/binder/fuzzer/hwbinder.cpp
+++ b/libs/binder/fuzzer/hwbinder.cpp
@@ -30,6 +30,9 @@
return os;
}
+#define PARCEL_READ_OPT_STATUS(T, FUN) \
+ PARCEL_READ_NO_STATUS(T, FUN), PARCEL_READ_WITH_STATUS(T, FUN)
+
#define PARCEL_READ_NO_STATUS(T, FUN) \
[] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
@@ -45,6 +48,7 @@
FUZZ_LOG() << #T " status: " << status << " value: " << t;\
}
+// clang-format off
std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS {
PARCEL_READ_NO_STATUS(size_t, dataSize),
PARCEL_READ_NO_STATUS(size_t, dataAvail),
@@ -62,30 +66,44 @@
FUZZ_LOG() << "enforceInterface status: " << okay;
},
PARCEL_READ_NO_STATUS(size_t, objectsCount),
+ [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ FUZZ_LOG() << "about to read";
+ std::vector<uint8_t> data (length);
+ status_t status = p.read(data.data(), length);
+ FUZZ_LOG() << "read status: " << status << " data: " << hexString(data.data(), data.size());
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ FUZZ_LOG() << "about to read";
+ std::vector<uint8_t> data (length);
+ const void* inplace = p.readInplace(length);
+ FUZZ_LOG() << "read status: " << hexString(inplace, length);
+ },
PARCEL_READ_WITH_STATUS(int8_t, readInt8),
PARCEL_READ_WITH_STATUS(uint8_t, readUint8),
PARCEL_READ_WITH_STATUS(int16_t, readInt16),
PARCEL_READ_WITH_STATUS(uint16_t, readUint16),
- PARCEL_READ_WITH_STATUS(int32_t, readInt32),
- PARCEL_READ_WITH_STATUS(uint32_t, readUint32),
- PARCEL_READ_WITH_STATUS(int64_t, readInt64),
- PARCEL_READ_WITH_STATUS(uint64_t, readUint64),
- PARCEL_READ_WITH_STATUS(float, readFloat),
- PARCEL_READ_WITH_STATUS(double, readDouble),
- PARCEL_READ_WITH_STATUS(bool, readBool),
- PARCEL_READ_WITH_STATUS(::android::String16, readString16),
- PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
- PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
- [] (const ::android::hardware::Parcel& p, uint8_t amount) {
- FUZZ_LOG() << "about to readInPlace " << amount;
- const uint8_t* data = (const uint8_t*)p.readInplace(amount);
- if (data) {
- std::vector<uint8_t> vdata(data, data + amount);
- FUZZ_LOG() << "readInPlace " << amount << " data: " << hexString(vdata);
- } else {
- FUZZ_LOG() << "readInPlace " << amount << " no data";
- }
+ PARCEL_READ_OPT_STATUS(int32_t, readInt32),
+ PARCEL_READ_OPT_STATUS(uint32_t, readUint32),
+ PARCEL_READ_OPT_STATUS(int64_t, readInt64),
+ PARCEL_READ_OPT_STATUS(uint64_t, readUint64),
+ PARCEL_READ_OPT_STATUS(float, readFloat),
+ PARCEL_READ_OPT_STATUS(double, readDouble),
+ PARCEL_READ_OPT_STATUS(bool, readBool),
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readCString";
+ const char* str = p.readCString();
+ FUZZ_LOG() << "readCString " << (str ? str : "<null>");
},
+ PARCEL_READ_OPT_STATUS(::android::String16, readString16),
+ PARCEL_READ_WITH_STATUS(std::unique_ptr<::android::String16>, readString16),
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readString16Inplace";
+ size_t outSize = 0;
+ const char16_t* str = p.readString16Inplace(&outSize);
+ FUZZ_LOG() << "readString16Inplace: " << hexString(str, sizeof(char16_t) * outSize);
+ },
+ PARCEL_READ_OPT_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
+ PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
[] (const ::android::hardware::Parcel& p, uint8_t size) {
FUZZ_LOG() << "about to readBuffer";
size_t handle = 0;
@@ -130,6 +148,28 @@
// should be null since we don't create any IPC objects
CHECK(data == nullptr) << data;
},
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readEmbeddedNativeHandle";
+ size_t parent_buffer_handle = size & 0xf;
+ size_t parent_offset = size >> 4;
+ const native_handle_t* handle = nullptr;
+ status_t status = p.readEmbeddedNativeHandle(parent_buffer_handle, parent_offset, &handle);
+ FUZZ_LOG() << "readEmbeddedNativeHandle status: " << status << " handle: " << handle << " handle: " << handle;
+
+ // should be null since we don't create any IPC objects
+ CHECK(handle == nullptr) << handle;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readNullableEmbeddedNativeHandle";
+ size_t parent_buffer_handle = size & 0xf;
+ size_t parent_offset = size >> 4;
+ const native_handle_t* handle = nullptr;
+ status_t status = p.readNullableEmbeddedNativeHandle(parent_buffer_handle, parent_offset, &handle);
+ FUZZ_LOG() << "readNullableEmbeddedNativeHandle status: " << status << " handle: " << handle << " handle: " << handle;
+
+ // should be null since we don't create any IPC objects
+ CHECK(handle == nullptr) << handle;
+ },
[] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
FUZZ_LOG() << "about to readNativeHandleNoDup";
const native_handle_t* handle = nullptr;
@@ -150,3 +190,4 @@
CHECK(handle == nullptr) << handle;
},
};
+// clang-format on
diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp
index bedab86..6657edb 100644
--- a/libs/binder/fuzzer/main.cpp
+++ b/libs/binder/fuzzer/main.cpp
@@ -34,6 +34,9 @@
P p;
p.setData(input.data(), input.size());
+ // since we are only using a byte to index
+ CHECK(reads.size() <= 255) << reads.size();
+
for (size_t i = 0; i < instructions.size() - 1; i += 2) {
uint8_t a = instructions[i];
uint8_t readIdx = a % reads.size();
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 64f3052..64604b7 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -62,7 +62,11 @@
DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
- FLAG_ONEWAY = 0x00000001
+ FLAG_ONEWAY = 0x00000001,
+
+ // Private userspace flag for transaction which is being requested from
+ // a vendor context.
+ FLAG_PRIVATE_VENDOR = 0x10000000,
};
IBinder();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 8726681..0f8abab 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -19,6 +19,7 @@
#include <map> // for legacy reasons
#include <string>
+#include <type_traits>
#include <vector>
#include <android-base/unique_fd.h>
@@ -157,6 +158,18 @@
status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
+ // Write an Enum vector with underlying type int8_t.
+ // Does not use padding; each byte is contiguous.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::vector<T>& val);
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+ // Write an Enum vector with underlying type != int8_t.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::vector<T>& val);
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+
template<typename T>
status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
@@ -275,6 +288,19 @@
status_t readStrongBinder(sp<IBinder>* val) const;
status_t readNullableStrongBinder(sp<IBinder>* val) const;
+
+ // Read an Enum vector with underlying type int8_t.
+ // Does not use padding; each byte is contiguous.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::vector<T>* val) const;
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+ // Read an Enum vector with underlying type != int8_t.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::vector<T>* val) const;
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+
template<typename T>
status_t readParcelableVector(
std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
@@ -438,6 +464,19 @@
status_t writeRawNullableParcelable(const Parcelable*
parcelable);
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
+ status_t writeEnum(const T& val);
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
+ status_t writeEnum(const T& val);
+
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
+ status_t readEnum(T* pArg) const;
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
+ status_t readEnum(T* pArg) const;
+
+ status_t writeByteVectorInternal(const int8_t* data, size_t size);
+ status_t readByteVectorInternal(int8_t* data, size_t size) const;
+
template<typename T, typename U>
status_t unsafeReadTypedVector(std::vector<T>* val,
status_t(Parcel::*read_func)(U*) const) const;
@@ -913,6 +952,66 @@
return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
+status_t Parcel::writeEnum(const T& val) {
+ return writeInt32(static_cast<int32_t>(val));
+}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
+status_t Parcel::writeEnum(const T& val) {
+ return writeInt64(static_cast<int64_t>(val));
+}
+
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::vector<T>& val) {
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::vector<T>& val) {
+ return writeTypedVector(val, &Parcel::writeEnum);
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
+ return writeNullableTypedVector(val, &Parcel::writeEnum);
+}
+
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
+status_t Parcel::readEnum(T* pArg) const {
+ return readInt32(reinterpret_cast<int32_t *>(pArg));
+}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
+status_t Parcel::readEnum(T* pArg) const {
+ return readInt64(reinterpret_cast<int64_t *>(pArg));
+}
+
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::vector<T>* val) const {
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null Enum vector.
+ return OK;
+ }
+ return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::vector<T>* val) const {
+ return readTypedVector(val, &Parcel::readEnum);
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
+ return readNullableTypedVector(val, &Parcel::readEnum);
+}
+
// ---------------------------------------------------------------------------
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 2894482..b2f51d3 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -81,7 +81,7 @@
VINTF = 0b111111,
};
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
static constexpr Level kLocalStability = Level::VENDOR;
#else
static constexpr Level kLocalStability = Level::SYSTEM;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index b06ca86..e752c45 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -17,6 +17,7 @@
#include <android/binder_ibinder.h>
#include "ibinder_internal.h"
+#include <android/binder_stability.h>
#include <android/binder_status.h>
#include "parcel_internal.h"
#include "status_internal.h"
@@ -542,7 +543,8 @@
return STATUS_UNKNOWN_TRANSACTION;
}
- if ((flags & ~FLAG_ONEWAY) != 0) {
+ constexpr binder_flags_t kAllFlags = FLAG_PRIVATE_VENDOR | FLAG_ONEWAY;
+ if ((flags & ~kAllFlags) != 0) {
LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
return STATUS_BAD_VALUE;
}
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index b03fce1..2a4ded8 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -20,7 +20,22 @@
__BEGIN_DECLS
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+/**
+ * Private addition to binder_flag_t.
+ */
+enum {
+ /**
+ * Indicates that this transaction is coupled w/ vendor.img
+ */
+ FLAG_PRIVATE_VENDOR = 0x10000000,
+};
+
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || \
+ (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
+
+enum {
+ FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
+};
/**
* This interface has the stability of the vendor image.
@@ -31,7 +46,12 @@
AIBinder_markVendorStability(binder);
}
-#else // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#else // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
+ // !defined(__ANDROID_APEX__))
+
+enum {
+ FLAG_PRIVATE_LOCAL = 0,
+};
/**
* This interface has the stability of the system image.
@@ -42,7 +62,8 @@
AIBinder_markSystemStability(binder);
}
-#endif // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#endif // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
+ // !defined(__ANDROID_APEX__))
/**
* This interface has system<->vendor stability
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index bb1fe2f..1c5dba3 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -67,3 +67,31 @@
srcs: ["main_server.cpp"],
gtest: false,
}
+
+cc_test {
+ name: "binderVendorDoubleLoadTest",
+ vendor: true,
+ srcs: [
+ "binderVendorDoubleLoadTest.cpp",
+ ],
+ static_libs: [
+ "IBinderVendorDoubleLoadTest-cpp",
+ "IBinderVendorDoubleLoadTest-ndk_platform",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libbinder_ndk",
+ "libutils",
+ ],
+ test_suites: ["device-tests"],
+}
+
+aidl_interface {
+ name: "IBinderVendorDoubleLoadTest",
+ // TODO(b/119771576): only vendor is needed
+ vendor_available: true,
+ srcs: [
+ "IBinderVendorDoubleLoadTest.aidl",
+ ],
+}
diff --git a/libs/binder/ndk/test/AndroidTest.xml b/libs/binder/ndk/test/AndroidTest.xml
new file mode 100644
index 0000000..89646f7
--- /dev/null
+++ b/libs/binder/ndk/test/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs binderVendorDoubleLoadTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="binderVendorDoubleLoadTest->/data/nativetest/vendor/binderVendorDoubleLoadTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/nativetest/vendor" />
+ <option name="module-name" value="binderVendorDoubleLoadTest" />
+ </test>
+</configuration>
+
diff --git a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
new file mode 100644
index 0000000..3a5bd9c
--- /dev/null
+++ b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+interface IBinderVendorDoubleLoadTest {
+ @utf8InCpp String RepeatString(@utf8InCpp String toRepeat);
+}
diff --git a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
new file mode 100644
index 0000000..f72dc36
--- /dev/null
+++ b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <BnBinderVendorDoubleLoadTest.h>
+#include <aidl/BnBinderVendorDoubleLoadTest.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_stability.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/Stability.h>
+#include <binder/Status.h>
+#include <gtest/gtest.h>
+
+#include <sys/prctl.h>
+
+using namespace android;
+using ::android::base::EndsWith;
+using ::android::base::GetProperty;
+using ::android::base::Split;
+using ::android::binder::Status;
+using ::android::internal::Stability;
+using ::ndk::ScopedAStatus;
+using ::ndk::SharedRefBase;
+using ::ndk::SpAIBinder;
+
+static const std::string kLocalNdkServerName = "NdkServer-local-IBinderVendorDoubleLoadTest";
+static const std::string kRemoteNdkServerName = "NdkServer-remote-IBinderVendorDoubleLoadTest";
+
+class NdkServer : public aidl::BnBinderVendorDoubleLoadTest {
+ ScopedAStatus RepeatString(const std::string& in, std::string* out) override {
+ *out = in;
+ return ScopedAStatus::ok();
+ }
+};
+class CppServer : public BnBinderVendorDoubleLoadTest {
+ Status RepeatString(const std::string& in, std::string* out) override {
+ *out = in;
+ return Status::ok();
+ }
+};
+
+TEST(DoubleBinder, VendorCppCantCallIntoSystem) {
+ Vector<String16> services = defaultServiceManager()->listServices();
+ EXPECT_TRUE(services.empty());
+}
+
+TEST(DoubleBinder, VendorCppCantRegisterService) {
+ sp<CppServer> cppServer = new CppServer;
+ status_t status = defaultServiceManager()->addService(String16("anything"), cppServer);
+ EXPECT_EQ(EX_TRANSACTION_FAILED, status);
+}
+
+TEST(DoubleBinder, CppVendorCantManuallyMarkVintfStability) {
+ // this test also implies that stability logic is turned on in vendor
+ ASSERT_DEATH(
+ {
+ sp<IBinder> binder = new CppServer();
+ Stability::markVintf(binder.get());
+ },
+ "Should only mark known object.");
+}
+
+TEST(DoubleBinder, NdkVendorCantManuallyMarkVintfStability) {
+ // this test also implies that stability logic is turned on in vendor
+ ASSERT_DEATH(
+ {
+ std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+ AIBinder_markVintfStability(ndkServer->asBinder().get());
+ },
+ "Should only mark known object.");
+}
+
+TEST(DoubleBinder, CallIntoNdk) {
+ for (const std::string& serviceName : {kLocalNdkServerName, kRemoteNdkServerName}) {
+ SpAIBinder binder = SpAIBinder(AServiceManager_checkService(serviceName.c_str()));
+ ASSERT_NE(nullptr, binder.get()) << serviceName;
+ EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())) << serviceName;
+
+ std::shared_ptr<aidl::IBinderVendorDoubleLoadTest> server =
+ aidl::IBinderVendorDoubleLoadTest::fromBinder(binder);
+
+ ASSERT_NE(nullptr, server.get()) << serviceName;
+
+ EXPECT_EQ(STATUS_OK, AIBinder_ping(server->asBinder().get()));
+
+ std::string outString;
+ ScopedAStatus status = server->RepeatString("foo", &outString);
+ EXPECT_EQ(STATUS_OK, AStatus_getExceptionCode(status.get())) << serviceName;
+ EXPECT_EQ("foo", outString) << serviceName;
+ }
+}
+
+void initDrivers() {
+ // Explicitly instantiated with the same driver that system would use.
+ // __ANDROID_VNDK__ right now uses /dev/vndbinder by default.
+ ProcessState::initWithDriver("/dev/binder");
+ ProcessState::self()->startThreadPool();
+ ABinderProcess_startThreadPool();
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ if (fork() == 0) {
+ // child process
+
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+ initDrivers();
+
+ // REMOTE SERVERS
+ std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+ CHECK(STATUS_OK == AServiceManager_addService(ndkServer->asBinder().get(),
+ kRemoteNdkServerName.c_str()));
+
+ // OR sleep forever or whatever, it doesn't matter
+ IPCThreadState::self()->joinThreadPool(true);
+ exit(1); // should not reach
+ }
+
+ sleep(1);
+
+ initDrivers();
+
+ // LOCAL SERVERS
+ std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+ AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str());
+
+ return RUN_ALL_TESTS();
+}
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 9bd3095..1ec73ce 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -266,10 +266,10 @@
char buf[CMSG_SPACE(kFdBufferSize)];
struct msghdr msg = {
- .msg_control = buf,
- .msg_controllen = sizeof(buf),
.msg_iov = &iov[0],
.msg_iovlen = 1,
+ .msg_control = buf,
+ .msg_controllen = sizeof(buf),
};
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
@@ -306,10 +306,10 @@
iov[0].iov_len = kMessageBufferSize;
struct msghdr msg = {
- .msg_control = fdBuf,
- .msg_controllen = sizeof(fdBuf),
.msg_iov = &iov[0],
.msg_iovlen = 1,
+ .msg_control = fdBuf,
+ .msg_controllen = sizeof(fdBuf),
};
int result;
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index 640a69a..930c7c7 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -18,10 +18,12 @@
#include "Connection.h"
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <cutils/atomic.h>
#include <inttypes.h>
+using android::base::GetBoolProperty;
using android::base::StringPrintf;
namespace android::inputdispatcher {
@@ -133,7 +135,11 @@
KeyEntry::~KeyEntry() {}
void KeyEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, "
+ msg += StringPrintf("KeyEvent");
+ if (!GetBoolProperty("ro.debuggable", false)) {
+ return;
+ }
+ msg += StringPrintf("(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, "
"flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
"repeatCount=%d), policyFlags=0x%08x",
deviceId, source, displayId, keyActionToString(action).c_str(), flags,
@@ -189,7 +195,11 @@
MotionEntry::~MotionEntry() {}
void MotionEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
+ msg += StringPrintf("MotionEvent");
+ if (!GetBoolProperty("ro.debuggable", false)) {
+ return;
+ }
+ msg += StringPrintf("(deviceId=%d, source=0x%08x, displayId=%" PRId32
", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
"buttonState=0x%08x, "
"classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6a45625..7065460 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -908,7 +908,6 @@
}
setZOrderRelativeOf(nullptr);
}
- mCurrentState.isRelativeOf = false;
setTransactionFlags(eTransactionNeeded);
return true;
}
@@ -931,6 +930,8 @@
mCurrentState.zOrderRelativeOf = relativeOf;
mCurrentState.sequence++;
mCurrentState.modified = true;
+ mCurrentState.isRelativeOf = relativeOf != nullptr;
+
setTransactionFlags(eTransactionNeeded);
}
@@ -952,7 +953,6 @@
mCurrentState.sequence++;
mCurrentState.modified = true;
mCurrentState.z = relativeZ;
- mCurrentState.isRelativeOf = true;
auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
if (oldZOrderRelativeOf != nullptr) {
diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp
index 8549db2..8c56d27 100644
--- a/services/surfaceflinger/tests/RelativeZ_test.cpp
+++ b/services/surfaceflinger/tests/RelativeZ_test.cpp
@@ -144,4 +144,63 @@
sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
}
}
+
+TEST_F(RelativeZTest, LayerAndRelativeRemoved) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // Child layer (BLUE) (relative to relativeToLayer layer)
+ // Relative layer (WHITE)
+ sp<SurfaceControl> childLayer =
+ createColorLayer("Child layer", Color::BLUE, mForegroundLayer.get());
+ sp<SurfaceControl> relativeToLayer =
+ createColorLayer("Relative layer", Color::WHITE, mForegroundLayer.get());
+
+ Transaction{}
+ .setRelativeLayer(childLayer, relativeToLayer->getHandle(), 1)
+ .show(childLayer)
+ .show(relativeToLayer)
+ .apply();
+
+ {
+ // The childLayer should be in front of relativeToLayer.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+ }
+
+ // Remove layer that childLayer is relative to
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // Child layer (BLUE) (relative to relativeToLayer layer)
+ Transaction{}.reparent(relativeToLayer, nullptr).apply();
+ relativeToLayer = 0;
+
+ {
+ // The child layer is relative to an deleted layer so it won't be drawn.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLayer, nullptr).apply();
+
+ {
+ // The child layer is offscreen, so it won't be drawn.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // Child layer (BLUE)
+ Transaction{}.reparent(childLayer, mForegroundLayer->getHandle()).apply();
+
+ {
+ // The relative z info for child layer should be reset, leaving the child layer on top.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+ }
+}
} // namespace android
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 272f2d1..f676573 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -562,5 +562,3 @@
} // namespace driver
} // namespace vulkan
-
-// clang-format on
diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py
index a0c648c..d1fff42 100644
--- a/vulkan/scripts/api_generator.py
+++ b/vulkan/scripts/api_generator.py
@@ -20,21 +20,36 @@
import os
import generator_common as gencom
-def isInstanceDispatchTableEntry(functionName):
- if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
- return False
- if gencom.gencom.isFunctionExported(functionName) and gencom.isInstanceDispatched(functionName):
- return True
- return False
+_INTERCEPTED_COMMANDS = [
+ 'vkCreateDevice',
+ 'vkDestroyDevice',
+ 'vkDestroyInstance',
+ 'vkEnumerateDeviceExtensionProperties',
+ 'vkEnumerateDeviceLayerProperties',
+]
-def isDeviceDispatchTableEntry(functionName):
- if gencom.gencom.isFunctionExported(functionName) and gencom.gencom.isDeviceDispatched(functionName):
- return True
- return False
-def api_genh():
+def gen_h():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'libvulkan', 'api_gen.h')
- header = """#ifndef LIBVULKAN_API_GEN_H
+ with open(genfile, 'w') as f:
+ instance_dispatch_table_entries = []
+ device_dispatch_table_entries = []
+
+ for cmd in gencom.command_list:
+ if cmd not in gencom.alias_dict:
+ if gencom.is_instance_dispatch_table_entry(cmd):
+ instance_dispatch_table_entries.append(
+ 'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';')
+ elif gencom.is_device_dispatch_table_entry(cmd):
+ device_dispatch_table_entries.append(
+ 'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';')
+
+ f.write(gencom.copyright_and_warning(2016))
+
+ f.write("""\
+#ifndef LIBVULKAN_API_GEN_H
#define LIBVULKAN_API_GEN_H
#include <vulkan/vulkan.h>
@@ -46,9 +61,26 @@
namespace vulkan {
namespace api {
-"""
+struct InstanceDispatchTable {
+ // clang-format off\n""")
- tail = """
+ for entry in instance_dispatch_table_entries:
+ f.write(gencom.indent(1) + entry + '\n')
+
+ f.write("""\
+ // clang-format on
+};
+
+struct DeviceDispatchTable {
+ // clang-format off\n""")
+
+ for entry in device_dispatch_table_entries:
+ f.write(gencom.indent(1) + entry + '\n')
+
+ f.write("""\
+ // clang-format on
+};
+
bool InitDispatchTable(
VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc,
@@ -61,105 +93,54 @@
} // namespace api
} // namespace vulkan
-#endif // LIBVULKAN_API_GEN_H
-"""
- genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.h')
- with open(genfile, 'w') as f:
- instanceDispatchTableEntries = []
- deviceDispatchTableEntries = []
- for commands in gencom.allCommandsList:
- if commands not in gencom.aliasDict:
- if gencom.isInstanceDispatchTableEntry(commands):
- instanceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
- elif gencom.isDeviceDispatchTableEntry(commands):
- deviceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+#endif // LIBVULKAN_API_GEN_H\n""")
- f.write (gencom.copyright)
- f.write (gencom.warning)
- f.write (header)
- f.write ('struct InstanceDispatchTable {\n')
- gencom.clang_off(f,1)
- for functions in instanceDispatchTableEntries:
- f.write(gencom.clang_off_spaces + functions + '\n')
- gencom.clang_on(f,1)
- f.write ('};\n\n')
-
- f.write ('struct DeviceDispatchTable {\n')
- gencom.clang_off(f,1)
- for functions in deviceDispatchTableEntries:
- f.write(gencom.clang_off_spaces + functions + '\n')
- gencom.clang_on(f,1)
- f.write ('};\n')
-
- f.write (tail)
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
-def defineInitProc(name, f):
- f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
- f.write ('\n')
- f.write ("""#define INIT_PROC(required, obj, proc) \\
- do { \\
- data.""" + name + """.proc = \\
- reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
- if (UNLIKELY(required && !data.""" + name + """.proc)) { \\
- ALOGE("missing " #obj " proc: vk" #proc); \\
- success = false; \\
- } \\
- } while (0)\n\n""")
-def defineInitProcExt(f):
- f.write ('// Exported extension functions may be invoked even when their extensions\n')
- f.write ('// are disabled. Dispatch to stubs when that happens.\n')
- f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\
- do { \\
- if (extensions[driver::ProcHook::ext]) \\
- INIT_PROC(required, obj, proc); \\
- else \\
- data.dispatch.proc = disabled##proc; \\
- } while (0)\n\n""")
+def _define_extension_stub(cmd, f):
+ if (cmd in gencom.extension_dict and gencom.is_function_exported(cmd)):
+ ext_name = gencom.extension_dict[cmd]
+ ret = gencom.return_type_dict[cmd]
+ params = gencom.param_dict[cmd]
+ first_param = params[0][0] + params[0][1]
+ tail_params = ', '.join([i[0][:-1] for i in params[1:]])
-def defineExtensionStub(functionName, f):
- if functionName in gencom.extensionsDict and gencom.isFunctionExported(functionName):
- extname = gencom.extensionsDict[functionName]
- base_name = functionName[2:]
- pList = gencom.paramDict[functionName]
- firstParam = pList[0][0] + pList[0][1]
- tailParams = [x[0][:-1] for x in pList[1:]]
- tailP = ', '.join(tailParams)
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' disabled' + base_name + '(' + firstParam + ', ' + tailP + ') {\n')
- f.write (gencom.clang_off_spaces)
- f.write ('driver::Logger(' + pList[0][1] + ').Err(' + pList[0][1] + ', \"' + extname + ' not enabled. Exported ' + functionName + ' not executed.\");\n')
- if gencom.returnTypeDict[functionName] != 'void':
- f.write(gencom.clang_off_spaces + 'return VK_SUCCESS;\n')
- f.write ('}\n\n')
+ f.write('VKAPI_ATTR ' + ret + ' disabled' + gencom.base_name(cmd) +
+ '(' + first_param + ', ' + tail_params + ') {\n')
-def isIntercepted(functionName):
- if gencom.isFunctionSupported(functionName):
- if gencom.isGloballyDispatched(functionName):
- return True
- elif functionName == 'vkCreateDevice':
- return True
- elif functionName == 'vkEnumerateDeviceLayerProperties':
- return True
- elif functionName == 'vkEnumerateDeviceExtensionProperties':
- return True
- elif functionName == 'vkDestroyInstance':
- return True
- elif functionName == 'vkDestroyDevice':
+ f.write(gencom.indent(1) + 'driver::Logger(' + params[0][1] +
+ ').Err(' + params[0][1] + ', \"' + ext_name +
+ ' not enabled. Exported ' + cmd + ' not executed.\");\n')
+
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write(gencom.indent(1) + 'return VK_SUCCESS;\n')
+
+ f.write('}\n\n')
+
+
+def _is_intercepted(cmd):
+ if gencom.is_function_supported(cmd):
+ if gencom.is_globally_dispatched(cmd) or cmd in _INTERCEPTED_COMMANDS:
return True
return False
-def interceptInstanceProcAddr(functionName, f):
- indent = 1
- f.write (gencom.clang_off_spaces*indent + '// global functions\n' + gencom.clang_off_spaces*indent+ 'if (instance == VK_NULL_HANDLE) {\n')
- indent = indent + 1
- for cmds in gencom.allCommandsList:
- if gencom.isGloballyDispatched(cmds):
- f.write(gencom.clang_off_spaces*indent + 'if (strcmp(pName, \"' + cmds + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
- f.write ('\n')
- f.write (""" ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
+def _intercept_instance_proc_addr(f):
+ f.write("""\
+ // global functions
+ if (instance == VK_NULL_HANDLE) {\n""")
+
+ for cmd in gencom.command_list:
+ if gencom.is_globally_dispatched(cmd):
+ f.write(gencom.indent(2) +
+ 'if (strcmp(pName, \"' + cmd +
+ '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' +
+ gencom.base_name(cmd) + ');\n')
+
+ f.write("""
+ ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
return nullptr;
}
@@ -167,14 +148,21 @@
const char* name;
PFN_vkVoidFunction proc;
} hooks[] = {\n""")
- sortedCommandsList = sorted(gencom.allCommandsList)
- for cmds in sortedCommandsList:
- if gencom.isFunctionExported(cmds):
- if gencom.isGloballyDispatched(cmds):
- f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", nullptr },\n')
- elif isIntercepted(cmds) or cmds == 'vkGetInstanceProcAddr' or gencom.isDeviceDispatched(cmds):
- f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ') },\n')
- f.write (gencom.clang_off_spaces + """};
+
+ sorted_command_list = sorted(gencom.command_list)
+ for cmd in sorted_command_list:
+ if gencom.is_function_exported(cmd):
+ if gencom.is_globally_dispatched(cmd):
+ f.write(gencom.indent(2) + '{ \"' + cmd + '\", nullptr },\n')
+ elif (_is_intercepted(cmd) or
+ cmd == 'vkGetInstanceProcAddr' or
+ gencom.is_device_dispatched(cmd)):
+ f.write(gencom.indent(2) + '{ \"' + cmd +
+ '\", reinterpret_cast<PFN_vkVoidFunction>(' +
+ gencom.base_name(cmd) + ') },\n')
+
+ f.write("""\
+ };
// clang-format on
constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
auto hook = std::lower_bound(
@@ -190,19 +178,25 @@
}
// clang-format off\n\n""")
-def interceptDeviceProcAddr(functionName, f):
- f.write (gencom.clang_off_spaces + """if (device == VK_NULL_HANDLE) {
+
+def _intercept_device_proc_addr(f):
+ f.write("""\
+ if (device == VK_NULL_HANDLE) {
ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
return nullptr;
- }\n\n""")
- f.write (gencom.clang_off_spaces + 'static const char* const known_non_device_names[] = {\n')
- sortedCommandsList = sorted(gencom.allCommandsList)
- for cmds in sortedCommandsList:
- if gencom.isFunctionSupported(cmds):
- if not gencom.isDeviceDispatched(cmds):
- f.write(gencom.clang_off_spaces*2 + '\"' + cmds + '\",\n')
- f.write(gencom.clang_off_spaces + '};\n')
- f.write(gencom.clang_off_spaces + """// clang-format on
+ }
+
+ static const char* const known_non_device_names[] = {\n""")
+
+ sorted_command_list = sorted(gencom.command_list)
+ for cmd in sorted_command_list:
+ if gencom.is_function_supported(cmd):
+ if not gencom.is_device_dispatched(cmd):
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+
+ f.write("""\
+ };
+ // clang-format on
constexpr size_t count =
sizeof(known_non_device_names) / sizeof(known_non_device_names[0]);
if (!pName ||
@@ -215,27 +209,38 @@
return nullptr;
}
// clang-format off\n\n""")
- for cmds in gencom.allCommandsList:
- if gencom.isDeviceDispatched(cmds):
- if isIntercepted(cmds) or cmds == 'vkGetDeviceProcAddr':
- f.write (gencom.clang_off_spaces + 'if (strcmp(pName, "' + cmds + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
- f.write ('\n')
-def apiDispatch(functionName, f):
- assert not isIntercepted(functionName)
-
- f.write (gencom.clang_off_spaces)
- if gencom.returnTypeDict[functionName] != 'void':
- f.write ('return ')
-
- paramList = gencom.paramDict[functionName]
- p0 = paramList[0][1]
- f.write('GetData(' + p0 + ').dispatch.' + functionName[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+ for cmd in gencom.command_list:
+ if gencom.is_device_dispatched(cmd):
+ if _is_intercepted(cmd) or cmd == 'vkGetDeviceProcAddr':
+ f.write(gencom.indent(1) + 'if (strcmp(pName, "' + cmd +
+ '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' +
+ gencom.base_name(cmd) + ');\n')
+ f.write('\n')
-def api_gencpp():
- genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.cpp')
- header = """#include <log/log.h>
+def _api_dispatch(cmd, f):
+ assert not _is_intercepted(cmd)
+
+ f.write(gencom.indent(1))
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write('return ')
+
+ param_list = gencom.param_dict[cmd]
+ handle = param_list[0][1]
+ f.write('GetData(' + handle + ').dispatch.' + gencom.base_name(cmd) +
+ '(' + ', '.join(i[1] for i in param_list) + ');\n')
+
+
+def gen_cpp():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'libvulkan', 'api_gen.cpp')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2016))
+
+ f.write("""\
+#include <log/log.h>
#include <string.h>
#include <algorithm>
@@ -247,80 +252,106 @@
namespace vulkan {
namespace api {
-"""
- with open(genfile, 'w') as f:
- f.write (gencom.copyright)
- f.write (gencom.warning)
- f.write ("""#include <log/log.h>
-#include <string.h>
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
-#include <algorithm>
+#define INIT_PROC(required, obj, proc) \\
+ do { \\
+ data.dispatch.proc = \\
+ reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+ if (UNLIKELY(required && !data.dispatch.proc)) { \\
+ ALOGE("missing " #obj " proc: vk" #proc); \\
+ success = false; \\
+ } \\
+ } while (0)
-// to catch mismatches between vulkan.h and this file
-#undef VK_NO_PROTOTYPES
-#include "api.h"
+// Exported extension functions may be invoked even when their extensions
+// are disabled. Dispatch to stubs when that happens.
+#define INIT_PROC_EXT(ext, required, obj, proc) \\
+ do { \\
+ if (extensions[driver::ProcHook::ext]) \\
+ INIT_PROC(required, obj, proc); \\
+ else \\
+ data.dispatch.proc = disabled##proc; \\
+ } while (0)
-namespace vulkan {
-namespace api {\n\n""")
- defineInitProc('dispatch',f)
- defineInitProcExt(f)
- f.write ('namespace {\n\n')
- gencom.clang_off(f,0)
- f.write ('\n')
- for cmds in gencom.allCommandsList:
- defineExtensionStub(cmds,f)
- gencom.clang_on(f,0)
- f.write ('\n} // namespace\n\n')
- f.write ("""bool InitDispatchTable(
+namespace {
+
+// clang-format off\n\n""")
+
+ for cmd in gencom.command_list:
+ _define_extension_stub(cmd, f)
+
+ f.write("""\
+// clang-format on
+
+} // namespace
+
+bool InitDispatchTable(
VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc,
const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
auto& data = GetData(instance);
- bool success = true;\n\n""")
- gencom.clang_off(f,1)
- for cmds in gencom.allCommandsList:
- if gencom.isInstanceDispatchTableEntry(cmds):
- gencom.initProc(cmds, f)
- gencom.clang_on(f,1)
- f.write ('\n')
- f.write (' return success;\n}\n\n')
- f.write ("""bool InitDispatchTable(
+ bool success = true;
+
+ // clang-format off\n""")
+
+ for cmd in gencom.command_list:
+ if gencom.is_instance_dispatch_table_entry(cmd):
+ gencom.init_proc(cmd, f)
+
+ f.write("""\
+ // clang-format on
+
+ return success;
+}
+
+bool InitDispatchTable(
VkDevice dev,
PFN_vkGetDeviceProcAddr get_proc,
const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
auto& data = GetData(dev);
- bool success = true;\n\n""")
+ bool success = true;
- gencom.clang_off(f,1)
- for cmds in gencom.allCommandsList:
- if gencom.isDeviceDispatchTableEntry(cmds):
- gencom.initProc(cmds, f)
- gencom.clang_on(f,1)
- f.write ('\n')
- f.write (' return success;\n}\n\n')
+ // clang-format off\n""")
- gencom.clang_off(f,0)
+ for cmd in gencom.command_list:
+ if gencom.is_device_dispatch_table_entry(cmd):
+ gencom.init_proc(cmd, f)
- f.write ('\nnamespace {\n\n')
- f.write('// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr\n')
- for cmds in gencom.allCommandsList:
- if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
- paramList = [''.join(i) for i in gencom.paramDict[cmds]]
- f.write ('VKAPI_ATTR '+gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ');\n')
+ f.write("""\
+ // clang-format on
- f.write ('\n')
+ return success;
+}
- for cmds in gencom.allCommandsList:
- if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
- paramList = [''.join(i) for i in gencom.paramDict[cmds]]
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ') {\n')
- if cmds == 'vkGetInstanceProcAddr':
- interceptInstanceProcAddr(cmds, f)
- elif cmds == 'vkGetDeviceProcAddr':
- interceptDeviceProcAddr(cmds, f)
- apiDispatch(cmds, f)
+// clang-format off
+
+namespace {
+
+// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
+""")
+
+ for cmd in gencom.command_list:
+ if gencom.is_function_exported(cmd) and not _is_intercepted(cmd):
+ param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+ f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+ gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n')
+
+ f.write('\n')
+ for cmd in gencom.command_list:
+ if gencom.is_function_exported(cmd) and not _is_intercepted(cmd):
+ param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+ f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+ gencom.base_name(cmd) + '(' + ', '.join(param_list) + ') {\n')
+ if cmd == 'vkGetInstanceProcAddr':
+ _intercept_instance_proc_addr(f)
+ elif cmd == 'vkGetDeviceProcAddr':
+ _intercept_device_proc_addr(f)
+ _api_dispatch(cmd, f)
f.write('}\n\n')
- f.write ("""\n} // anonymous namespace
+
+ f.write("""
+} // anonymous namespace
// clang-format on
@@ -329,18 +360,19 @@
// clang-format off\n\n""")
- for cmds in gencom.allCommandsList:
- if gencom.isFunctionExported(cmds):
- paramList = [''.join(i) for i in gencom.paramDict[cmds]]
- f.write ('__attribute__((visibility("default")))\n')
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds + '(' + ', '.join(paramList) + ') {\n')
- f.write (gencom.clang_off_spaces)
- if gencom.returnTypeDict[cmds] != 'void':
- f.write ('return ')
- paramList = gencom.paramDict[cmds]
- f.write ('vulkan::api::' + cmds[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
- f.write ('}\n\n')
+ for cmd in gencom.command_list:
+ if gencom.is_function_exported(cmd):
+ param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+ f.write('__attribute__((visibility("default")))\n')
+ f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+ cmd + '(' + ', '.join(param_list) + ') {\n')
+ f.write(gencom.indent(1))
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write('return ')
+ param_list = gencom.param_dict[cmd]
+ f.write('vulkan::api::' + gencom.base_name(cmd) +
+ '(' + ', '.join(i[1] for i in param_list) + ');\n}\n\n')
- gencom.clang_on(f, 0)
+ f.write('// clang-format on\n')
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
diff --git a/vulkan/scripts/code_generator.py b/vulkan/scripts/code_generator.py
index 39fedf4..378a9c0 100755
--- a/vulkan/scripts/code_generator.py
+++ b/vulkan/scripts/code_generator.py
@@ -17,16 +17,16 @@
# This script provides the main function for generating
# vulkan framework directly from the vulkan registry (vk.xml).
-import generator_common as gencom
-import api_generator as apigen
-import driver_generator as drivergen
-import null_generator as nullgen
+import api_generator
+import driver_generator
+import generator_common
+import null_generator
if __name__ == '__main__':
- gencom.parseVulkanRegistry()
- apigen.api_genh()
- apigen.api_gencpp()
- drivergen.driver_genh()
- drivergen.driver_gencpp()
- nullgen.null_driver_genh()
- nullgen.null_driver_gencpp()
+ generator_common.parse_vulkan_registry()
+ api_generator.gen_h()
+ api_generator.gen_cpp()
+ driver_generator.gen_h()
+ driver_generator.gen_cpp()
+ null_generator.gen_h()
+ null_generator.gen_cpp()
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index 4868ac0..5fff83e 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -17,41 +17,147 @@
# This script provides the functions for generating the
# vulkan driver framework directly from the vulkan registry (vk.xml).
-import generator_common as gencom
import os
+import generator_common as gencom
-interceptedExtensions = [
- 'VK_ANDROID_native_buffer',
- 'VK_EXT_debug_report',
- 'VK_EXT_hdr_metadata',
- 'VK_EXT_swapchain_colorspace',
- 'VK_GOOGLE_display_timing',
- 'VK_KHR_android_surface',
- 'VK_KHR_get_surface_capabilities2',
- 'VK_KHR_incremental_present',
- 'VK_KHR_shared_presentable_image',
- 'VK_KHR_surface',
- 'VK_KHR_swapchain',
+_INTERCEPTED_EXTENSIONS = [
+ 'VK_ANDROID_native_buffer',
+ 'VK_EXT_debug_report',
+ 'VK_EXT_hdr_metadata',
+ 'VK_EXT_swapchain_colorspace',
+ 'VK_GOOGLE_display_timing',
+ 'VK_KHR_android_surface',
+ 'VK_KHR_get_surface_capabilities2',
+ 'VK_KHR_incremental_present',
+ 'VK_KHR_shared_presentable_image',
+ 'VK_KHR_surface',
+ 'VK_KHR_swapchain',
]
-knownExtensions = interceptedExtensions + [
- 'VK_ANDROID_external_memory_android_hardware_buffer',
- 'VK_KHR_bind_memory2',
- 'VK_KHR_get_physical_device_properties2',
+_KNOWN_EXTENSIONS = _INTERCEPTED_EXTENSIONS + [
+ 'VK_ANDROID_external_memory_android_hardware_buffer',
+ 'VK_KHR_bind_memory2',
+ 'VK_KHR_get_physical_device_properties2',
]
-def defineProcHookType(f):
- f.write ("""struct ProcHook {
+_NEEDED_COMMANDS = [
+ # Create functions of dispatchable objects
+ 'vkCreateDevice',
+ 'vkGetDeviceQueue',
+ 'vkGetDeviceQueue2',
+ 'vkAllocateCommandBuffers',
+
+ # Destroy functions of dispatchable objects
+ 'vkDestroyInstance',
+ 'vkDestroyDevice',
+
+ # Enumeration of extensions
+ 'vkEnumerateDeviceExtensionProperties',
+
+ # We cache physical devices in loader.cpp
+ 'vkEnumeratePhysicalDevices',
+ 'vkEnumeratePhysicalDeviceGroups',
+
+ 'vkGetInstanceProcAddr',
+ 'vkGetDeviceProcAddr',
+
+ 'vkQueueSubmit',
+
+ # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
+ 'vkCreateImage',
+ 'vkDestroyImage',
+
+ 'vkGetPhysicalDeviceProperties',
+ 'vkGetPhysicalDeviceProperties2',
+ 'vkGetPhysicalDeviceProperties2KHR',
+
+ # VK_KHR_swapchain v69 requirement
+ 'vkBindImageMemory2',
+ 'vkBindImageMemory2KHR',
+]
+
+_INTERCEPTED_COMMANDS = [
+ # Create functions of dispatchable objects
+ 'vkCreateInstance',
+ 'vkCreateDevice',
+ 'vkEnumeratePhysicalDevices',
+ 'vkEnumeratePhysicalDeviceGroups',
+ 'vkGetDeviceQueue',
+ 'vkGetDeviceQueue2',
+ 'vkAllocateCommandBuffers',
+
+ # Destroy functions of dispatchable objects
+ 'vkDestroyInstance',
+ 'vkDestroyDevice',
+
+ # Enumeration of extensions
+ 'vkEnumerateInstanceExtensionProperties',
+ 'vkEnumerateDeviceExtensionProperties',
+
+ 'vkGetInstanceProcAddr',
+ 'vkGetDeviceProcAddr',
+
+ 'vkQueueSubmit',
+
+ # VK_KHR_swapchain v69 requirement
+ 'vkBindImageMemory2',
+ 'vkBindImageMemory2KHR',
+]
+
+
+def _is_driver_table_entry(cmd):
+ if gencom.is_function_supported(cmd):
+ if cmd in _NEEDED_COMMANDS:
+ return True
+ if cmd in gencom.extension_dict:
+ if (gencom.extension_dict[cmd] == 'VK_ANDROID_native_buffer' or
+ gencom.extension_dict[cmd] == 'VK_EXT_debug_report'):
+ return True
+ return False
+
+
+def _is_instance_driver_table_entry(cmd):
+ return (_is_driver_table_entry(cmd) and
+ gencom.is_instance_dispatched(cmd))
+
+
+def _is_device_driver_table_entry(cmd):
+ return (_is_driver_table_entry(cmd) and
+ gencom.is_device_dispatched(cmd))
+
+
+def gen_h():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'libvulkan', 'driver_gen.h')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2016))
+
+ f.write("""\
+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+
+#include <bitset>
+
+namespace vulkan {
+namespace driver {
+
+struct ProcHook {
enum Type {
GLOBAL,
INSTANCE,
DEVICE,
};
enum Extension {\n""")
- for exts in knownExtensions:
- f.write (gencom.clang_off_spaces*2 + exts[3:] + ',\n')
- f.write ('\n')
- f.write (gencom.clang_off_spaces*2 + """EXTENSION_CORE, // valid bit
+
+ for exts in _KNOWN_EXTENSIONS:
+ f.write(gencom.indent(2) + exts[3:] + ',\n')
+
+ f.write("""
+ EXTENSION_CORE, // valid bit
EXTENSION_COUNT,
EXTENSION_UNKNOWN,
};
@@ -62,99 +168,33 @@
PFN_vkVoidFunction proc;
PFN_vkVoidFunction checked_proc; // always nullptr for non-device hooks
-};\n\n""")
+};
-def isExtensionIntercepted(extensionName):
- if extensionName in interceptedExtensions:
- return True
- return False
+struct InstanceDriverTable {
+ // clang-format off\n""")
-def isDriverTableEntry(functionName):
- switchCase = {
- # Create functions of dispatchable objects
- 'vkCreateDevice' : True,
- 'vkGetDeviceQueue' : True,
- 'vkGetDeviceQueue2' : True,
- 'vkAllocateCommandBuffers' : True,
+ for cmd in gencom.command_list:
+ if _is_instance_driver_table_entry(cmd):
+ f.write(gencom.indent(1) + 'PFN_' + cmd + ' ' +
+ gencom.base_name(cmd) + ';\n')
- # Destroy functions of dispatchable objects
- 'vkDestroyInstance' : True,
- 'vkDestroyDevice' : True,
+ f.write("""\
+ // clang-format on
+};
- # Enumeration of extensions
- 'vkEnumerateDeviceExtensionProperties' : True,
+struct DeviceDriverTable {
+ // clang-format off\n""")
- # We cache physical devices in loader.cpp
- 'vkEnumeratePhysicalDevices' : True,
- 'vkEnumeratePhysicalDeviceGroups' : True,
+ for cmd in gencom.command_list:
+ if _is_device_driver_table_entry(cmd):
+ f.write(gencom.indent(1) + 'PFN_' + cmd + ' ' +
+ gencom.base_name(cmd) + ';\n')
- 'vkGetInstanceProcAddr' : True,
- 'vkGetDeviceProcAddr' : True,
+ f.write("""\
+ // clang-format on
+};
- 'vkQueueSubmit' : True,
-
- # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
- 'vkCreateImage' : True,
- 'vkDestroyImage' : True,
-
- 'vkGetPhysicalDeviceProperties' : True,
- 'vkGetPhysicalDeviceProperties2' : True,
- 'vkGetPhysicalDeviceProperties2KHR' : True,
-
- # VK_KHR_swapchain v69 requirement
- 'vkBindImageMemory2' : True,
- 'vkBindImageMemory2KHR' : True
- }
- if gencom.isFunctionSupported(functionName):
- if functionName in switchCase:
- return True
- if functionName in gencom.extensionsDict:
- if gencom.extensionsDict[functionName] == 'VK_ANDROID_native_buffer' or gencom.extensionsDict[functionName] == 'VK_EXT_debug_report':
- return True
- return False
-
-def isInstanceDriverTableEntry(functionName):
- if isDriverTableEntry(functionName) and gencom.isInstanceDispatched(functionName):
- return True
- return False
-
-def isDeviceDriverTableEntry(functionName):
- if isDriverTableEntry(functionName) and gencom.isDeviceDispatched(functionName):
- return True
- return False
-
-def driver_genh():
- header = """#ifndef LIBVULKAN_DRIVER_GEN_H
-#define LIBVULKAN_DRIVER_GEN_H
-
-#include <vulkan/vk_android_native_buffer.h>
-#include <vulkan/vulkan.h>
-
-#include <bitset>
-
-namespace vulkan {
-namespace driver {\n\n"""
- genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.h')
- with open(genfile, 'w') as f:
- f.write (gencom.copyright)
- f.write (gencom.warning)
- f.write (header)
- defineProcHookType(f)
- f.write ('struct InstanceDriverTable {\n')
- gencom.clang_off(f, 1)
- for cmds in gencom.allCommandsList:
- if isInstanceDriverTableEntry(cmds):
- f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
- gencom.clang_on(f, 1)
- f.write ('};\n\n')
- f.write ('struct DeviceDriverTable {\n')
- gencom.clang_off(f,1)
- for cmds in gencom.allCommandsList:
- if isDeviceDriverTableEntry(cmds):
- f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
- gencom.clang_on(f,1)
- f.write ('};\n\n')
- f.write ("""const ProcHook* GetProcHook(const char* name);
+const ProcHook* GetProcHook(const char* name);
ProcHook::Extension GetProcHookExtension(const char* name);
bool InitDriverTable(VkInstance instance,
@@ -168,148 +208,131 @@
} // namespace vulkan
#endif // LIBVULKAN_DRIVER_TABLE_H\n""")
+
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
-def isIntercepted(functionName):
- switchCase = {
- # Create functions of dispatchable objects
- 'vkCreateInstance' : True,
- 'vkCreateDevice' : True,
- 'vkEnumeratePhysicalDevices' : True,
- 'vkEnumeratePhysicalDeviceGroups' : True,
- 'vkGetDeviceQueue' : True,
- 'vkGetDeviceQueue2' : True,
- 'vkAllocateCommandBuffers' : True,
- # Destroy functions of dispatchable objects
- 'vkDestroyInstance' : True,
- 'vkDestroyDevice' : True,
+def _is_intercepted(cmd):
+ if gencom.is_function_supported(cmd):
+ if cmd in _INTERCEPTED_COMMANDS:
+ return True
- # Enumeration of extensions
- 'vkEnumerateInstanceExtensionProperties' : True,
- 'vkEnumerateDeviceExtensionProperties' : True,
-
- 'vkGetInstanceProcAddr' : True,
- 'vkGetDeviceProcAddr' : True,
-
- 'vkQueueSubmit' : True,
-
- # VK_KHR_swapchain v69 requirement
- 'vkBindImageMemory2' : True,
- 'vkBindImageMemory2KHR' : True
- }
- if gencom.isFunctionSupported(functionName):
- if functionName in switchCase:
- return switchCase[functionName]
-
- if functionName in gencom.extensionsDict:
- return isExtensionIntercepted(gencom.extensionsDict[functionName])
+ if cmd in gencom.extension_dict:
+ return gencom.extension_dict[cmd] in _INTERCEPTED_EXTENSIONS
return False
-def needProcHookStub(functionName):
- if isIntercepted(functionName) and gencom.isDeviceDispatched(functionName):
- if functionName in gencom.extensionsDict:
- if not gencom.isExtensionInternal(gencom.extensionsDict[functionName]):
+
+def _need_proc_hook_stub(cmd):
+ if _is_intercepted(cmd) and gencom.is_device_dispatched(cmd):
+ if cmd in gencom.extension_dict:
+ if not gencom.is_extension_internal(gencom.extension_dict[cmd]):
return True
return False
-def defineInitProc(name, f):
- f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
- f.write ('\n')
- f.write ("""#define INIT_PROC(required, obj, proc) \\
- do { \\
- data.""" + name + """.proc = \\
- reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
- if (UNLIKELY(required && !data.""" + name + """.proc)) { \\
- ALOGE("missing " #obj " proc: vk" #proc); \\
- success = false; \\
- } \\
- } while (0)\n\n""")
-def defineInitProcExt(f):
- f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\
- do { \\
- if (extensions[ProcHook::ext]) \\
- INIT_PROC(required, obj, proc); \\
- } while (0)\n\n""")
-
-def defineProcHookStub(functionName, f):
- if needProcHookStub(functionName):
- ext_name = gencom.extensionsDict[functionName]
- base_name = functionName[2:]
- paramList = [''.join(i) for i in gencom.paramDict[functionName]]
- p0 = gencom.paramDict[functionName][0][1]
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' checked' + base_name + '(' + ', '.join(paramList) + ') {\n')
+def _define_proc_hook_stub(cmd, f):
+ if _need_proc_hook_stub(cmd):
+ return_type = gencom.return_type_dict[cmd]
+ ext_name = gencom.extension_dict[cmd]
ext_hook = 'ProcHook::' + ext_name[3:]
+ handle = gencom.param_dict[cmd][0][1]
+ param_types = ', '.join([''.join(i) for i in gencom.param_dict[cmd]])
+ param_names = ', '.join([''.join(i[1]) for i in gencom.param_dict[cmd]])
- f.write (gencom.clang_off_spaces + 'if (GetData(' + p0 + ').hook_extensions[' + ext_hook + ']) {\n')
- f.write (gencom.clang_off_spaces *2)
- if gencom.returnTypeDict[functionName] != 'void':
- f.write ('return ')
- paramNames = [''.join(i[1]) for i in gencom.paramDict[functionName]]
- f.write (base_name + '(' + ', '.join(paramNames) + ');\n')
- f.write (gencom.clang_off_spaces + '} else {\n')
- f.write (gencom.clang_off_spaces*2 + 'Logger(' + p0 + ').Err(' + p0 + ', \"' + ext_name + ' not enabled. ' + functionName + ' not executed.\");\n')
- if gencom.returnTypeDict[functionName] != 'void':
- f.write (gencom.clang_off_spaces*2 + 'return VK_SUCCESS;\n')
- f.write (gencom.clang_off_spaces + '}\n')
- f.write ('}\n\n')
+ f.write('VKAPI_ATTR ' + return_type + ' checked' + gencom.base_name(cmd) +
+ '(' + param_types + ') {\n')
+ f.write(gencom.indent(1) + 'if (GetData(' + handle + ').hook_extensions[' +
+ ext_hook + ']) {\n')
-def defineGlobalProcHook(functionName, f):
- base_name = functionName[2:]
- assert (functionName not in gencom.extensionsDict)
- f.write (gencom.clang_off_spaces + '{\n' + gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n' + gencom.clang_off_spaces*2)
- f.write ("""ProcHook::GLOBAL,
+ f.write(gencom.indent(2))
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write('return ')
+ f.write(gencom.base_name(cmd) + '(' + param_names + ');\n')
+
+ f.write(gencom.indent(1) + '} else {\n')
+ f.write(gencom.indent(2) + 'Logger(' + handle + ').Err(' + handle + ', \"' +
+ ext_name + ' not enabled. ' + cmd + ' not executed.\");\n')
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write(gencom.indent(2) + 'return VK_SUCCESS;\n')
+ f.write(gencom.indent(1) + '}\n}\n\n')
+
+
+def _define_global_proc_hook(cmd, f):
+ assert cmd not in gencom.extension_dict
+
+ f.write(gencom.indent(1) + '{\n')
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+ f.write("""\
+ ProcHook::GLOBAL,
ProcHook::EXTENSION_CORE,
- reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
nullptr,
},\n""")
-def defineInstanceProcHook(functionName, f):
- base_name = functionName[2:]
- f.write (gencom.clang_off_spaces + '{\n')
- f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
- f.write (gencom.clang_off_spaces*2 + 'ProcHook::INSTANCE,\n')
- if functionName in gencom.extensionsDict:
- ext_name = gencom.extensionsDict[functionName]
- f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
- if gencom.isExtensionInternal(ext_name):
- f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+def _define_instance_proc_hook(cmd, f):
+ f.write(gencom.indent(1) + '{\n')
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+ f.write(gencom.indent(2) + 'ProcHook::INSTANCE,\n')
+
+ if cmd in gencom.extension_dict:
+ ext_name = gencom.extension_dict[cmd]
+ f.write(gencom.indent(2) + 'ProcHook::' + ext_name[3:] + ',\n')
+
+ if gencom.is_extension_internal(ext_name):
+ f.write("""\
+ nullptr,
+ nullptr,\n""")
else:
- f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
-
+ f.write("""\
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
+ nullptr,\n""")
else:
- f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
- reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+ f.write("""\
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
nullptr,\n""")
- f.write (gencom.clang_off_spaces + '},\n')
+ f.write(gencom.indent(1) + '},\n')
-def defineDeviceProcHook(functionName, f):
- base_name = functionName[2:]
- f.write (gencom.clang_off_spaces + '{\n')
- f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
- f.write (gencom.clang_off_spaces*2 + 'ProcHook::DEVICE,\n')
- if functionName in gencom.extensionsDict:
- ext_name = gencom.extensionsDict[functionName]
- f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
- if gencom.isExtensionInternal(ext_name):
- f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+def _define_device_proc_hook(cmd, f):
+ f.write(gencom.indent(1) + '{\n')
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+ f.write(gencom.indent(2) + 'ProcHook::DEVICE,\n')
+
+ if cmd in gencom.extension_dict:
+ ext_name = gencom.extension_dict[cmd]
+ f.write(gencom.indent(2) + 'ProcHook::' + ext_name[3:] + ',\n')
+
+ if gencom.is_extension_internal(ext_name):
+ f.write("""\
+ nullptr,
+ nullptr,\n""")
else:
- f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(checked' + base_name + '),\n')
+ f.write("""\
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
+ reinterpret_cast<PFN_vkVoidFunction>(checked""" +
+ gencom.base_name(cmd) + '),\n')
else:
- f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
- reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+ f.write("""\
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
nullptr,\n""")
- f.write (gencom.clang_off_spaces + '},\n')
+ f.write(gencom.indent(1) + '},\n')
-def driver_gencpp():
- header = """#include <log/log.h>
+
+def gen_cpp():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'libvulkan', 'driver_gen.cpp')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2016))
+ f.write("""\
+#include <log/log.h>
#include <string.h>
#include <algorithm>
@@ -321,35 +344,34 @@
namespace {
-// clang-format off\n\n"""
+// clang-format off\n\n""")
- genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.cpp')
+ for cmd in gencom.command_list:
+ _define_proc_hook_stub(cmd, f)
- with open(genfile, 'w') as f:
- f.write (gencom.copyright)
- f.write (gencom.warning)
- f.write (header)
+ f.write("""\
+// clang-format on
- for cmds in gencom.allCommandsList:
- defineProcHookStub(cmds, f)
- gencom.clang_on(f, 0)
- f.write ('\n')
+const ProcHook g_proc_hooks[] = {
+ // clang-format off\n""")
- f.write ('const ProcHook g_proc_hooks[] = {\n')
- gencom.clang_off(f, 1)
- sortedCommandsList = sorted(gencom.allCommandsList)
- for cmds in sortedCommandsList:
- if isIntercepted(cmds):
- if gencom.isGloballyDispatched(cmds):
- defineGlobalProcHook(cmds, f)
- elif gencom.isInstanceDispatched(cmds):
- defineInstanceProcHook(cmds, f)
- elif gencom.isDeviceDispatched(cmds):
- defineDeviceProcHook(cmds, f)
- gencom.clang_on(f, 1)
- f.write ('};\n\n} // namespace\n\n')
+ sorted_command_list = sorted(gencom.command_list)
+ for cmd in sorted_command_list:
+ if _is_intercepted(cmd):
+ if gencom.is_globally_dispatched(cmd):
+ _define_global_proc_hook(cmd, f)
+ elif gencom.is_instance_dispatched(cmd):
+ _define_instance_proc_hook(cmd, f)
+ elif gencom.is_device_dispatched(cmd):
+ _define_device_proc_hook(cmd, f)
- f.write ("""const ProcHook* GetProcHook(const char* name) {
+ f.write("""\
+ // clang-format on
+};
+
+} // namespace
+
+const ProcHook* GetProcHook(const char* name) {
const auto& begin = g_proc_hooks;
const auto& end =
g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
@@ -357,44 +379,76 @@
begin, end, name,
[](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
-}\n\n""")
+}
- f.write ('ProcHook::Extension GetProcHookExtension(const char* name) {\n')
- gencom.clang_off(f, 1)
- for exts in knownExtensions:
- f.write (gencom.clang_off_spaces + 'if (strcmp(name, \"' + exts + '\") == 0) return ProcHook::' + exts[3:] + ';\n')
- gencom.clang_on(f, 1)
- f.write (gencom.clang_off_spaces + 'return ProcHook::EXTENSION_UNKNOWN;\n')
- f.write ('}\n\n')
+ProcHook::Extension GetProcHookExtension(const char* name) {
+ // clang-format off\n""")
- defineInitProc('driver', f)
- defineInitProcExt(f)
+ for exts in _KNOWN_EXTENSIONS:
+ f.write(gencom.indent(1) + 'if (strcmp(name, \"' + exts +
+ '\") == 0) return ProcHook::' + exts[3:] + ';\n')
- f.write ("""bool InitDriverTable(VkInstance instance,
+ f.write("""\
+ // clang-format on
+ return ProcHook::EXTENSION_UNKNOWN;
+}
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+#define INIT_PROC(required, obj, proc) \\
+ do { \\
+ data.driver.proc = \\
+ reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+ if (UNLIKELY(required && !data.driver.proc)) { \\
+ ALOGE("missing " #obj " proc: vk" #proc); \\
+ success = false; \\
+ } \\
+ } while (0)
+
+#define INIT_PROC_EXT(ext, required, obj, proc) \\
+ do { \\
+ if (extensions[ProcHook::ext]) \\
+ INIT_PROC(required, obj, proc); \\
+ } while (0)
+
+bool InitDriverTable(VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc,
const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
auto& data = GetData(instance);
- bool success = true;\n\n""")
- gencom.clang_off(f, 1)
- for cmds in gencom.allCommandsList:
- if isInstanceDriverTableEntry(cmds):
- gencom.initProc(cmds, f)
- gencom.clang_on(f, 1)
- f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
- f.write ('}\n\n')
+ bool success = true;
- f.write ("""bool InitDriverTable(VkDevice dev,
+ // clang-format off\n""")
+
+ for cmd in gencom.command_list:
+ if _is_instance_driver_table_entry(cmd):
+ gencom.init_proc(cmd, f)
+
+ f.write("""\
+ // clang-format on
+
+ return success;
+}
+
+bool InitDriverTable(VkDevice dev,
PFN_vkGetDeviceProcAddr get_proc,
const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
auto& data = GetData(dev);
- bool success = true;\n\n""")
- gencom.clang_off(f, 1)
- for cmds in gencom.allCommandsList:
- if isDeviceDriverTableEntry(cmds):
- gencom.initProc(cmds, f)
- gencom.clang_on(f, 1)
- f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
- f.write ('}\n\n} // namespace driver\n} // namespace vulkan\n\n')
- gencom.clang_on(f, 0)
+ bool success = true;
+
+ // clang-format off\n""")
+
+ for cmd in gencom.command_list:
+ if _is_device_driver_table_entry(cmd):
+ gencom.init_proc(cmd, f)
+
+ f.write("""\
+ // clang-format on
+
+ return success;
+}
+
+} // namespace driver
+} // namespace vulkan\n""")
+
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
index f1f09d5..03993e2 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -17,29 +17,11 @@
# This script provides the common functions for generating the
# vulkan framework directly from the vulkan registry (vk.xml).
-from subprocess import check_call
+import os
+import subprocess
+import xml.etree.ElementTree as element_tree
-copyright = """/*
- * Copyright 2016 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.
- */
-
-"""
-
-warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n'
-
-blacklistedExtensions = [
+_BLACKLISTED_EXTENSIONS = [
'VK_EXT_acquire_xlib_display',
'VK_EXT_direct_mode_display',
'VK_EXT_display_control',
@@ -70,191 +52,218 @@
'VK_NVX_image_view_handle',
]
-exportedExtensions = [
+_EXPORTED_EXTENSIONS = [
'VK_ANDROID_external_memory_android_hardware_buffer',
'VK_KHR_android_surface',
'VK_KHR_surface',
'VK_KHR_swapchain',
]
-optionalCommands = [
+_OPTIONAL_COMMANDS = [
'vkGetSwapchainGrallocUsageANDROID',
'vkGetSwapchainGrallocUsage2ANDROID',
]
-def runClangFormat(args):
- clang_call = ["clang-format", "--style", "file", "-i", args]
- check_call (clang_call)
+_DISPATCH_TYPE_DICT = {
+ 'VkInstance ': 'Instance',
+ 'VkPhysicalDevice ': 'Instance',
+ 'VkDevice ': 'Device',
+ 'VkQueue ': 'Device',
+ 'VkCommandBuffer ': 'Device'
+}
-def isExtensionInternal(extensionName):
- if extensionName == 'VK_ANDROID_native_buffer':
- return True
- return False
+alias_dict = {}
+command_list = []
+extension_dict = {}
+param_dict = {}
+return_type_dict = {}
+version_dict = {}
-def isFunctionSupported(functionName):
- if functionName not in extensionsDict:
+
+def indent(num):
+ return ' ' * num
+
+
+def copyright_and_warning(year):
+ return """\
+/*
+ * Copyright """ + str(year) + """ 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+"""
+
+
+def run_clang_format(args):
+ clang_call = ['clang-format', '--style', 'file', '-i', args]
+ subprocess.check_call(clang_call)
+
+
+def is_extension_internal(extension_name):
+ return extension_name == 'VK_ANDROID_native_buffer'
+
+
+def base_name(cmd):
+ return cmd[2:]
+
+
+def is_function_supported(cmd):
+ if cmd not in extension_dict:
return True
else:
- if extensionsDict[functionName] not in blacklistedExtensions:
+ if extension_dict[cmd] not in _BLACKLISTED_EXTENSIONS:
return True
return False
-def isInstanceDispatched(functionName):
- return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Instance'
-def isDeviceDispatched(functionName):
- return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Device'
-
-def isGloballyDispatched(functionName):
- return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Global'
-
-def isExtensionExported(extensionName):
- if extensionName in exportedExtensions:
- return True
- return False
-
-def isFunctionExported(functionName):
- if isFunctionSupported(functionName):
- if functionName in extensionsDict:
- return isExtensionExported(extensionsDict[functionName])
- return True
- return False
-
-def getDispatchTableType(functionName):
- if functionName not in paramDict:
+def get_dispatch_table_type(cmd):
+ if cmd not in param_dict:
return None
- switchCase = {
- 'VkInstance ' : 'Instance',
- 'VkPhysicalDevice ' : 'Instance',
- 'VkDevice ' : 'Device',
- 'VkQueue ' : 'Device',
- 'VkCommandBuffer ' : 'Device'
- }
-
- if len(paramDict[functionName]) > 0:
- return switchCase.get(paramDict[functionName][0][0], 'Global')
+ if param_dict[cmd]:
+ return _DISPATCH_TYPE_DICT.get(param_dict[cmd][0][0], 'Global')
return 'Global'
-def isInstanceDispatchTableEntry(functionName):
- if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+
+def is_globally_dispatched(cmd):
+ return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'
+
+
+def is_instance_dispatched(cmd):
+ return (is_function_supported(cmd) and
+ get_dispatch_table_type(cmd) == 'Instance')
+
+
+def is_device_dispatched(cmd):
+ return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'
+
+
+def is_extension_exported(extension_name):
+ return extension_name in _EXPORTED_EXTENSIONS
+
+
+def is_function_exported(cmd):
+ if is_function_supported(cmd):
+ if cmd in extension_dict:
+ return is_extension_exported(extension_dict[cmd])
+ return True
+ return False
+
+
+def is_instance_dispatch_table_entry(cmd):
+ if cmd == 'vkEnumerateDeviceLayerProperties':
+ # deprecated, unused internally - @dbd33bc
return False
- if isFunctionExported(functionName) and isInstanceDispatched(functionName):
- return True
- return False
-
-def isDeviceDispatchTableEntry(functionName):
- if isFunctionExported(functionName) and isDeviceDispatched(functionName):
- return True
- return False
+ return is_function_exported(cmd) and is_instance_dispatched(cmd)
-def clang_on(f, indent):
- f.write (clang_off_spaces * indent + '// clang-format on\n')
+def is_device_dispatch_table_entry(cmd):
+ return is_function_exported(cmd) and is_device_dispatched(cmd)
-def clang_off(f, indent):
- f.write (clang_off_spaces * indent + '// clang-format off\n')
-clang_off_spaces = ' ' * 4
+def init_proc(name, f):
+ f.write(indent(1))
+ if name in extension_dict:
+ f.write('INIT_PROC_EXT(' + extension_dict[name][3:] + ', ')
+ else:
+ f.write('INIT_PROC(')
-parametersList = []
-paramDict = {}
-allCommandsList = []
-extensionsDict = {}
-returnTypeDict = {}
-versionDict = {}
-aliasDict = {}
+ if name in version_dict and version_dict[name] == 'VK_VERSION_1_1':
+ f.write('false, ')
+ elif name in _OPTIONAL_COMMANDS:
+ f.write('false, ')
+ else:
+ f.write('true, ')
-def parseVulkanRegistry():
- import xml.etree.ElementTree as ET
- import os
- vulkan_registry = os.path.join(os.path.dirname(__file__),'..','..','..','..','external','vulkan-headers','registry','vk.xml')
- tree = ET.parse(vulkan_registry)
+ if is_instance_dispatched(name):
+ f.write('instance, ')
+ else:
+ f.write('dev, ')
+
+ f.write(base_name(name) + ');\n')
+
+
+def parse_vulkan_registry():
+ registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
+ 'external', 'vulkan-headers', 'registry', 'vk.xml')
+ tree = element_tree.parse(registry)
root = tree.getroot()
for commands in root.iter('commands'):
for command in commands:
if command.tag == 'command':
- parametersList.clear()
+ parameter_list = []
protoset = False
- fnName = ""
- fnType = ""
- if command.get('alias') != None:
+ cmd_name = ''
+ cmd_type = ''
+ if command.get('alias') is not None:
alias = command.get('alias')
- fnName = command.get('name')
- aliasDict[fnName] = alias
- allCommandsList.append(fnName)
- paramDict[fnName] = paramDict[alias].copy()
- returnTypeDict[fnName] = returnTypeDict[alias]
+ cmd_name = command.get('name')
+ alias_dict[cmd_name] = alias
+ command_list.append(cmd_name)
+ param_dict[cmd_name] = param_dict[alias].copy()
+ return_type_dict[cmd_name] = return_type_dict[alias]
for params in command:
if params.tag == 'param':
- paramtype = ""
- if params.text != None and params.text.strip() != '':
- paramtype = params.text.strip() + ' '
- typeval = params.find('type')
- paramtype = paramtype + typeval.text
- if typeval.tail != None:
- paramtype += typeval.tail.strip() + ' '
+ param_type = ''
+ if params.text is not None and params.text.strip():
+ param_type = params.text.strip() + ' '
+ type_val = params.find('type')
+ param_type = param_type + type_val.text
+ if type_val.tail is not None:
+ param_type += type_val.tail.strip() + ' '
pname = params.find('name')
- paramname = pname.text
- if pname.tail != None and pname.tail.strip() != '':
- parametersList.append((paramtype, paramname, pname.tail.strip()))
+ param_name = pname.text
+ if pname.tail is not None and pname.tail.strip():
+ parameter_list.append(
+ (param_type, param_name, pname.tail.strip()))
else:
- parametersList.append((paramtype, paramname))
+ parameter_list.append((param_type, param_name))
if params.tag == 'proto':
for c in params:
if c.tag == 'type':
- fnType = c.text
+ cmd_type = c.text
if c.tag == 'name':
- fnName = c.text
+ cmd_name = c.text
protoset = True
- allCommandsList.append(fnName)
- returnTypeDict[fnName] = fnType
- if protoset == True:
- paramDict[fnName] = parametersList.copy()
+ command_list.append(cmd_name)
+ return_type_dict[cmd_name] = cmd_type
+ if protoset:
+ param_dict[cmd_name] = parameter_list.copy()
for exts in root.iter('extensions'):
for extension in exts:
- apiversion = ""
+ apiversion = ''
if extension.tag == 'extension':
extname = extension.get('name')
for req in extension:
- if req.get('feature') != None:
+ if req.get('feature') is not None:
apiversion = req.get('feature')
for commands in req:
if commands.tag == 'command':
- commandname = commands.get('name')
- if commandname not in extensionsDict:
- extensionsDict[commandname] = extname
- if apiversion != "":
- versionDict[commandname] = apiversion
+ cmd_name = commands.get('name')
+ if cmd_name not in extension_dict:
+ extension_dict[cmd_name] = extname
+ if apiversion:
+ version_dict[cmd_name] = apiversion
for feature in root.iter('feature'):
apiversion = feature.get('name')
for req in feature:
for command in req:
if command.tag == 'command':
- cmdName = command.get('name')
- if cmdName in allCommandsList:
- versionDict[cmdName] = apiversion
-
-
-def initProc(name, f):
- if name in extensionsDict:
- f.write (' INIT_PROC_EXT(' + extensionsDict[name][3:] + ', ')
- else:
- f.write (' INIT_PROC(')
-
- if name in versionDict and versionDict[name] == 'VK_VERSION_1_1':
- f.write('false, ')
- elif name in optionalCommands:
- f.write('false, ')
- else:
- f.write('true, ')
-
- if isInstanceDispatched(name):
- f.write('instance, ')
- else:
- f.write('dev, ')
-
- f.write(name[2:] + ');\n')
-
+ cmd_name = command.get('name')
+ if cmd_name in command_list:
+ version_dict[cmd_name] = apiversion
diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py
index 3a761ce..2a99a1d 100644
--- a/vulkan/scripts/null_generator.py
+++ b/vulkan/scripts/null_generator.py
@@ -17,45 +17,31 @@
# This script provides the functions for generating the null driver
# framework directly from the vulkan registry (vk.xml).
-import generator_common as gencom
import os
+import generator_common as gencom
-copyright = """/*
- * Copyright 2015 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.
- */
+_DRIVER_EXTENSION_DICT = {
+ 'VK_ANDROID_native_buffer',
+ 'VK_EXT_debug_report',
+ 'VK_KHR_get_physical_device_properties2'
+}
-"""
-def isDriverExtension(extensionName):
- switchCase = {
- 'VK_ANDROID_native_buffer' : True,
- 'VK_EXT_debug_report' : True,
- 'VK_KHR_get_physical_device_properties2' : True
- }
-
- if extensionName in switchCase:
- return switchCase[extensionName]
- return False
-
-def isDriverFunction(functionName):
- if functionName in gencom.extensionsDict:
- return isDriverExtension(gencom.extensionsDict[functionName])
+def _is_driver_function(cmd):
+ if cmd in gencom.extension_dict:
+ return gencom.extension_dict[cmd] in _DRIVER_EXTENSION_DICT
return True
-def null_driver_genh():
- header = """#ifndef NULLDRV_NULL_DRIVER_H
+
+def gen_h():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'nulldrv', 'null_driver_gen.h')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2015))
+
+ f.write("""\
+#ifndef NULLDRV_NULL_DRIVER_H
#define NULLDRV_NULL_DRIVER_H 1
#include <vulkan/vk_android_native_buffer.h>
@@ -66,27 +52,34 @@
PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
PFN_vkVoidFunction GetInstanceProcAddr(const char* name);
-"""
- genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.h')
- with open(genfile, 'w') as f:
- f.write (copyright)
- f.write (gencom.warning)
- f.write (header)
- gencom.clang_off(f,0)
+// clang-format off\n""")
- for cmds in gencom.allCommandsList:
- if isDriverFunction(cmds):
- paramList = [''.join(i) for i in gencom.paramDict[cmds]]
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' +', '.join(paramList) + ');\n')
- gencom.clang_on(f,0)
+ for cmd in gencom.command_list:
+ if _is_driver_function(cmd):
+ param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+ f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+ gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n')
- f.write ('\n} // namespace null_driver\n')
- f.write ('\n#endif // NULLDRV_NULL_DRIVER_H\n')
+ f.write("""\
+// clang-format on
+
+} // namespace null_driver
+
+#endif // NULLDRV_NULL_DRIVER_H\n""")
+
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
-def null_driver_gencpp():
- header = """#include <algorithm>
+
+def gen_cpp():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'nulldrv', 'null_driver_gen.cpp')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2015))
+
+ f.write("""\
+#include <algorithm>
#include "null_driver_gen.h"
@@ -116,30 +109,36 @@
}
const NameProc kGlobalProcs[] = {
-"""
- genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.cpp')
- with open(genfile, 'w') as f:
- f.write (copyright)
- f.write (gencom.warning)
- f.write (header)
- gencom.clang_off(f,1)
+ // clang-format off\n""")
- sortedCommandsList = sorted(gencom.allCommandsList)
- for cmds in sortedCommandsList:
- if isDriverFunction(cmds) and gencom.getDispatchTableType(cmds) == 'Global':
- f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
- gencom.clang_on(f,1)
- f.write ('};\n\n')
+ sorted_command_list = sorted(gencom.command_list)
+ for cmd in sorted_command_list:
+ if (_is_driver_function(cmd) and
+ gencom.get_dispatch_table_type(cmd) == 'Global'):
+ f.write(gencom.indent(1) + '{\"' + cmd +
+ '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' +
+ cmd + '>(' + gencom.base_name(cmd) + '))},\n')
- f.write ('const NameProc kInstanceProcs[] = {\n')
- gencom.clang_off(f,1)
- for cmds in sortedCommandsList:
- if isDriverFunction(cmds):
- f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
- gencom.clang_on(f,1)
- f.write ('};\n\n} // namespace\n\n')
+ f.write("""\
+ // clang-format on
+};
- f.write ("""namespace null_driver {
+const NameProc kInstanceProcs[] = {
+ // clang-format off\n""")
+
+ for cmd in sorted_command_list:
+ if _is_driver_function(cmd):
+ f.write(gencom.indent(1) + '{\"' + cmd +
+ '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' +
+ cmd + '>(' + gencom.base_name(cmd) + '))},\n')
+
+ f.write("""\
+ // clang-format on
+};
+
+} // namespace
+
+namespace null_driver {
PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
return Lookup(name, kGlobalProcs);
@@ -150,6 +149,6 @@
}
} // namespace null_driver\n""")
- f.close()
- gencom.runClangFormat(genfile)
+ f.close()
+ gencom.run_clang_format(genfile)