Merge "SF: Scheduler add strong typing helpers."
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/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index 2d6292c..09a5f39 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -52,10 +52,6 @@
"libutils",
],
- required: [
- "libandroid_runtime",
- ],
-
export_include_dirs: [
"include",
],
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 9da9c13..60f047f 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -115,18 +115,23 @@
}
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
- return noteOp(op, uid, callingPackage, String16("noteOp from native code"));
+ return noteOp(op, uid, callingPackage, String16(), String16());
}
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage,
- const String16& message) {
+ const String16& featureId, const String16& message) {
sp<IAppOpsService> service = getService();
int32_t mode = service != nullptr
? service->noteOperation(op, uid, callingPackage)
: APP_OPS_MANAGER_UNAVAILABLE_MODE;
if (mode == AppOpsManager::MODE_ALLOWED) {
- markAppOpNoted(uid, callingPackage, op, message);
+ if (message.size() == 0) {
+ markAppOpNoted(uid, callingPackage, op, featureId,
+ String16("noteOp from native code"));
+ } else {
+ markAppOpNoted(uid, callingPackage, op, featureId, message);
+ }
}
return mode;
@@ -134,19 +139,23 @@
int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
bool startIfModeDefault) {
- return startOpNoThrow(op, uid, callingPackage, startIfModeDefault,
- String16("startOpNoThrow from native code"));
+ return startOpNoThrow(op, uid, callingPackage, startIfModeDefault, String16(), String16());
}
int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
- bool startIfModeDefault, const String16& message) {
+ bool startIfModeDefault, const String16& featureId, const String16& message) {
sp<IAppOpsService> service = getService();
int32_t mode = service != nullptr
? service->startOperation(getToken(service), op, uid, callingPackage,
startIfModeDefault) : APP_OPS_MANAGER_UNAVAILABLE_MODE;
if (mode == AppOpsManager::MODE_ALLOWED) {
- markAppOpNoted(uid, callingPackage, op, message);
+ if (message.size() == 0) {
+ markAppOpNoted(uid, callingPackage, op, featureId,
+ String16("startOp from native code"));
+ } else {
+ markAppOpNoted(uid, callingPackage, op, featureId, message);
+ }
}
return mode;
@@ -198,7 +207,7 @@
}
void AppOpsManager::markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
- const String16& message) {
+ const String16& featureId, const String16& message) {
// check it the appops needs to be collected and cache result
if (appOpsToNote[opCode] == 0) {
if (shouldCollectNotes(opCode)) {
@@ -212,14 +221,16 @@
return;
}
- noteAsyncOp(String16(), uid, packageName, opCode, message);
+ noteAsyncOp(String16(), uid, packageName, opCode, featureId, message);
}
void AppOpsManager::noteAsyncOp(const String16& callingPackageName, int32_t uid,
- const String16& packageName, int32_t opCode, const String16& message) {
+ const String16& packageName, int32_t opCode, const String16& featureId,
+ const String16& message) {
sp<IAppOpsService> service = getService();
if (service != nullptr) {
- return service->noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+ return service->noteAsyncOp(callingPackageName, uid, packageName, opCode, featureId,
+ message);
}
}
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/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index 6c16c2d..9760e13 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -145,7 +145,8 @@
}
virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
- const String16& packageName, int32_t opCode, const String16& message) {
+ const String16& packageName, int32_t opCode, const String16& featureId,
+ const String16& message) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
@@ -166,6 +167,14 @@
}
data.writeInt32(opCode);
+
+ // Convert empty featureId into null string
+ if (featureId.size() != 0) {
+ data.writeString16(featureId);
+ } else {
+ data.writeString16(nullptr, 0);
+ }
+
data.writeString16(message);
remote()->transact(NOTE_ASYNC_OP_TRANSACTION, data, &reply);
}
@@ -291,8 +300,9 @@
int32_t uid = data.readInt32();
String16 packageName = data.readString16();
int32_t opCode = data.readInt32();
+ String16 featureId = data.readString16();
String16 message = data.readString16();
- noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+ noteAsyncOp(callingPackageName, uid, packageName, opCode, featureId, message);
reply->writeNoException();
return NO_ERROR;
} break;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 573a038..323e079 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(...)
@@ -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 {
@@ -2630,11 +2562,13 @@
if (objectsSize == 0) {
free(mObjects);
mObjects = nullptr;
+ mObjectsCapacity = 0;
} else {
binder_size_t* objects =
(binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
if (objects) {
mObjects = objects;
+ mObjectsCapacity = objectsSize;
}
}
mObjectsSize = objectsSize;
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 136bdb0..b3afd81 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "binderSafeInterfaceTest"
},
{
+ "name": "binderVendorDoubleLoadTest"
+ },
+ {
"name": "binderDriverInterfaceTest"
},
{
@@ -14,6 +17,9 @@
},
{
"name": "binderStabilityTest"
+ },
+ {
+ "name": "CtsNdkBinderTestCases"
}
]
}
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 929e2c3..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();
@@ -74,6 +77,10 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size <= 1) return 0; // no use
+
+ // avoid timeouts, see b/142617274, b/142473153
+ if (size > 50000) return 0;
+
uint8_t options = *data;
data++;
size--;
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 0ab40b8..2744ce1 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -130,16 +130,17 @@
int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
int32_t checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
const String16& callingPackage);
- // @Deprecated, use noteOp(int32_t, int32_t uid, const String16&, const String16&) instead
+ // @Deprecated, use noteOp(int32_t, int32_t uid, const String16&, const String16&,
+ // const String16&) instead
int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage,
- const String16& message);
- // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&)
- // instead
+ const String16& featureId, const String16& message);
+ // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&,
+ // const String16&) instead
int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
bool startIfModeDefault);
int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
- bool startIfModeDefault, const String16& message);
+ bool startIfModeDefault, const String16& featureId, const String16& message);
void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback);
@@ -147,7 +148,7 @@
int32_t permissionToOpCode(const String16& permission);
void setCameraAudioRestriction(int32_t mode);
void noteAsyncOp(const String16& callingPackageName, int32_t uid, const String16& packageName,
- int32_t opCode, const String16& message);
+ int32_t opCode, const String16& featureId, const String16& message);
private:
Mutex mLock;
@@ -155,7 +156,7 @@
sp<IAppOpsService> getService();
void markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
- const String16& message);
+ const String16& featureId, const String16& message);
bool shouldCollectNotes(int32_t opCode);
};
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 8b8a3c2..ad34bc5 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -49,7 +49,8 @@
const String16& packageName) = 0;
virtual void setCameraAudioRestriction(int32_t mode) = 0;
virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
- const String16& packageName, int32_t opCode, const String16& message) = 0;
+ const String16& packageName, int32_t opCode, const String16& featureId,
+ const String16& message) = 0;
virtual bool shouldCollectNotes(int32_t opCode) = 0;
enum {
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/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_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index c6868b0..dc3c8d2 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -201,7 +201,22 @@
/**
* See AStatus_isOk.
*/
- bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+ bool isOk() const { return get() != nullptr && AStatus_isOk(get()); }
+
+ /**
+ * See AStatus_getExceptionCode
+ */
+ binder_exception_t getExceptionCode() const { return AStatus_getExceptionCode(get()); }
+
+ /**
+ * See AStatus_getServiceSpecificError
+ */
+ int32_t getServiceSpecificError() const { return AStatus_getServiceSpecificError(get()); }
+
+ /**
+ * See AStatus_getStatus
+ */
+ binder_status_t getStatus() const { return AStatus_getStatus(get()); }
/**
* Convenience method for okay status.
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index b03fce1..e1a8cfd 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -20,7 +20,21 @@
__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_VNDK__) && !defined(__ANDROID_APEX__))
+
+enum {
+ FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
+};
/**
* This interface has the stability of the vendor image.
@@ -33,6 +47,10 @@
#else // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+enum {
+ FLAG_PRIVATE_LOCAL = 0,
+};
+
/**
* This interface has the stability of the system image.
*/
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/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 3a369cd..9a50175 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -64,7 +64,7 @@
: Fence::NO_FENCE);
mNextCallbackBufferItem = BufferItem();
}
- mDequeueWaitCV.notify_one();
+ mDequeueWaitCV.notify_all();
decStrong((void*)transactionCallbackThunk);
}
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index a5f115e..db1ac24 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -18,8 +18,14 @@
#include <gui/BLASTBufferQueue.h>
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
#include <gui/SurfaceComposerClient.h>
+#include <private/gui/ComposerService.h>
+#include <ui/DisplayInfo.h>
#include <ui/GraphicBuffer.h>
+#include <ui/GraphicTypes.h>
#include <gtest/gtest.h>
@@ -27,10 +33,8 @@
namespace android {
-const int DEFAULT_WIDTH = 100;
-const int DEFAULT_HEIGHT = 100;
-
using Transaction = SurfaceComposerClient::Transaction;
+using android::hardware::graphics::common::V1_2::BufferUsage;
class BLASTBufferQueueHelper {
public:
@@ -47,12 +51,24 @@
}
int getWidth() { return mBlastBufferQueueAdapter->mWidth; }
+
int getHeight() { return mBlastBufferQueueAdapter->mHeight; }
+
Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }
+
+ sp<IGraphicBufferProducer> getIGraphicBufferProducer() {
+ return mBlastBufferQueueAdapter->getIGraphicBufferProducer();
+ }
+
const sp<SurfaceControl> getSurfaceControl() {
return mBlastBufferQueueAdapter->mSurfaceControl;
}
+ void waitForCallback() {
+ std::unique_lock lock{mBlastBufferQueueAdapter->mMutex};
+ mBlastBufferQueueAdapter->mDequeueWaitCV.wait_for(lock, 1s);
+ }
+
private:
sp<BLASTBufferQueue> mBlastBufferQueueAdapter;
};
@@ -73,39 +89,149 @@
}
void SetUp() {
+ mComposer = ComposerService::getComposerService();
mClient = new SurfaceComposerClient();
- mSurfaceControl = mClient->createSurface(String8("TestSurface"), DEFAULT_WIDTH,
- DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888);
+ mDisplayToken = mClient->getInternalDisplayToken();
+ ASSERT_NE(nullptr, mDisplayToken.get());
+ Transaction t;
+ t.setDisplayLayerStack(mDisplayToken, 0);
+ t.apply();
+ t.clear();
+
+ DisplayInfo info;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplayToken, &info));
+ mDisplayWidth = info.w;
+ mDisplayHeight = info.h;
+
+ mSurfaceControl = mClient->createSurface(String8("TestSurface"), mDisplayWidth,
+ mDisplayHeight, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceBufferState,
+ /*parent*/ nullptr);
+ t.setLayerStack(mSurfaceControl, 0)
+ .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
+ .setFrame(mSurfaceControl, Rect(0, 0, mDisplayWidth, mDisplayHeight))
+ .show(mSurfaceControl)
+ .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB)
+ .apply();
+ }
+
+ void fillBuffer(uint32_t* bufData, uint32_t width, uint32_t height, uint32_t stride, uint8_t r,
+ uint8_t g, uint8_t b) {
+ for (uint32_t row = 0; row < height; row++) {
+ for (uint32_t col = 0; col < width; col++) {
+ uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
+ *pixel = r;
+ *(pixel + 1) = g;
+ *(pixel + 2) = b;
+ *(pixel + 3) = 255;
+ }
+ }
+ }
+
+ void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b) {
+ const auto width = mScreenCaptureBuf->getWidth();
+ const auto height = mScreenCaptureBuf->getHeight();
+ const auto stride = mScreenCaptureBuf->getStride();
+
+ uint32_t* bufData;
+ mScreenCaptureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN),
+ reinterpret_cast<void**>(&bufData));
+
+ for (uint32_t row = 0; row < height; row++) {
+ for (uint32_t col = 0; col < width; col++) {
+ uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
+ EXPECT_EQ(r, *(pixel));
+ EXPECT_EQ(g, *(pixel + 1));
+ EXPECT_EQ(b, *(pixel + 2));
+ }
+ }
+ mScreenCaptureBuf->unlock();
+ ASSERT_EQ(false, ::testing::Test::HasFailure());
}
sp<SurfaceComposerClient> mClient;
+ sp<ISurfaceComposer> mComposer;
+
+ sp<IBinder> mDisplayToken;
+
sp<SurfaceControl> mSurfaceControl;
+ sp<GraphicBuffer> mScreenCaptureBuf;
+
+ uint32_t mDisplayWidth;
+ uint32_t mDisplayHeight;
};
TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
// create BLASTBufferQueue adapter associated with this surface
- BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl());
- ASSERT_EQ(DEFAULT_WIDTH, adapter.getWidth());
- ASSERT_EQ(DEFAULT_HEIGHT, adapter.getHeight());
+ ASSERT_EQ(mDisplayWidth, adapter.getWidth());
+ ASSERT_EQ(mDisplayHeight, adapter.getHeight());
ASSERT_EQ(nullptr, adapter.getNextTransaction());
}
TEST_F(BLASTBufferQueueTest, Update) {
- BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
sp<SurfaceControl> updateSurface =
- mClient->createSurface(String8("UpdateTest"), DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2,
- PIXEL_FORMAT_RGB_888);
- adapter.update(updateSurface, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2);
+ mClient->createSurface(String8("UpdateTest"), mDisplayWidth / 2, mDisplayHeight / 2,
+ PIXEL_FORMAT_RGBA_8888);
+ adapter.update(updateSurface, mDisplayWidth / 2, mDisplayHeight / 2);
ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
- ASSERT_EQ(DEFAULT_WIDTH / 2, adapter.getWidth());
- ASSERT_EQ(DEFAULT_HEIGHT / 2, adapter.getHeight());
+ ASSERT_EQ(mDisplayWidth / 2, adapter.getWidth());
+ ASSERT_EQ(mDisplayHeight / 2, adapter.getHeight());
}
TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
- BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
Transaction next;
adapter.setNextTransaction(&next);
ASSERT_EQ(&next, adapter.getNextTransaction());
}
+
+TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) {
+ uint8_t r = 255;
+ uint8_t g = 0;
+ uint8_t b = 0;
+
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ auto igbProducer = adapter.getIGraphicBufferProducer();
+ ASSERT_NE(nullptr, igbProducer.get());
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ ASSERT_EQ(NO_ERROR,
+ igbProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
+ &qbOutput));
+ ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(3));
+
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
+ PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
+ nullptr, nullptr);
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+ ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+
+ uint32_t* bufData;
+ buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
+ reinterpret_cast<void**>(&bufData));
+ fillBuffer(bufData, buf->getWidth(), buf->getHeight(), buf->getStride(), r, g, b);
+ buf->unlock();
+
+ IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN,
+ Rect(mDisplayWidth, mDisplayHeight),
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+ Fence::NO_FENCE);
+ igbProducer->queueBuffer(slot, input, &qbOutput);
+
+ adapter.waitForCallback();
+
+ // capture screen and verify that it is red
+ bool capturedSecureLayers;
+ ASSERT_EQ(NO_ERROR,
+ mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers,
+ ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(),
+ mDisplayWidth, mDisplayHeight,
+ /*useIdentityTransform*/ false));
+ ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b));
+}
} // namespace android
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 09eeaea..03b9cd7 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -405,12 +405,11 @@
surface->expectTap(1, 1);
}
-/**
- * TODO(b/139494112) fix tests once we define expected behavior
- *
-// Ensure we send the input to the right surface when the surface visibility changes due to the
-// first buffer being submitted. ref: b/120839715
-TEST_F(InputSurfacesTest, input_respects_buffer_layer_buffer) {
+// TODO(b/139494112) update tests once we define expected behavior
+// Ensure we still send input to the surface regardless of surface visibility changes due to the
+// first buffer being submitted or alpha changes.
+// Original bug ref: b/120839715
+TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) {
std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
std::unique_ptr<InputSurface> bufferSurface =
InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
@@ -419,14 +418,14 @@
bufferSurface->showAt(10, 10);
injectTap(11, 11);
- bgSurface->expectTap(1, 1);
+ bufferSurface->expectTap(1, 1);
postBuffer(bufferSurface->mSurfaceControl);
injectTap(11, 11);
bufferSurface->expectTap(1, 1);
}
-TEST_F(InputSurfacesTest, input_respects_buffer_layer_alpha) {
+TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) {
std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
std::unique_ptr<InputSurface> bufferSurface =
InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
@@ -441,10 +440,10 @@
bufferSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
injectTap(11, 11);
- bgSurface->expectTap(1, 1);
+ bufferSurface->expectTap(1, 1);
}
-TEST_F(InputSurfacesTest, input_respects_color_layer_alpha) {
+TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) {
std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
@@ -457,9 +456,8 @@
fgSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
injectTap(11, 11);
- bgSurface->expectTap(1, 1);
+ fgSurface->expectTap(1, 1);
}
-*/
TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) {
std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
diff --git a/libs/math/include/math/quat.h b/libs/math/include/math/quat.h
index 1936a2b..07573c5 100644
--- a/libs/math/include/math/quat.h
+++ b/libs/math/include/math/quat.h
@@ -109,7 +109,7 @@
// initialize from 4 values to w + xi + yj + zk
template<typename A, typename B, typename C, typename D>
- constexpr TQuaternion(A w, B x, C y, D z) : x(x), y(y), z(z), w(w) { }
+ constexpr TQuaternion(A w, B x, C y, D z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)), w(static_cast<T>(w)) { }
// initialize from a vec3 + a value to : v.xi + v.yj + v.zk + w
template<typename A, typename B>
diff --git a/libs/math/include/math/vec2.h b/libs/math/include/math/vec2.h
index a347633..e0adb7f 100644
--- a/libs/math/include/math/vec2.h
+++ b/libs/math/include/math/vec2.h
@@ -89,7 +89,7 @@
constexpr TVec2(A v) : x(v), y(v) { }
template<typename A, typename B>
- constexpr TVec2(A x, B y) : x(x), y(y) { }
+ constexpr TVec2(A x, B y) : x(static_cast<T>(x)), y(static_cast<T>(y)) { }
template<typename A>
explicit
diff --git a/libs/math/include/math/vec3.h b/libs/math/include/math/vec3.h
index 009fd84..21fb684 100644
--- a/libs/math/include/math/vec3.h
+++ b/libs/math/include/math/vec3.h
@@ -86,13 +86,13 @@
// handles implicit conversion to a tvec4. must not be explicit.
template<typename A, typename = typename std::enable_if<std::is_arithmetic<A>::value >::type>
- constexpr TVec3(A v) : x(v), y(v), z(v) { }
+ constexpr TVec3(A v) : x(static_cast<T>(v)), y(static_cast<T>(v)), z(static_cast<T>(v)) { }
template<typename A, typename B, typename C>
- constexpr TVec3(A x, B y, C z) : x(x), y(y), z(z) { }
+ constexpr TVec3(A x, B y, C z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)) { }
template<typename A, typename B>
- constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(z) { }
+ constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(static_cast<T>(z)) { }
template<typename A>
explicit
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/libs/ui/ColorSpace.cpp b/libs/ui/ColorSpace.cpp
index 7a14af1..df390e2 100644
--- a/libs/ui/ColorSpace.cpp
+++ b/libs/ui/ColorSpace.cpp
@@ -364,7 +364,11 @@
for (uint32_t z = 0; z < size; z++) {
for (int32_t y = int32_t(size - 1); y >= 0; y--) {
for (uint32_t x = 0; x < size; x++) {
- *data++ = connector.transform({x * m, y * m, z * m});
+ *data++ = connector.transform({
+ static_cast<float>(x) * m,
+ static_cast<float>(y) * m,
+ static_cast<float>(z) * m,
+ });
}
}
}
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index eb787a2..cc9ccbc 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -89,7 +89,7 @@
if (rec.size) {
StringAppendF(&result,
"%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 " | %s\n",
- list.keyAt(i), rec.size / 1024.0, rec.width, rec.stride, rec.height,
+ list.keyAt(i), static_cast<double>(rec.size) / 1024.0, rec.width, rec.stride, rec.height,
rec.layerCount, rec.format, rec.usage, rec.requestorName.c_str());
} else {
StringAppendF(&result,
@@ -99,7 +99,7 @@
}
total += rec.size;
}
- StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", total / 1024.0);
+ StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", static_cast<double>(total) / 1024.0);
result.append(mAllocator->dumpDebugInfo());
}
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 55e3b99..1222cd6 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -339,10 +339,10 @@
size_t count = mStorage.size();
Rect* rects = mStorage.editArray();
while (count) {
- rects->left = static_cast<int32_t>(rects->left * sx + 0.5f);
- rects->right = static_cast<int32_t>(rects->right * sx + 0.5f);
- rects->top = static_cast<int32_t>(rects->top * sy + 0.5f);
- rects->bottom = static_cast<int32_t>(rects->bottom * sy + 0.5f);
+ rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
+ rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
+ rects->top = static_cast<int32_t>(static_cast<float>(rects->top) * sy + 0.5f);
+ rects->bottom = static_cast<int32_t>(static_cast<float>(rects->bottom) * sy + 0.5f);
rects++;
count--;
}
diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h
index c39d8af..d9b713d 100644
--- a/libs/ui/include/ui/Size.h
+++ b/libs/ui/include/ui/Size.h
@@ -132,7 +132,7 @@
// Otherwise we leverage implicit conversion to safely compare values of
// different types, to ensure we return a value clamped to the range of
// ToType.
- return v < toLowest ? toLowest : (v > toHighest ? toHighest : static_cast<ToType>(v));
+ return v < toLowest ? toLowest : (static_cast<ToType>(v) > toHighest ? toHighest : static_cast<ToType>(v));
}
};
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/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index 2f046c3..683c05d 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -127,10 +127,10 @@
input_bus_t bus, const char* uniqueId) {
auto identifier = new ::input_device_identifier {
.name = name,
- .productId = productId,
- .vendorId = vendorId,
- .bus = bus,
.uniqueId = uniqueId,
+ .bus = bus,
+ .vendorId = vendorId,
+ .productId = productId,
};
// TODO: store this identifier somewhere
return identifier;
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index b500ad3..603a9f7 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -61,7 +61,7 @@
mTextureName(args.textureName),
mCompositionLayer{mFlinger->getCompositionEngine().createLayer(
compositionengine::LayerCreationArgs{this})} {
- ALOGV("Creating Layer %s", args.name.string());
+ ALOGV("Creating Layer %s", getDebugName());
mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index d80a70e..a4f7797 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -62,7 +62,7 @@
std::vector<OccupancyTracker::Segment> history;
status_t result = mConsumer->getOccupancyHistory(forceFlush, &history);
if (result != NO_ERROR) {
- ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result);
+ ALOGW("[%s] Failed to obtain occupancy history (%d)", getDebugName(), result);
return {};
}
return history;
@@ -110,7 +110,7 @@
ALOGW_IF(!isPlausible,
"[%s] Timestamp %" PRId64 " seems implausible "
"relative to expectedPresent %" PRId64,
- mName.string(), addedTime, expectedPresentTime);
+ getDebugName(), addedTime, expectedPresentTime);
const bool isDue = addedTime < expectedPresentTime;
return isDue || !isPlausible;
@@ -225,7 +225,7 @@
bool queuedBuffer = false;
const int32_t layerID = getSequence();
LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
+ getProducerStickyTransform() != 0, mName, mOverrideScalingMode,
getTransformToDisplayInverse());
if (isRemovedFromCurrentState()) {
@@ -398,7 +398,7 @@
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", mName.string());
+ ALOGE("[%s] Timed out waiting on callback", getDebugName());
}
}
@@ -426,7 +426,7 @@
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", mName.string());
+ ALOGE("[%s] Timed out waiting on callback", getDebugName());
}
}
@@ -459,12 +459,14 @@
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, true);
- mProducer = new MonitoredProducer(producer, mFlinger, this);
- mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
+ mFlinger->getFactory().createBufferQueue(&producer, &consumer, true);
+ mProducer = mFlinger->getFactory().createMonitoredProducer(producer, mFlinger, this);
+ mConsumer =
+ mFlinger->getFactory().createBufferLayerConsumer(consumer, mFlinger->getRenderEngine(),
+ mTextureName, this);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mConsumer->setContentsChangedListener(this);
- mConsumer->setName(mName);
+ mConsumer->setName(String8(mName.data(), mName.size()));
// BufferQueueCore::mMaxDequeuedBufferCount is default to 1
if (!mFlinger->isLayerTripleBufferingDisabled()) {
@@ -527,9 +529,7 @@
}
sp<Layer> BufferQueueLayer::createClone() {
- const String8 name = mName + " (Mirror)";
- LayerCreationArgs args =
- LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata());
+ LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata());
args.textureName = mTextureName;
sp<BufferQueueLayer> layer = mFlinger->getFactory().createBufferQueueLayer(args);
layer->setInitialValuesForClone(this);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 75fc0e9..6fe89c4 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -136,7 +136,7 @@
return;
}
mPendingStates.push_back(mCurrentState);
- ATRACE_INT(mTransactionName.string(), mPendingStates.size());
+ ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
}
bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
@@ -479,7 +479,7 @@
(s.active.w != bufferWidth || s.active.h != bufferHeight)) {
ALOGE("[%s] rejecting buffer: "
"bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
- mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h);
+ getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h);
mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber);
return BAD_VALUE;
}
@@ -669,9 +669,7 @@
}
sp<Layer> BufferStateLayer::createClone() {
- const String8 name = mName + " (Mirror)";
- LayerCreationArgs args =
- LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata());
+ LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata());
args.textureName = mTextureName;
sp<BufferStateLayer> layer = mFlinger->getFactory().createBufferStateLayer(args);
layer->mHwcSlotGenerator = mHwcSlotGenerator;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 172d445..8bfa569 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -108,13 +108,11 @@
}
sp<Layer> ColorLayer::createClone() {
- String8 name = mName + " (Mirror)";
sp<ColorLayer> layer = mFlinger->getFactory().createColorLayer(
- LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()));
+ LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0,
+ LayerMetadata()));
layer->setInitialValuesForClone(this);
return layer;
}
-// ---------------------------------------------------------------------------
-
-}; // namespace android
+} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index e58e6f4..ab664be 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -31,10 +31,11 @@
}
sp<Layer> ContainerLayer::createClone() {
- String8 name = mName + " (Mirror)";
sp<ContainerLayer> layer = mFlinger->getFactory().createContainerLayer(
- LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()));
+ LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0,
+ LayerMetadata()));
layer->setInitialValuesForClone(this);
return layer;
}
+
} // namespace android
diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp
index 365a0bd..a532fc1 100644
--- a/services/surfaceflinger/EventLog/EventLog.cpp
+++ b/services/surfaceflinger/EventLog/EventLog.cpp
@@ -17,13 +17,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <log/log.h>
-#include <utils/String8.h>
#include "EventLog.h"
-// ---------------------------------------------------------------------------
namespace android {
-// ---------------------------------------------------------------------------
ANDROID_SINGLETON_STATIC_INSTANCE(EventLog)
@@ -31,11 +28,11 @@
EventLog::EventLog() {
}
-void EventLog::doLogFrameDurations(const String8& window,
- const int32_t* durations, size_t numDurations) {
+void EventLog::doLogFrameDurations(const std::string_view& name, const int32_t* durations,
+ size_t numDurations) {
EventLog::TagBuffer buffer(LOGTAG_SF_FRAME_DUR);
buffer.startList(1 + numDurations);
- buffer.writeString8(window);
+ buffer.writeString(name);
for (size_t i = 0; i < numDurations; i++) {
buffer.writeInt32(durations[i]);
}
@@ -43,10 +40,9 @@
buffer.log();
}
-void EventLog::logFrameDurations(const String8& window,
- const int32_t* durations, size_t numDurations) {
- EventLog::getInstance().doLogFrameDurations(window, durations,
- numDurations);
+void EventLog::logFrameDurations(const std::string_view& name, const int32_t* durations,
+ size_t numDurations) {
+ EventLog::getInstance().doLogFrameDurations(name, durations, numDurations);
}
// ---------------------------------------------------------------------------
@@ -113,9 +109,9 @@
mPos += needed;
}
-void EventLog::TagBuffer::writeString8(const String8& value) {
+void EventLog::TagBuffer::writeString(const std::string_view& value) {
if (mOverflow) return;
- const int32_t stringLen = value.length();
+ const size_t stringLen = value.length();
const size_t needed = 1 + sizeof(int32_t) + stringLen;
if (mPos + needed > STORAGE_MAX_SIZE) {
mOverflow = true;
@@ -123,11 +119,8 @@
}
mStorage[mPos + 0] = EVENT_TYPE_STRING;
memcpy(&mStorage[mPos + 1], &stringLen, sizeof(int32_t));
- memcpy(&mStorage[mPos + 5], value.string(), stringLen);
+ memcpy(&mStorage[mPos + 5], value.data(), stringLen);
mPos += needed;
}
-// ---------------------------------------------------------------------------
-}// namespace android
-
-// ---------------------------------------------------------------------------
+} // namespace android
diff --git a/services/surfaceflinger/EventLog/EventLog.h b/services/surfaceflinger/EventLog/EventLog.h
index efc5d70..ee3587e 100644
--- a/services/surfaceflinger/EventLog/EventLog.h
+++ b/services/surfaceflinger/EventLog/EventLog.h
@@ -14,24 +14,21 @@
* limitations under the License.
*/
-#include <stdint.h>
+#pragma once
+
#include <utils/Errors.h>
#include <utils/Singleton.h>
-#ifndef ANDROID_SF_EVENTLOG_H
-#define ANDROID_SF_EVENTLOG_H
+#include <cstdint>
+#include <string_view>
-// ---------------------------------------------------------------------------
namespace android {
-// ---------------------------------------------------------------------------
-
-class String8;
class EventLog : public Singleton<EventLog> {
public:
- static void logFrameDurations(const String8& window,
- const int32_t* durations, size_t numDurations);
+ static void logFrameDurations(const std::string_view& name, const int32_t* durations,
+ size_t numDurations);
protected:
EventLog();
@@ -54,18 +51,13 @@
public:
explicit TagBuffer(int32_t tag);
- // starts list of items
void startList(int8_t count);
- // terminates the list
void endList();
- // write a 32-bit integer
- void writeInt32(int32_t value);
- // write a 64-bit integer
- void writeInt64(int64_t value);
- // write a C string
- void writeString8(const String8& value);
- // outputs the the buffer to the log
+ void writeInt32(int32_t);
+ void writeInt64(int64_t);
+ void writeString(const std::string_view&);
+
void log();
};
@@ -74,12 +66,8 @@
EventLog& operator =(const EventLog&);
enum { LOGTAG_SF_FRAME_DUR = 60100 };
- void doLogFrameDurations(const String8& window, const int32_t* durations,
- size_t numDurations);
+ void doLogFrameDurations(const std::string_view& name, const int32_t* durations,
+ size_t numDurations);
};
-// ---------------------------------------------------------------------------
-}// namespace android
-// ---------------------------------------------------------------------------
-
-#endif /* ANDROID_SF_EVENTLOG_H */
+} // namespace android
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
index f4cc49b..a6e511e 100644
--- a/services/surfaceflinger/FrameTracker.cpp
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -21,7 +21,6 @@
#include <android-base/stringprintf.h>
#include <android/log.h>
-#include <utils/String8.h>
#include <ui/FrameStats.h>
@@ -139,7 +138,7 @@
}
}
-void FrameTracker::logAndResetStats(const String8& name) {
+void FrameTracker::logAndResetStats(const std::string_view& name) {
Mutex::Autolock lock(mMutex);
logStatsLocked(name);
resetFrameCountersLocked();
@@ -217,7 +216,7 @@
}
}
-void FrameTracker::logStatsLocked(const String8& name) const {
+void FrameTracker::logStatsLocked(const std::string_view& name) const {
for (int i = 0; i < NUM_FRAME_BUCKETS; i++) {
if (mNumFrames[i] > 0) {
EventLog::logFrameDurations(name, mNumFrames, NUM_FRAME_BUCKETS);
diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h
index 555dcc1..35382be 100644
--- a/services/surfaceflinger/FrameTracker.h
+++ b/services/surfaceflinger/FrameTracker.h
@@ -14,21 +14,18 @@
* limitations under the License.
*/
-#ifndef ANDROID_FRAMETRACKER_H
-#define ANDROID_FRAMETRACKER_H
+#pragma once
#include <ui/FenceTime.h>
-
-#include <stddef.h>
-
#include <utils/Mutex.h>
-#include <utils/Timers.h>
#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+#include <cstddef>
+#include <string_view>
namespace android {
-class String8;
-
// FrameTracker tracks information about the most recently rendered frames. It
// uses a circular buffer of frame records, and is *NOT* thread-safe -
// mutexing must be done at a higher level if multi-threaded access is
@@ -87,7 +84,7 @@
// logAndResetStats dumps the current statistics to the binary event log
// and then resets the accumulated statistics to their initial values.
- void logAndResetStats(const String8& name);
+ void logAndResetStats(const std::string_view& name);
// dumpStats dump appends the current frame display time history to the result string.
void dumpStats(std::string& result) const;
@@ -123,7 +120,7 @@
void resetFrameCountersLocked();
// logStatsLocked dumps the current statistics to the binary event log.
- void logStatsLocked(const String8& name) const;
+ void logStatsLocked(const std::string_view& name) const;
// isFrameValidLocked returns true if the data for the given frame index is
// valid and has all arrived (i.e. there are no oustanding fences).
@@ -160,6 +157,4 @@
mutable Mutex mMutex;
};
-}
-
-#endif // ANDROID_FRAMETRACKER_H
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6a45625..37caab2 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -83,8 +83,6 @@
if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
- mTransactionName = String8("TX - ") + mName;
-
mCurrentState.active_legacy.w = args.w;
mCurrentState.active_legacy.h = args.h;
mCurrentState.flags = layerFlags;
@@ -137,11 +135,11 @@
}
LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+ std::string name, uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata)
: flinger(flinger),
client(client),
- name(name),
+ name(std::move(name)),
w(w),
h(h),
flags(flags),
@@ -235,10 +233,6 @@
// set-up
// ---------------------------------------------------------------------------
-const String8& Layer::getName() const {
- return mName;
-}
-
bool Layer::getPremultipledAlpha() const {
return mPremultipliedAlpha;
}
@@ -523,7 +517,7 @@
}
const char* Layer::getDebugName() const {
- return mName.string();
+ return mName.c_str();
}
// ---------------------------------------------------------------------------
@@ -614,7 +608,7 @@
if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) {
sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote();
if (barrierLayer == nullptr) {
- ALOGE("[%s] Unable to promote barrier Layer.", mName.string());
+ ALOGE("[%s] Unable to promote barrier Layer.", getDebugName());
// If we can't promote the layer we are intended to wait on,
// then it is expired or otherwise invalid. Allow this transaction
// to be applied as per normal (no synchronization).
@@ -638,7 +632,7 @@
mFlinger->setTransactionFlags(eTraversalNeeded);
}
mPendingStates.push_back(mCurrentState);
- ATRACE_INT(mTransactionName.string(), mPendingStates.size());
+ ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
}
void Layer::popPendingState(State* stateToCommit) {
@@ -646,7 +640,7 @@
*stateToCommit = mPendingStates[0];
mPendingStates.removeAt(0);
- ATRACE_INT(mTransactionName.string(), mPendingStates.size());
+ ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
}
bool Layer::applyPendingStates(State* stateToCommit) {
@@ -657,7 +651,7 @@
// If we don't have a sync point for this, apply it anyway. It
// will be visually wrong, but it should keep us from getting
// into too much trouble.
- ALOGE("[%s] No local sync point found", mName.string());
+ ALOGE("[%s] No local sync point found", getDebugName());
popPendingState(stateToCommit);
stateUpdateAvailable = true;
continue;
@@ -665,7 +659,7 @@
if (mRemoteSyncPoints.front()->getFrameNumber() !=
mPendingStates[0].frameNumber_legacy) {
- ALOGE("[%s] Unexpected sync point frame number found", mName.string());
+ ALOGE("[%s] Unexpected sync point frame number found", getDebugName());
// Signal our end of the sync point and then dispose of it
mRemoteSyncPoints.front()->setTransactionApplied();
@@ -717,7 +711,7 @@
" requested={ wh={%4u,%4u} }}\n"
" drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
" requested={ wh={%4u,%4u} }}\n",
- this, getName().string(), getBufferTransform(), getEffectiveScalingMode(),
+ this, getName().c_str(), getBufferTransform(), getEffectiveScalingMode(),
stateToCommit->active_legacy.w, stateToCommit->active_legacy.h,
stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top,
stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom,
@@ -908,7 +902,6 @@
}
setZOrderRelativeOf(nullptr);
}
- mCurrentState.isRelativeOf = false;
setTransactionFlags(eTransactionNeeded);
return true;
}
@@ -931,6 +924,8 @@
mCurrentState.zOrderRelativeOf = relativeOf;
mCurrentState.sequence++;
mCurrentState.modified = true;
+ mCurrentState.isRelativeOf = relativeOf != nullptr;
+
setTransactionFlags(eTransactionNeeded);
}
@@ -952,7 +947,6 @@
mCurrentState.sequence++;
mCurrentState.modified = true;
mCurrentState.z = relativeZ;
- mCurrentState.isRelativeOf = true;
auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
if (oldZOrderRelativeOf != nullptr) {
@@ -999,9 +993,10 @@
if (!mCurrentState.bgColorLayer && alpha != 0) {
// create background color layer if one does not yet exist
uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor;
- const String8& name = mName + "BackgroundColorLayer";
+ std::string name = mName + "BackgroundColorLayer";
mCurrentState.bgColorLayer = mFlinger->getFactory().createColorLayer(
- LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags, LayerMetadata()));
+ LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags,
+ LayerMetadata()));
// add to child list
addChild(mCurrentState.bgColorLayer);
@@ -1196,11 +1191,13 @@
// TODO(marissaw): add new layer state info to layer debugging
LayerDebugInfo Layer::getLayerDebugInfo() const {
+ using namespace std::string_literals;
+
LayerDebugInfo info;
const State& ds = getDrawingState();
info.mName = getName();
sp<Layer> parent = getParent();
- info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string());
+ info.mParentName = parent ? parent->getName() : "none"s;
info.mType = getType();
info.mTransparentRegion = ds.activeTransparentRegion_legacy;
@@ -1267,12 +1264,12 @@
std::string name;
if (mName.length() > 77) {
std::string shortened;
- shortened.append(mName.string(), 36);
+ shortened.append(mName, 0, 36);
shortened.append("[...]");
- shortened.append(mName.string() + (mName.length() - 36), 36);
- name = shortened;
+ shortened.append(mName, mName.length() - 36);
+ name = std::move(shortened);
} else {
- name = std::string(mName.string(), mName.size());
+ name = mName;
}
StringAppendF(&result, " %s\n", name.c_str());
@@ -1319,14 +1316,14 @@
}
void Layer::dumpFrameEvents(std::string& result) {
- StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getType(), this);
+ StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().c_str(), getType(), this);
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.checkFencesForCompletion();
mFrameEventHistory.dump(result);
}
void Layer::dumpCallingUidPid(std::string& result) const {
- StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().string(), getType(),
+ StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().c_str(), getType(),
mCallingPid, mCallingUid);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3023cf5..ad81920 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -34,7 +34,6 @@
#include <ui/Region.h>
#include <ui/Transform.h>
#include <utils/RefBase.h>
-#include <utils/String8.h>
#include <utils/Timers.h>
#include <cstdint>
@@ -79,12 +78,12 @@
// ---------------------------------------------------------------------------
struct LayerCreationArgs {
- LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+ LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client, std::string name,
uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata);
SurfaceFlinger* flinger;
const sp<Client>& client;
- const String8& name;
+ std::string name;
uint32_t w;
uint32_t h;
uint32_t flags;
@@ -804,7 +803,7 @@
// Creates a new handle each time, so we only expect
// this to be called once.
sp<IBinder> getHandle();
- const String8& getName() const;
+ const std::string& getName() const { return mName; }
virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {}
virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; }
bool getPremultipledAlpha() const;
@@ -820,8 +819,8 @@
bool usingRelativeZ(LayerVector::StateSet stateSet) const;
bool mPremultipliedAlpha{true};
- String8 mName;
- String8 mTransactionName; // A cached version of "TX - " + mName for systraces
+ const std::string mName;
+ const std::string mTransactionName{"TX - " + mName};
bool mPrimaryDisplayOnly = false;
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 8a22183..1a60f1e 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -24,7 +24,7 @@
namespace android {
LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current,
- bool& recomputeVisibleRegions, bool stickySet, const char* name,
+ bool& recomputeVisibleRegions, bool stickySet, const std::string& name,
int32_t overrideScalingMode, bool transformToDisplayInverse)
: mFront(front),
mCurrent(current),
@@ -90,7 +90,7 @@
"(%4d,%4d) "
"}\n"
" requested_legacy={ wh={%4u,%4u} }}\n",
- mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
+ mName.c_str(), bufWidth, bufHeight, item.mTransform, item.mScalingMode,
mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop_legacy.left,
mFront.crop_legacy.top, mFront.crop_legacy.right, mFront.crop_legacy.bottom,
mFront.crop_legacy.getWidth(), mFront.crop_legacy.getHeight(),
@@ -102,7 +102,8 @@
// reject this buffer
ALOGE("[%s] rejecting buffer: "
"bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}",
- mName, bufWidth, bufHeight, mFront.active_legacy.w, mFront.active_legacy.h);
+ mName.c_str(), bufWidth, bufHeight, mFront.active_legacy.w,
+ mFront.active_legacy.h);
return true;
}
}
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
index 1bd0c26..fb5c750 100644
--- a/services/surfaceflinger/LayerRejecter.h
+++ b/services/surfaceflinger/LayerRejecter.h
@@ -14,30 +14,29 @@
* limitations under the License.
*/
-#ifndef ANDROID_LAYER_REJECTER_H
-#define ANDROID_LAYER_REJECTER_H
+#pragma once
#include "Layer.h"
#include "BufferLayerConsumer.h"
namespace android {
- class LayerRejecter : public BufferLayerConsumer::BufferRejecter {
- public:
- LayerRejecter(Layer::State &front, Layer::State ¤t, bool &recomputeVisibleRegions,
- bool stickySet, const char *name, int32_t overrideScalingMode,
- bool transformToDisplayInverse);
- virtual bool reject(const sp<GraphicBuffer> &buf, const BufferItem &item);
+class LayerRejecter : public BufferLayerConsumer::BufferRejecter {
+public:
+ LayerRejecter(Layer::State& front, Layer::State& current, bool& recomputeVisibleRegions,
+ bool stickySet, const std::string& name, int32_t overrideScalingMode,
+ bool transformToDisplayInverse);
- private:
- Layer::State &mFront;
- Layer::State &mCurrent;
- bool &mRecomputeVisibleRegions;
- bool mStickyTransformSet;
- const char *mName;
- int32_t mOverrideScalingMode;
- bool mTransformToDisplayInverse;
- };
-} // namespace android
+ virtual bool reject(const sp<GraphicBuffer>&, const BufferItem&);
-#endif // ANDROID_LAYER_REJECTER_H
+private:
+ Layer::State& mFront;
+ Layer::State& mCurrent;
+ bool& mRecomputeVisibleRegions;
+ const bool mStickyTransformSet;
+ const std::string& mName;
+ const int32_t mOverrideScalingMode;
+ const bool mTransformToDisplayInverse;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 1c1367c..30027de 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -436,7 +436,7 @@
}
if (!intersectsAnyArea) return;
- ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getName().string(), bounds.left,
+ ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getDebugName(), bounds.left,
bounds.top, bounds.right, bounds.bottom);
visitor(layer);
};
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index f80c233..5473db6 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -40,7 +40,7 @@
LayerHistory::LayerHistory() {
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.layer_history_trace", value, "0");
- mTraceEnabled = bool(atoi(value));
+ mTraceEnabled = static_cast<bool>(atoi(value));
}
LayerHistory::~LayerHistory() = default;
@@ -128,19 +128,23 @@
// Iterate through all layers that have been recently updated, and find the max refresh rate.
for (const auto& [layerId, layerInfo] : mActiveLayerInfos) {
- const float layerRefreshRate = layerInfo->getDesiredRefreshRate();
- if (mTraceEnabled) {
- // Store the refresh rate in traces for easy debugging.
- std::string layerName = "LFPS " + layerInfo->getName();
- ATRACE_INT(layerName.c_str(), std::round(layerRefreshRate));
- ALOGD("%s: %f", layerName.c_str(), std::round(layerRefreshRate));
- }
- if (layerInfo->isRecentlyActive() && layerRefreshRate > newRefreshRate) {
- newRefreshRate = layerRefreshRate;
+ const bool recent = layerInfo->isRecentlyActive();
+ if (recent || CC_UNLIKELY(mTraceEnabled)) {
+ const float refreshRate = layerInfo->getDesiredRefreshRate();
+ if (recent && refreshRate > newRefreshRate) {
+ newRefreshRate = refreshRate;
+ }
+
+ if (CC_UNLIKELY(mTraceEnabled)) {
+ std::string name = "LFPS " + layerInfo->getName();
+ const float rate = std::round(refreshRate);
+ ATRACE_INT(name.c_str(), rate);
+ ALOGD("%s: %f", name.c_str(), rate);
+ }
}
isHDR |= layerInfo->getHDRContent();
}
- if (mTraceEnabled) {
+ if (CC_UNLIKELY(mTraceEnabled)) {
ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate);
}
@@ -158,7 +162,7 @@
(!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) {
// erase() function returns the iterator of the next
// to last deleted element.
- if (mTraceEnabled) {
+ if (CC_UNLIKELY(mTraceEnabled)) {
ALOGD("Layer %s obsolete", it->second->getName().c_str());
// Make sure to update systrace to indicate that the layer was erased.
std::string layerName = "LFPS " + it->second->getName();
@@ -189,4 +193,4 @@
}
} // namespace scheduler
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 54e2065..0e33f10 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -122,6 +122,8 @@
namespace android {
+using namespace std::string_literals;
+
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
using namespace android::sysprop;
@@ -1911,8 +1913,7 @@
layer->onPostComposition(displayDevice->getId(), glCompositionDoneFenceTime,
presentFenceTime, compositorTiming);
if (frameLatched) {
- recordBufferingStats(layer->getName().string(),
- layer->getOccupancyHistory(false));
+ recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false));
}
});
@@ -2574,7 +2575,7 @@
if (!mLayersPendingRemoval.isEmpty()) {
// Notify removed layers now that they can't be drawn from
for (const auto& l : mLayersPendingRemoval) {
- recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true));
+ recordBufferingStats(l->getName(), l->getOccupancyHistory(true));
// Ensure any buffers set to display on any children are released.
if (l->isRemovedFromCurrentState()) {
@@ -3244,11 +3245,12 @@
// everything else inherits layer stack from its parent.
if (layer->hasParent()) {
ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
- layer->getName().string());
+ layer->getDebugName());
} else if (idx < 0) {
ALOGE("Attempt to set layer stack on layer without parent (%s) that "
- "that also does not appear in the top level layer list. Something"
- " has gone wrong.", layer->getName().string());
+ "that also does not appear in the top level layer list. Something"
+ " has gone wrong.",
+ layer->getDebugName());
} else if (layer->setLayerStack(s.layerStack)) {
mCurrentState.layersSortedByZ.removeAt(idx);
mCurrentState.layersSortedByZ.add(layer);
@@ -3406,7 +3408,7 @@
sp<Layer> mirrorLayer;
sp<Layer> mirrorFrom;
- String8 uniqueName = getUniqueLayerName(String8("MirrorRoot"));
+ std::string uniqueName = getUniqueLayerName("MirrorRoot");
{
Mutex::Autolock _l(mStateLock);
@@ -3415,8 +3417,8 @@
return NAME_NOT_FOUND;
}
- status_t result = createContainerLayer(client, uniqueName, -1, -1, 0, LayerMetadata(),
- outHandle, &mirrorLayer);
+ status_t result = createContainerLayer(client, std::move(uniqueName), -1, -1, 0,
+ LayerMetadata(), outHandle, &mirrorLayer);
if (result != NO_ERROR) {
return result;
}
@@ -3447,7 +3449,7 @@
sp<Layer> layer;
- String8 uniqueName = getUniqueLayerName(name);
+ std::string uniqueName = getUniqueLayerName(name.string());
bool primaryDisplayOnly = false;
@@ -3463,13 +3465,13 @@
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata),
- format, handle, gbp, &layer);
+ result = createBufferQueueLayer(client, std::move(uniqueName), w, h, flags,
+ std::move(metadata), format, handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceBufferState:
- result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata),
- handle, &layer);
+ result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags,
+ std::move(metadata), handle, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceColor:
// check if buffer size is set for color layer.
@@ -3479,8 +3481,8 @@
return BAD_VALUE;
}
- result = createColorLayer(client, uniqueName, w, h, flags, std::move(metadata), handle,
- &layer);
+ result = createColorLayer(client, std::move(uniqueName), w, h, flags,
+ std::move(metadata), handle, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceContainer:
// check if buffer size is set for container layer.
@@ -3489,8 +3491,8 @@
int(w), int(h));
return BAD_VALUE;
}
- result = createContainerLayer(client, uniqueName, w, h, flags, std::move(metadata),
- handle, &layer);
+ result = createContainerLayer(client, std::move(uniqueName), w, h, flags,
+ std::move(metadata), handle, &layer);
break;
default:
result = BAD_VALUE;
@@ -3517,35 +3519,32 @@
return result;
}
-String8 SurfaceFlinger::getUniqueLayerName(const String8& name)
-{
- bool matchFound = true;
- uint32_t dupeCounter = 0;
+std::string SurfaceFlinger::getUniqueLayerName(const char* name) {
+ unsigned dupeCounter = 0;
// Tack on our counter whether there is a hit or not, so everyone gets a tag
- String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str());
+ std::string uniqueName = base::StringPrintf("%s#%u", name, dupeCounter);
// Grab the state lock since we're accessing mCurrentState
Mutex::Autolock lock(mStateLock);
// Loop over layers until we're sure there is no matching name
+ bool matchFound = true;
while (matchFound) {
matchFound = false;
mCurrentState.traverseInZOrder([&](Layer* layer) {
if (layer->getName() == uniqueName) {
matchFound = true;
- uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str());
+ uniqueName = base::StringPrintf("%s#%u", name, ++dupeCounter);
}
});
}
- ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(),
- uniqueName.c_str());
-
+ ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name, uniqueName.c_str());
return uniqueName;
}
-status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, const String8& name,
+status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, std::string name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, PixelFormat& format,
sp<IBinder>* handle,
@@ -3563,8 +3562,7 @@
}
sp<BufferQueueLayer> layer;
- LayerCreationArgs args =
- LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata));
+ LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
args.textureName = getNewTexture();
{
// Grab the SF state lock during this since it's the only safe way to access
@@ -3585,12 +3583,11 @@
return err;
}
-status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, const String8& name,
+status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, std::string name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, sp<IBinder>* handle,
sp<Layer>* outLayer) {
- LayerCreationArgs args =
- LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata));
+ LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
args.displayDevice = getDefaultDisplayDevice();
args.textureName = getNewTexture();
sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(args);
@@ -3600,26 +3597,25 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::createColorLayer(const sp<Client>& client, const String8& name, uint32_t w,
+status_t SurfaceFlinger::createColorLayer(const sp<Client>& client, std::string name, uint32_t w,
uint32_t h, uint32_t flags, LayerMetadata metadata,
sp<IBinder>* handle, sp<Layer>* outLayer) {
*outLayer = getFactory().createColorLayer(
- LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
+ {this, client, std::move(name), w, h, flags, std::move(metadata)});
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
-status_t SurfaceFlinger::createContainerLayer(const sp<Client>& client, const String8& name,
+status_t SurfaceFlinger::createContainerLayer(const sp<Client>& client, std::string name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, sp<IBinder>* handle,
sp<Layer>* outLayer) {
*outLayer = getFactory().createContainerLayer(
- LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
+ {this, client, std::move(name), w, h, flags, std::move(metadata)});
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
-
void SurfaceFlinger::markLayerPendingRemovalLocked(const sp<Layer>& layer) {
mLayersPendingRemoval.add(layer);
mLayersRemoved = true;
@@ -3828,8 +3824,6 @@
strerror(-err), err);
}
- using namespace std::string_literals;
-
static const std::unordered_map<std::string, Dumper> dumpers = {
{"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
{"--dispsync"s,
@@ -3885,7 +3879,7 @@
void SurfaceFlinger::listLayersLocked(std::string& result) const {
mCurrentState.traverseInZOrder(
- [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getName().string()); });
+ [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getDebugName()); });
}
void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const {
@@ -3894,7 +3888,7 @@
if (args.size() > 1) {
const auto name = String8(args[1]);
mCurrentState.traverseInZOrder([&](Layer* layer) {
- if (name == layer->getName()) {
+ if (layer->getName() == name.string()) {
layer->dumpFrameStats(result);
}
});
@@ -3904,8 +3898,11 @@
}
void SurfaceFlinger::clearStatsLocked(const DumpArgs& args, std::string&) {
+ const bool clearAll = args.size() < 2;
+ const auto name = clearAll ? String8() : String8(args[1]);
+
mCurrentState.traverseInZOrder([&](Layer* layer) {
- if (args.size() < 2 || String8(args[1]) == layer->getName()) {
+ if (clearAll || layer->getName() == name.string()) {
layer->clearFrameStats();
}
});
@@ -3924,7 +3921,7 @@
layer->logFrameStats();
});
- mAnimFrameTracker.logAndResetStats(String8("<win-anim>"));
+ mAnimFrameTracker.logAndResetStats("<win-anim>");
}
void SurfaceFlinger::appendSfConfigString(std::string& result) const {
@@ -3982,8 +3979,8 @@
bucketTimeSec, percent);
}
-void SurfaceFlinger::recordBufferingStats(const char* layerName,
- std::vector<OccupancyTracker::Segment>&& history) {
+void SurfaceFlinger::recordBufferingStats(const std::string& layerName,
+ std::vector<OccupancyTracker::Segment>&& history) {
Mutex::Autolock lock(getBE().mBufferingStatsMutex);
auto& stats = getBE().mBufferingStats[layerName];
for (const auto& segment : history) {
@@ -5031,13 +5028,14 @@
drawLayers();
} else {
Rect bounds = getBounds();
+ uint32_t w = static_cast<uint32_t>(bounds.getWidth());
+ uint32_t h = static_cast<uint32_t>(bounds.getHeight());
// In the "childrenOnly" case we reparent the children to a screenshot
// layer which has no properties set and which does not draw.
sp<ContainerLayer> screenshotParentLayer =
- mFlinger->getFactory().createContainerLayer(
- LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"),
- bounds.getWidth(), bounds.getHeight(), 0,
- LayerMetadata()));
+ mFlinger->getFactory().createContainerLayer({mFlinger, nullptr,
+ "Screenshot Parent"s, w, h, 0,
+ LayerMetadata()});
ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop);
drawLayers();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9f3a914..b719245 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -607,27 +607,27 @@
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp,
const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer = nullptr);
- status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w,
+ status_t createBufferQueueLayer(const sp<Client>& client, std::string name, uint32_t w,
uint32_t h, uint32_t flags, LayerMetadata metadata,
PixelFormat& format, sp<IBinder>* outHandle,
sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
- status_t createBufferStateLayer(const sp<Client>& client, const String8& name, uint32_t w,
+ status_t createBufferStateLayer(const sp<Client>& client, std::string name, uint32_t w,
uint32_t h, uint32_t flags, LayerMetadata metadata,
sp<IBinder>* outHandle, sp<Layer>* outLayer);
- status_t createColorLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h,
+ status_t createColorLayer(const sp<Client>& client, std::string name, uint32_t w, uint32_t h,
uint32_t flags, LayerMetadata metadata, sp<IBinder>* outHandle,
sp<Layer>* outLayer);
- status_t createContainerLayer(const sp<Client>& client, const String8& name, uint32_t w,
+ status_t createContainerLayer(const sp<Client>& client, std::string name, uint32_t w,
uint32_t h, uint32_t flags, LayerMetadata metadata,
sp<IBinder>* outHandle, sp<Layer>* outLayer);
status_t mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
sp<IBinder>* outHandle);
- String8 getUniqueLayerName(const String8& name);
+ std::string getUniqueLayerName(const char* name);
// called when all clients have released all their references to
// this layer meaning it is entirely safe to destroy all
@@ -866,8 +866,8 @@
// Not const because each Layer needs to query Fences and cache timestamps.
void dumpFrameEventsLocked(std::string& result);
- void recordBufferingStats(const char* layerName,
- std::vector<OccupancyTracker::Segment>&& history);
+ void recordBufferingStats(const std::string& layerName,
+ std::vector<OccupancyTracker::Segment>&& history);
void dumpBufferingStats(std::string& result) const;
void dumpDisplayIdentificationData(std::string& result) const;
void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
index f0457e3..4f439da 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
@@ -17,12 +17,14 @@
#include <compositionengine/impl/CompositionEngine.h>
#include <ui/GraphicBuffer.h>
+#include "BufferLayerConsumer.h"
#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "ColorLayer.h"
#include "ContainerLayer.h"
#include "DisplayDevice.h"
#include "Layer.h"
+#include "MonitoredProducer.h"
#include "NativeWindowSurface.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlingerDefaultFactory.h"
@@ -92,6 +94,18 @@
BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
}
+sp<IGraphicBufferProducer> DefaultFactory::createMonitoredProducer(
+ const sp<IGraphicBufferProducer>& producer, const sp<SurfaceFlinger>& flinger,
+ const wp<Layer>& layer) {
+ return new MonitoredProducer(producer, flinger, layer);
+}
+
+sp<BufferLayerConsumer> DefaultFactory::createBufferLayerConsumer(
+ const sp<IGraphicBufferConsumer>& consumer, renderengine::RenderEngine& renderEngine,
+ uint32_t textureName, Layer* layer) {
+ return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
+}
+
std::unique_ptr<surfaceflinger::NativeWindowSurface> DefaultFactory::createNativeWindowSurface(
const sp<IGraphicBufferProducer>& producer) {
return surfaceflinger::impl::createNativeWindowSurface(producer);
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
index 89e0679..42bb177 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
@@ -42,6 +42,12 @@
void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) override;
+ sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>&,
+ const sp<SurfaceFlinger>&,
+ const wp<Layer>&) override;
+ sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>&,
+ renderengine::RenderEngine&, uint32_t tex,
+ Layer*) override;
std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>&) override;
std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override;
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index 3fd4de8..20784d2 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -30,6 +30,7 @@
class BufferQueueLayer;
class BufferStateLayer;
+class BufferLayerConsumer;
class ColorLayer;
class ContainerLayer;
class DisplayDevice;
@@ -39,6 +40,7 @@
class HWComposer;
class IGraphicBufferConsumer;
class IGraphicBufferProducer;
+class Layer;
class MessageQueue;
class Scheduler;
class StartPropertySetThread;
@@ -85,6 +87,13 @@
virtual void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) = 0;
+ virtual sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>&,
+ const sp<SurfaceFlinger>&,
+ const wp<Layer>&) = 0;
+ virtual sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>&,
+ renderengine::RenderEngine&,
+ uint32_t tex, Layer*) = 0;
+
virtual std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>&) = 0;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index a02d14c..7e6c472 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -165,10 +165,6 @@
return layer;
}
-const std::string SurfaceInterceptor::getLayerName(const sp<const Layer>& layer) const {
- return layer->getName().string();
-}
-
int32_t SurfaceInterceptor::getLayerId(const sp<const Layer>& layer) const {
return layer->sequence;
}
@@ -490,7 +486,7 @@
{
SurfaceCreation* creation(increment->mutable_surface_creation());
creation->set_id(getLayerId(layer));
- creation->set_name(getLayerName(layer));
+ creation->set_name(layer->getName());
creation->set_w(layer->mCurrentState.active_legacy.w);
creation->set_h(layer->mCurrentState.active_legacy.h);
}
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 6858c4d..72b734b 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -123,7 +123,6 @@
status_t writeProtoFileLocked();
const sp<const Layer> getLayer(const wp<const IBinder>& weakHandle) const;
- const std::string getLayerName(const sp<const Layer>& layer) const;
int32_t getLayerId(const sp<const Layer>& layer) const;
int32_t getLayerIdFromWeakRef(const wp<const Layer>& layer) const;
int32_t getLayerIdFromHandle(const sp<const IBinder>& weakHandle) const;
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/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 8aff096..60da70f 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -839,7 +839,7 @@
static FlingerLayerType createLayer(CompositionTest* test) {
FlingerLayerType layer = Base::template createLayerWithFactory<ColorLayer>(test, [test]() {
return new ColorLayer(LayerCreationArgs(test->mFlinger.mFlinger.get(), sp<Client>(),
- String8("test-layer"), LayerProperties::WIDTH,
+ "test-layer", LayerProperties::WIDTH,
LayerProperties::HEIGHT,
LayerProperties::LAYER_FLAGS, LayerMetadata()));
});
@@ -879,11 +879,9 @@
FlingerLayerType layer =
Base::template createLayerWithFactory<BufferQueueLayer>(test, [test]() {
sp<Client> client;
- String8 name("test-layer");
- LayerCreationArgs args =
- LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name,
- LayerProperties::WIDTH, LayerProperties::HEIGHT,
- LayerProperties::LAYER_FLAGS, LayerMetadata());
+ LayerCreationArgs args(test->mFlinger.mFlinger.get(), client, "test-layer",
+ LayerProperties::WIDTH, LayerProperties::HEIGHT,
+ LayerProperties::LAYER_FLAGS, LayerMetadata());
args.textureName = test->mFlinger.mutableTexturePool().back();
return new BufferQueueLayer(args);
});
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index b85c1b6..c7664fb 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -62,23 +62,19 @@
~Factory() = default;
std::unique_ptr<DispSync> createDispSync(const char*, bool) override {
- // TODO: Use test-fixture controlled factory
return nullptr;
}
std::unique_ptr<EventControlThread> createEventControlThread(
std::function<void(bool)>) override {
- // TODO: Use test-fixture controlled factory
return nullptr;
}
std::unique_ptr<HWComposer> createHWComposer(const std::string&) override {
- // TODO: Use test-fixture controlled factory
return nullptr;
}
std::unique_ptr<MessageQueue> createMessageQueue() override {
- // TODO: Use test-fixture controlled factory
return std::make_unique<android::impl::MessageQueue>();
}
@@ -88,39 +84,49 @@
std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>,
const scheduler::RefreshRateConfigs&) override {
- // TODO: Use test-fixture controlled factory
return nullptr;
}
std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger* flinger) override {
- // TODO: Use test-fixture controlled factory
return std::make_unique<android::impl::SurfaceInterceptor>(flinger);
}
sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override {
- // TODO: Use test-fixture controlled factory
return new StartPropertySetThread(timestampPropertyValue);
}
sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&& creationArgs) override {
- // TODO: Use test-fixture controlled factory
return new DisplayDevice(std::move(creationArgs));
}
sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format,
uint32_t layerCount, uint64_t usage,
std::string requestorName) override {
- // TODO: Use test-fixture controlled factory
return new GraphicBuffer(width, height, format, layerCount, usage, requestorName);
}
void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) override {
- if (!mCreateBufferQueue) return;
+ if (!mCreateBufferQueue) {
+ BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
+ return;
+ }
mCreateBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
}
+ sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>& producer,
+ const sp<SurfaceFlinger>& flinger,
+ const wp<Layer>& layer) override {
+ return new MonitoredProducer(producer, flinger, layer);
+ }
+
+ sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>& consumer,
+ renderengine::RenderEngine& renderEngine,
+ uint32_t textureName, Layer* layer) override {
+ return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
+ }
+
std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>& producer) override {
if (!mCreateNativeWindowSurface) return nullptr;
@@ -132,22 +138,18 @@
}
sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override {
- // TODO: Use test-fixture controlled factory
return nullptr;
}
sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs&) override {
- // TODO: Use test-fixture controlled factory
return nullptr;
}
sp<ColorLayer> createColorLayer(const LayerCreationArgs&) override {
- // TODO: Use test-fixture controlled factory
return nullptr;
}
sp<ContainerLayer> createContainerLayer(const LayerCreationArgs&) override {
- // TODO: Use test-fixture controlled factory
return nullptr;
}
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 48f26e7..1578d9f 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -519,7 +519,11 @@
get_device_proc_addr_(nullptr),
driver_extensions_(nullptr),
driver_extension_count_(0) {
- enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE);
+ // advertise the loader supported core Vulkan API version at vulkan::api
+ for (uint32_t i = driver::ProcHook::EXTENSION_CORE_1_0;
+ i != driver::ProcHook::EXTENSION_COUNT; ++i) {
+ enabled_extensions_.set(i);
+ }
}
LayerChain::~LayerChain() {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index b413ac9..c3c19ec 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -99,6 +99,7 @@
VkResult Validate();
void DowngradeApiVersion();
+ void UpgradeDeviceCoreApiVersion(uint32_t api_version);
const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
@@ -328,8 +329,12 @@
physical_dev_(VK_NULL_HANDLE),
instance_info_(create_info),
extension_filter_() {
- hook_extensions_.set(ProcHook::EXTENSION_CORE);
- hal_extensions_.set(ProcHook::EXTENSION_CORE);
+ // instance core versions need to match the loader api version
+ for (uint32_t i = ProcHook::EXTENSION_CORE_1_0;
+ i != ProcHook::EXTENSION_COUNT; ++i) {
+ hook_extensions_.set(i);
+ hal_extensions_.set(i);
+ }
}
CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
@@ -340,8 +345,9 @@
physical_dev_(physical_dev),
dev_info_(create_info),
extension_filter_() {
- hook_extensions_.set(ProcHook::EXTENSION_CORE);
- hal_extensions_.set(ProcHook::EXTENSION_CORE);
+ // initialize with baseline core API version
+ hook_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
}
CreateInfoWrapper::~CreateInfoWrapper() {
@@ -540,7 +546,8 @@
case ProcHook::ANDROID_external_memory_android_hardware_buffer:
case ProcHook::ANDROID_native_buffer:
case ProcHook::GOOGLE_display_timing:
- case ProcHook::EXTENSION_CORE:
+ case ProcHook::EXTENSION_CORE_1_0:
+ case ProcHook::EXTENSION_CORE_1_1:
case ProcHook::EXTENSION_COUNT:
// Device and meta extensions. If we ever get here it's a bug in
// our code. But enumerating them lets us avoid having a default
@@ -588,7 +595,8 @@
case ProcHook::EXT_debug_report:
case ProcHook::EXT_swapchain_colorspace:
case ProcHook::ANDROID_native_buffer:
- case ProcHook::EXTENSION_CORE:
+ case ProcHook::EXTENSION_CORE_1_0:
+ case ProcHook::EXTENSION_CORE_1_1:
case ProcHook::EXTENSION_COUNT:
// Instance and meta extensions. If we ever get here it's a bug
// in our code. But enumerating them lets us avoid having a
@@ -636,6 +644,31 @@
}
}
+void CreateInfoWrapper::UpgradeDeviceCoreApiVersion(uint32_t api_version) {
+ ALOG_ASSERT(!is_instance_, "Device only API called by instance wrapper.");
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+ api_version ^= VK_VERSION_PATCH(api_version);
+#pragma clang diagnostic pop
+
+ // cap the API version to the loader supported highest version
+ if (api_version > VK_API_VERSION_1_1)
+ api_version = VK_API_VERSION_1_1;
+
+ switch (api_version) {
+ case VK_API_VERSION_1_1:
+ hook_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
+ [[clang::fallthrough]];
+ case VK_API_VERSION_1_0:
+ break;
+ default:
+ ALOGD("Unknown upgrade API version[%u]", api_version);
+ break;
+ }
+}
+
VKAPI_ATTR void* DefaultAllocate(void*,
size_t size,
size_t alignment,
@@ -771,7 +804,7 @@
: nullptr;
break;
case ProcHook::DEVICE:
- proc = (hook->extension == ProcHook::EXTENSION_CORE)
+ proc = (hook->extension == ProcHook::EXTENSION_CORE_1_0)
? hook->proc
: hook->checked_proc;
break;
@@ -1117,6 +1150,13 @@
if (!data)
return VK_ERROR_OUT_OF_HOST_MEMORY;
+ VkPhysicalDeviceProperties properties;
+ ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
+ instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
+ &properties);
+ ATRACE_END();
+
+ wrapper.UpgradeDeviceCoreApiVersion(properties.apiVersion);
data->hook_extensions |= wrapper.GetHookExtensions();
// call into the driver
@@ -1161,12 +1201,6 @@
return VK_ERROR_INCOMPATIBLE_DRIVER;
}
- VkPhysicalDeviceProperties properties;
- ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
- instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
- &properties);
- ATRACE_END();
-
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
// Log that the app is hitting software Vulkan implementation
android::GraphicsEnv::getInstance().setTargetStats(
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index f058c47..61e1818 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -67,9 +67,7 @@
: opaque_api_data(),
allocator(alloc),
driver(),
- get_device_proc_addr(nullptr) {
- hook_extensions.set(ProcHook::EXTENSION_CORE);
- }
+ get_device_proc_addr(nullptr) {}
api::InstanceData opaque_api_data;
@@ -89,9 +87,7 @@
: opaque_api_data(),
allocator(alloc),
debug_report_callbacks(debug_report_callbacks_),
- driver() {
- hook_extensions.set(ProcHook::EXTENSION_CORE);
- }
+ driver() {}
api::DeviceData opaque_api_data;
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 272f2d1..52205e9 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -74,6 +74,15 @@
}
}
+VKAPI_ATTR VkResult checkedBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+ if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
+ return BindImageMemory2(device, bindInfoCount, pBindInfos);
+ } else {
+ Logger(device).Err(device, "VK_VERSION_1_1 not enabled. vkBindImageMemory2 not executed.");
+ return VK_SUCCESS;
+ }
+}
+
VKAPI_ATTR VkResult checkedBindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
if (GetData(device).hook_extensions[ProcHook::KHR_bind_memory2]) {
return BindImageMemory2KHR(device, bindInfoCount, pBindInfos);
@@ -145,6 +154,14 @@
}
}
+VKAPI_ATTR void checkedGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+ if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
+ GetDeviceQueue2(device, pQueueInfo, pQueue);
+ } else {
+ Logger(device).Err(device, "VK_VERSION_1_1 not enabled. vkGetDeviceQueue2 not executed.");
+ }
+}
+
// clang-format on
const ProcHook g_proc_hooks[] = {
@@ -173,16 +190,16 @@
{
"vkAllocateCommandBuffers",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers),
nullptr,
},
{
"vkBindImageMemory2",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_1,
reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2),
- nullptr,
+ reinterpret_cast<PFN_vkVoidFunction>(checkedBindImageMemory2),
},
{
"vkBindImageMemory2KHR",
@@ -208,14 +225,14 @@
{
"vkCreateDevice",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
nullptr,
},
{
"vkCreateInstance",
ProcHook::GLOBAL,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(CreateInstance),
nullptr,
},
@@ -243,14 +260,14 @@
{
"vkDestroyDevice",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
nullptr,
},
{
"vkDestroyInstance",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance),
nullptr,
},
@@ -271,28 +288,28 @@
{
"vkEnumerateDeviceExtensionProperties",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties),
nullptr,
},
{
"vkEnumerateInstanceExtensionProperties",
ProcHook::GLOBAL,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties),
nullptr,
},
{
"vkEnumeratePhysicalDeviceGroups",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_1,
reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroups),
nullptr,
},
{
"vkEnumeratePhysicalDevices",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices),
nullptr,
},
@@ -313,28 +330,28 @@
{
"vkGetDeviceProcAddr",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr),
nullptr,
},
{
"vkGetDeviceQueue",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue),
nullptr,
},
{
"vkGetDeviceQueue2",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_1,
reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2),
- nullptr,
+ reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceQueue2),
},
{
"vkGetInstanceProcAddr",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr),
nullptr,
},
@@ -446,7 +463,7 @@
{
"vkQueueSubmit",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE,
+ ProcHook::EXTENSION_CORE_1_0,
reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit),
nullptr,
},
@@ -562,5 +579,3 @@
} // namespace driver
} // namespace vulkan
-
-// clang-format on
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index cd7d8f8..43c4d14 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -49,7 +49,8 @@
KHR_bind_memory2,
KHR_get_physical_device_properties2,
- EXTENSION_CORE, // valid bit
+ EXTENSION_CORE_1_0,
+ EXTENSION_CORE_1_1,
EXTENSION_COUNT,
EXTENSION_UNKNOWN,
};
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index d60eaa7..bbf50a1 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1291,6 +1291,7 @@
VkImageCreateInfo image_create = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = &image_native_buffer,
+ .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
.imageType = VK_IMAGE_TYPE_2D,
.format = create_info->imageFormat,
.extent = {0, 0, 1},
@@ -1299,7 +1300,6 @@
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = create_info->imageUsage,
- .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
.sharingMode = create_info->imageSharingMode,
.queueFamilyIndexCount = create_info->queueFamilyIndexCount,
.pQueueFamilyIndices = create_info->pQueueFamilyIndices,
diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py
index a0c648c..7c39075 100644
--- a/vulkan/scripts/api_generator.py
+++ b/vulkan/scripts/api_generator.py
@@ -13,28 +13,46 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-# This script provides the functions required for generating the
-# vulkan api framework directly from the vulkan registry (vk.xml)
+
+"""Generates the api_gen.h and api_gen.cpp.
+"""
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
+# Functions intercepted at vulkan::api level.
+_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():
+ """Generates the api_gen.h file.
+ """
+ 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 +64,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 +96,70 @@
} // 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):
+ """Emits a stub for an exported extension function.
-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')
+ Args:
+ cmd: Vulkan function name.
+ f: Output file handle.
+ """
+ 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 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('VKAPI_ATTR ' + ret + ' disabled' + gencom.base_name(cmd) +
+ '(' + first_param + ', ' + tail_params + ') {\n')
+
+ 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):
+ """Returns true if a function is intercepted by vulkan::api.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ 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):
+ """Emits code for vkGetInstanceProcAddr for function interception.
+
+ Args:
+ f: Output file handle.
+ """
+ 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 +167,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 +197,30 @@
}
// 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):
+ """Emits code for vkGetDeviceProcAddr for function interception.
+
+ Args:
+ f: Output file handle.
+ """
+ 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 +233,46 @@
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):
+ """Emits code to dispatch a function.
+
+ Args:
+ cmd: Vulkan function name.
+ f: Output file handle.
+ """
+ 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():
+ """Generates the api_gen.cpp file.
+ """
+ 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 +284,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 +392,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..2a017d2 100755
--- a/vulkan/scripts/code_generator.py
+++ b/vulkan/scripts/code_generator.py
@@ -13,20 +13,20 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-# This 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
+"""Generates vulkan framework directly from the vulkan registry (vk.xml).
+"""
+
+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..a64a702 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -13,45 +13,176 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-# This script provides the functions for generating the
-# vulkan driver framework directly from the vulkan registry (vk.xml).
-import generator_common as gencom
+"""Generates the driver_gen.h and driver_gen.cpp.
+"""
+
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',
+# Extensions intercepted at vulkan::driver level.
+_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',
+# Extensions known to vulkan::driver level.
+_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 {
+# Functions needed at vulkan::driver level.
+_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',
+]
+
+# Functions intercepted at vulkan::driver level.
+_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):
+ """Returns true if a function is needed by vulkan::driver.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ 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):
+ """Returns true if a instance-dispatched function is needed by vulkan::driver.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ return (_is_driver_table_entry(cmd) and
+ gencom.is_instance_dispatched(cmd))
+
+
+def _is_device_driver_table_entry(cmd):
+ """Returns true if a device-dispatched function is needed by vulkan::driver.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ return (_is_driver_table_entry(cmd) and
+ gencom.is_device_dispatched(cmd))
+
+
+def gen_h():
+ """Generates the driver_gen.h file.
+ """
+ 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 ext in _KNOWN_EXTENSIONS:
+ f.write(gencom.indent(2) + gencom.base_ext_name(ext) + ',\n')
+
+ f.write('\n')
+ for version in gencom.version_code_list:
+ f.write(gencom.indent(2) + 'EXTENSION_CORE_' + version + ',\n')
+
+ # EXTENSION_COUNT must be the next enum after the highest API version.
+ f.write("""\
EXTENSION_COUNT,
EXTENSION_UNKNOWN,
};
@@ -62,99 +193,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 +233,198 @@
} // 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):
+ """Returns true if a function is intercepted by vulkan::driver.
- # Enumeration of extensions
- 'vkEnumerateInstanceExtensionProperties' : True,
- 'vkEnumerateDeviceExtensionProperties' : True,
+ Args:
+ cmd: Vulkan function name.
+ """
+ if gencom.is_function_supported(cmd):
+ if cmd in _INTERCEPTED_COMMANDS:
+ return 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 _get_proc_hook_enum(cmd):
+ """Returns the ProcHook enumeration for the corresponding core function.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ assert cmd in gencom.version_dict
+ for version in gencom.version_code_list:
+ if gencom.version_dict[cmd] == 'VK_VERSION_' + version:
+ return 'ProcHook::EXTENSION_CORE_' + version
+
+
+def _need_proc_hook_stub(cmd):
+ """Returns true if a function needs a ProcHook stub.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ 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
+ elif gencom.version_dict[cmd] != 'VK_VERSION_1_0':
+ 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 _define_proc_hook_stub(cmd, f):
+ """Emits a stub for ProcHook::checked_proc.
-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')
- ext_hook = 'ProcHook::' + ext_name[3:]
+ Args:
+ cmd: Vulkan function name.
+ f: Output file handle.
+ """
+ if _need_proc_hook_stub(cmd):
+ return_type = gencom.return_type_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')
+ ext_name = ''
+ ext_hook = ''
+ if cmd in gencom.extension_dict:
+ ext_name = gencom.extension_dict[cmd]
+ ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name)
+ else:
+ ext_name = gencom.version_dict[cmd]
+ ext_hook = _get_proc_hook_enum(cmd)
-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,
- ProcHook::EXTENSION_CORE,
- reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+ 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('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')
+
+ 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):
+ """Emits definition of a global ProcHook.
+
+ Args:
+ cmd: Vulkan function name.
+ f: Output file handle.
+ """
+ assert cmd not in gencom.extension_dict
+
+ f.write(gencom.indent(1) + '{\n')
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+ f.write(gencom.indent(2) + 'ProcHook::GLOBAL,\n')
+ f.write(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
+ f.write(gencom.indent(2) + 'reinterpret_cast<PFN_vkVoidFunction>(' +
+ gencom.base_name(cmd) + '),\n')
+ f.write(gencom.indent(2) + 'nullptr,\n')
+ f.write(gencom.indent(1) + '},\n')
+
+
+def _define_instance_proc_hook(cmd, f):
+ """Emits definition of a instance ProcHook.
+
+ Args:
+ cmd: Vulkan function name.
+ f: Output file handle.
+ """
+ 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::' +
+ gencom.base_ext_name(ext_name) + ',\n')
+
+ if gencom.is_extension_internal(ext_name):
+ f.write("""\
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')
+ 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(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
+ f.write("""\
+ 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):
+ """Emits definition of a device ProcHook.
+
+ Args:
+ cmd: Vulkan function name.
+ f: Output file handle.
+ """
+ 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 or
+ gencom.version_dict[cmd] != 'VK_VERSION_1_0'):
+ ext_name = ''
+ ext_hook = ''
+ if cmd in gencom.extension_dict:
+ ext_name = gencom.extension_dict[cmd]
+ ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name)
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')
+ ext_name = gencom.version_dict[cmd]
+ ext_hook = _get_proc_hook_enum(cmd)
+ f.write(gencom.indent(2) + ext_hook + ',\n')
+
+ if gencom.is_extension_internal(ext_name):
+ f.write("""\
+ nullptr,
+ nullptr,\n""")
+ else:
+ 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(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
+ f.write("""\
+ 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():
+ """Generates the driver_gen.cpp file.
+ """
+ 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 +436,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 +471,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 ext in _KNOWN_EXTENSIONS:
+ f.write(gencom.indent(1) + 'if (strcmp(name, \"' + ext +
+ '\") == 0) return ProcHook::' + gencom.base_ext_name(ext) + ';\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..cf370fa 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -13,33 +13,16 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-# This script provides the common functions for generating the
-# vulkan framework directly from the vulkan registry (vk.xml).
-from subprocess import check_call
-
-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.
- */
-
+"""Provide the utilities for framework generation.
"""
-warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n'
+import os
+import subprocess
+import xml.etree.ElementTree as element_tree
-blacklistedExtensions = [
+# Extensions unsupported on Android.
+_BLACKLISTED_EXTENSIONS = [
'VK_EXT_acquire_xlib_display',
'VK_EXT_direct_mode_display',
'VK_EXT_display_control',
@@ -70,191 +53,354 @@
'VK_NVX_image_view_handle',
]
-exportedExtensions = [
+# Extensions having functions exported by the loader.
+_EXPORTED_EXTENSIONS = [
'VK_ANDROID_external_memory_android_hardware_buffer',
'VK_KHR_android_surface',
'VK_KHR_surface',
'VK_KHR_swapchain',
]
-optionalCommands = [
+# Functions optional on Android even if extension is advertised.
+_OPTIONAL_COMMANDS = [
'vkGetSwapchainGrallocUsageANDROID',
'vkGetSwapchainGrallocUsage2ANDROID',
]
-def runClangFormat(args):
- clang_call = ["clang-format", "--style", "file", "-i", args]
- check_call (clang_call)
+# Dict for mapping dispatch table to a type.
+_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
+# Dict for mapping a function to its alias.
+alias_dict = {}
-def isFunctionSupported(functionName):
- if functionName not in extensionsDict:
+# List of all the Vulkan functions.
+command_list = []
+
+# Dict for mapping a function to an extension.
+extension_dict = {}
+
+# Dict for mapping a function to all its parameters.
+param_dict = {}
+
+# Dict for mapping a function to its return type.
+return_type_dict = {}
+
+# List of the sorted Vulkan version codes. e.g. '1_0', '1_1'.
+version_code_list = []
+
+# Dict for mapping a function to the core Vulkan API version.
+version_dict = {}
+
+
+def indent(num):
+ """Returns the requested indents.
+
+ Args:
+ num: Number of the 4-space indents.
+ """
+ return ' ' * num
+
+
+def copyright_and_warning(year):
+ """Returns the standard copyright and warning codes.
+
+ Args:
+ year: An integer year for the copyright.
+ """
+ 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):
+ """Run clang format on the file.
+
+ Args:
+ args: The file to be formatted.
+ """
+ clang_call = ['clang-format', '--style', 'file', '-i', args]
+ subprocess.check_call(clang_call)
+
+
+def is_extension_internal(ext):
+ """Returns true if an extension is internal to the loader and drivers.
+
+ The loader should not enumerate this extension.
+
+ Args:
+ ext: Vulkan extension name.
+ """
+ return ext == 'VK_ANDROID_native_buffer'
+
+
+def base_name(cmd):
+ """Returns a function name without the 'vk' prefix.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ return cmd[2:]
+
+
+def base_ext_name(ext):
+ """Returns an extension name without the 'VK_' prefix.
+
+ Args:
+ ext: Vulkan extension name.
+ """
+ return ext[3:]
+
+
+def version_code(version):
+ """Returns the version code from a version string.
+
+ Args:
+ version: Vulkan version string.
+ """
+ return version[11:]
+
+
+def is_function_supported(cmd):
+ """Returns true if a function is core or from a supportable extension.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ 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 get_dispatch_table_type(cmd):
+ """Returns the dispatch table type for a function.
-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:
+ Args:
+ cmd: Vulkan function name.
+ """
+ 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):
+ """Returns true if the function is global, which is not dispatched.
+
+ Only global functions and functions handled in the loader top without calling
+ into lower layers are not dispatched.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'
+
+
+def is_instance_dispatched(cmd):
+ """Returns true for functions that can have instance-specific dispatch.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ return (is_function_supported(cmd) and
+ get_dispatch_table_type(cmd) == 'Instance')
+
+
+def is_device_dispatched(cmd):
+ """Returns true for functions that can have device-specific dispatch.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'
+
+
+def is_extension_exported(ext):
+ """Returns true if an extension has functions exported by the loader.
+
+ E.g. applications can directly link to an extension function.
+
+ Args:
+ ext: Vulkan extension name.
+ """
+ return ext in _EXPORTED_EXTENSIONS
+
+
+def is_function_exported(cmd):
+ """Returns true if a function is exported from the Android Vulkan library.
+
+ Functions in the core API and in loader extensions are exported.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ 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):
+ """Returns true if a function is exported and instance-dispatched.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ 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):
+ """Returns true if a function is exported and device-dispatched.
-def clang_off(f, indent):
- f.write (clang_off_spaces * indent + '// clang-format off\n')
+ Args:
+ cmd: Vulkan function name.
+ """
+ return is_function_exported(cmd) and is_device_dispatched(cmd)
-clang_off_spaces = ' ' * 4
-parametersList = []
-paramDict = {}
-allCommandsList = []
-extensionsDict = {}
-returnTypeDict = {}
-versionDict = {}
-aliasDict = {}
+def init_proc(name, f):
+ """Emits code to invoke INIT_PROC or INIT_PROC_EXT.
-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)
+ Args:
+ name: Vulkan function name.
+ f: Output file handle.
+ """
+ f.write(indent(1))
+ if name in extension_dict:
+ f.write('INIT_PROC_EXT(' + base_ext_name(extension_dict[name]) + ', ')
+ else:
+ f.write('INIT_PROC(')
+
+ 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, ')
+
+ if is_instance_dispatched(name):
+ f.write('instance, ')
+ else:
+ f.write('dev, ')
+
+ f.write(base_name(name) + ');\n')
+
+
+def parse_vulkan_registry():
+ """Parses Vulkan registry into the below global variables.
+
+ alias_dict
+ command_list
+ extension_dict
+ param_dict
+ return_type_dict
+ version_code_list
+ version_dict
+ """
+ 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
+ cmd_name = command.get('name')
+ if cmd_name in command_list:
+ version_dict[cmd_name] = 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')
-
+ version_code_set = set()
+ for version in version_dict.values():
+ version_code_set.add(version_code(version))
+ for code in sorted(version_code_set):
+ version_code_list.append(code)
diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py
index 3a761ce..e9faef6 100644
--- a/vulkan/scripts/null_generator.py
+++ b/vulkan/scripts/null_generator.py
@@ -13,49 +13,43 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-# This script provides the functions for generating the null driver
-# framework directly from the vulkan registry (vk.xml).
-import generator_common as gencom
-import os
-
-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.
- */
-
+"""Generates the null_driver_gen.h and null_driver_gen.cpp.
"""
-def isDriverExtension(extensionName):
- switchCase = {
- 'VK_ANDROID_native_buffer' : True,
- 'VK_EXT_debug_report' : True,
- 'VK_KHR_get_physical_device_properties2' : True
- }
+import os
+import generator_common as gencom
- if extensionName in switchCase:
- return switchCase[extensionName]
- return False
+# Extensions implemented by the driver.
+_DRIVER_EXTENSION_DICT = {
+ 'VK_ANDROID_native_buffer',
+ 'VK_EXT_debug_report',
+ 'VK_KHR_get_physical_device_properties2'
+}
-def isDriverFunction(functionName):
- if functionName in gencom.extensionsDict:
- return isDriverExtension(gencom.extensionsDict[functionName])
+
+def _is_driver_function(cmd):
+ """Returns true if the function is implemented by the driver.
+
+ Args:
+ cmd: Vulkan function name.
+ """
+ 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():
+ """Generates the null_driver_gen.h file.
+ """
+ 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 +60,36 @@
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():
+ """Generates the null_driver_gen.cpp file.
+ """
+ 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 +119,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 +159,6 @@
}
} // namespace null_driver\n""")
- f.close()
- gencom.runClangFormat(genfile)
+ f.close()
+ gencom.run_clang_format(genfile)