Merge "Use newer matrix api"
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 015954d..90feedd 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -145,6 +145,7 @@
cflags: [
"-Wall",
"-Wextra",
+ "-Wextra-semi",
"-Werror",
"-Wzero-as-null-pointer-constant",
"-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index cf9bb46..08169f5 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -135,6 +135,6 @@
// ------------------------------------------------------------------------------------
-IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager");
+IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager")
} // namespace android
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index b9eb281..2b3f462 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -43,7 +43,7 @@
}
};
-IMPLEMENT_META_INTERFACE(AppOpsCallback, "com.android.internal.app.IAppOpsCallback");
+IMPLEMENT_META_INTERFACE(AppOpsCallback, "com.android.internal.app.IAppOpsCallback")
// ----------------------------------------------------------------------
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index ee0cd62..1897969 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -162,7 +162,7 @@
}
};
-IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
+IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService")
// ----------------------------------------------------------------------
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index a47dbac..d0085df 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -130,7 +130,7 @@
};
-IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats");
+IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats")
// ----------------------------------------------------------------------
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
index 5f3d670..f5fa817 100644
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -38,7 +38,7 @@
}
};
-IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor");
+IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor")
// ----------------------------------------------------------------------
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index d8b44f9..cca8f81 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -223,7 +223,7 @@
// ---------------------------------------------------------------------------
-IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory");
+IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory")
BnMemory::BnMemory() {
}
@@ -388,7 +388,7 @@
// ---------------------------------------------------------------------------
-IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
+IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap")
BnMemoryHeap::BnMemoryHeap() {
}
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index d9bf3cc..f94f413 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -103,7 +103,7 @@
}
};
-IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");
+IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController")
// ----------------------------------------------------------------------
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
index a38a27a..570edb9 100644
--- a/libs/binder/IProcessInfoService.cpp
+++ b/libs/binder/IProcessInfoService.cpp
@@ -84,7 +84,7 @@
}
};
-IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService");
+IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService")
// ----------------------------------------------------------------------
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
index 556288c..cd92217 100644
--- a/libs/binder/IResultReceiver.cpp
+++ b/libs/binder/IResultReceiver.cpp
@@ -42,7 +42,7 @@
}
};
-IMPLEMENT_META_INTERFACE(ResultReceiver, "com.android.internal.os.IResultReceiver");
+IMPLEMENT_META_INTERFACE(ResultReceiver, "com.android.internal.os.IResultReceiver")
// ----------------------------------------------------------------------
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index a3e2b67..86dd5c4 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -52,7 +52,7 @@
}
};
-IMPLEMENT_META_INTERFACE(ShellCallback, "com.android.internal.os.IShellCallback");
+IMPLEMENT_META_INTERFACE(ShellCallback, "com.android.internal.os.IShellCallback")
// ----------------------------------------------------------------------
diff --git a/libs/binder/IUidObserver.cpp b/libs/binder/IUidObserver.cpp
index 4714234..a1b08db 100644
--- a/libs/binder/IUidObserver.cpp
+++ b/libs/binder/IUidObserver.cpp
@@ -71,7 +71,7 @@
// ----------------------------------------------------------------------
-IMPLEMENT_META_INTERFACE(UidObserver, "android.app.IUidObserver");
+IMPLEMENT_META_INTERFACE(UidObserver, "android.app.IUidObserver")
// ----------------------------------------------------------------------
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index 75a6d22..6eae5ef 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -27,7 +27,7 @@
// ----------------------------------------------------------------------------
-ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache) ;
+ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache)
// ----------------------------------------------------------------------------
diff --git a/libs/binder/ProcessInfoService.cpp b/libs/binder/ProcessInfoService.cpp
index 00d6eef..f75141e 100644
--- a/libs/binder/ProcessInfoService.cpp
+++ b/libs/binder/ProcessInfoService.cpp
@@ -99,6 +99,6 @@
}
}
-ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService);
+ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService)
} // namespace android
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index db0f1c7..565f2e2 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -33,7 +33,7 @@
{
public:
LogTextOutput() : BufferedTextOutput(MULTITHREADED) { }
- virtual ~LogTextOutput() { };
+ virtual ~LogTextOutput() { }
protected:
virtual status_t writeLines(const struct iovec& vec, size_t N)
@@ -49,7 +49,7 @@
{
public:
explicit FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { }
- virtual ~FdTextOutput() { };
+ virtual ~FdTextOutput() { }
protected:
virtual status_t writeLines(const struct iovec& vec, size_t N)
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index a0e28d2..2735315 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -28,7 +28,7 @@
namespace internal {
class Stability;
-};
+}
using binder_proxy_limit_callback = void(*)(int);
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index 17e34db..6d3fe4a 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -25,7 +25,7 @@
class IShellCallback : public IInterface
{
public:
- DECLARE_META_INTERFACE(ShellCallback);
+ DECLARE_META_INTERFACE(ShellCallback)
virtual int openFile(const String16& path, const String16& seLinuxContext,
const String16& mode) = 0;
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
index c1cd3c2..a8faa3f 100644
--- a/libs/binder/include/binder/IpPrefix.h
+++ b/libs/binder/include/binder/IpPrefix.h
@@ -73,8 +73,8 @@
private:
union InternalUnion {
InternalUnion() = default;
- explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
- explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
+ explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { }
+ explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { }
struct in6_addr mIn6Addr;
struct in_addr mInAddr;
} mUnion;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 4b2d50d..cfe1f3a 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -131,7 +131,7 @@
status_t writeString8(const char* str, size_t len);
status_t writeString16(const String16& str);
status_t writeString16(const std::optional<String16>& str);
- status_t writeString16(const std::unique_ptr<String16>& str);
+ status_t writeString16(const std::unique_ptr<String16>& str) __attribute__((deprecated("use std::optional version instead")));
status_t writeString16(const char16_t* str, size_t len);
status_t writeStrongBinder(const sp<IBinder>& val);
status_t writeInt32Array(size_t len, const int32_t *val);
@@ -143,48 +143,48 @@
// Take a UTF8 encoded string, convert to UTF16, write it to the parcel.
status_t writeUtf8AsUtf16(const std::string& str);
status_t writeUtf8AsUtf16(const std::optional<std::string>& str);
- status_t writeUtf8AsUtf16(const std::unique_ptr<std::string>& str);
+ status_t writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) __attribute__((deprecated("use std::optional version instead")));
status_t writeByteVector(const std::optional<std::vector<int8_t>>& val);
- status_t writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val);
+ status_t writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeByteVector(const std::vector<int8_t>& val);
status_t writeByteVector(const std::optional<std::vector<uint8_t>>& val);
- status_t writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val);
+ status_t writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeByteVector(const std::vector<uint8_t>& val);
status_t writeInt32Vector(const std::optional<std::vector<int32_t>>& val);
- status_t writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val);
+ status_t writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeInt32Vector(const std::vector<int32_t>& val);
status_t writeInt64Vector(const std::optional<std::vector<int64_t>>& val);
- status_t writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val);
+ status_t writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeInt64Vector(const std::vector<int64_t>& val);
status_t writeUint64Vector(const std::optional<std::vector<uint64_t>>& val);
- status_t writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val);
+ status_t writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeUint64Vector(const std::vector<uint64_t>& val);
status_t writeFloatVector(const std::optional<std::vector<float>>& val);
- status_t writeFloatVector(const std::unique_ptr<std::vector<float>>& val);
+ status_t writeFloatVector(const std::unique_ptr<std::vector<float>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeFloatVector(const std::vector<float>& val);
status_t writeDoubleVector(const std::optional<std::vector<double>>& val);
- status_t writeDoubleVector(const std::unique_ptr<std::vector<double>>& val);
+ status_t writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeDoubleVector(const std::vector<double>& val);
status_t writeBoolVector(const std::optional<std::vector<bool>>& val);
- status_t writeBoolVector(const std::unique_ptr<std::vector<bool>>& val);
+ status_t writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeBoolVector(const std::vector<bool>& val);
status_t writeCharVector(const std::optional<std::vector<char16_t>>& val);
- status_t writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val);
+ status_t writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeCharVector(const std::vector<char16_t>& val);
status_t writeString16Vector(
const std::optional<std::vector<std::optional<String16>>>& val);
status_t writeString16Vector(
- const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val);
+ const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeString16Vector(const std::vector<String16>& val);
status_t writeUtf8VectorAsUtf16Vector(
const std::optional<std::vector<std::optional<std::string>>>& val);
status_t writeUtf8VectorAsUtf16Vector(
- const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val);
+ const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val);
status_t writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val);
- status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
+ status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
// Write an Enum vector with underlying type int8_t.
@@ -194,21 +194,21 @@
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::optional<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);
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
// 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::optional<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);
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
template<typename T>
status_t writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val);
template<typename T>
- status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
+ status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")));
template<typename T>
- status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val);
+ status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")));
template<typename T>
status_t writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val);
template<typename T>
@@ -217,7 +217,7 @@
template<typename T>
status_t writeNullableParcelable(const std::optional<T>& parcelable);
template<typename T>
- status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable);
+ status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")));
status_t writeParcelable(const Parcelable& parcelable);
@@ -232,7 +232,7 @@
template<typename T>
status_t writeVectorSize(const std::optional<std::vector<T>>& val);
template<typename T>
- status_t writeVectorSize(const std::unique_ptr<std::vector<T>>& val);
+ status_t writeVectorSize(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
// Place a native_handle into the parcel (the native_handle's file-
// descriptors are dup'ed, so it is safe to delete the native_handle
@@ -269,7 +269,7 @@
status_t writeUniqueFileDescriptorVector(
const std::optional<std::vector<base::unique_fd>>& val);
status_t writeUniqueFileDescriptorVector(
- const std::unique_ptr<std::vector<base::unique_fd>>& val);
+ const std::unique_ptr<std::vector<base::unique_fd>>& val) __attribute__((deprecated("use std::optional version instead")));
status_t writeUniqueFileDescriptorVector(
const std::vector<base::unique_fd>& val);
@@ -317,7 +317,7 @@
// Read a UTF16 encoded string, convert to UTF8
status_t readUtf8FromUtf16(std::string* str) const;
status_t readUtf8FromUtf16(std::optional<std::string>* str) const;
- status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const;
+ status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const __attribute__((deprecated("use std::optional version instead")));
const char* readCString() const;
String8 readString8() const;
@@ -326,7 +326,7 @@
String16 readString16() const;
status_t readString16(String16* pArg) const;
status_t readString16(std::optional<String16>* pArg) const;
- status_t readString16(std::unique_ptr<String16>* pArg) const;
+ status_t readString16(std::unique_ptr<String16>* pArg) const __attribute__((deprecated("use std::optional version instead")));
const char16_t* readString16Inplace(size_t* outLen) const;
sp<IBinder> readStrongBinder() const;
status_t readStrongBinder(sp<IBinder>* val) const;
@@ -337,14 +337,14 @@
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;
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
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::optional<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;
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
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::optional<std::vector<T>>* val) const;
@@ -353,7 +353,7 @@
std::optional<std::vector<std::optional<T>>>* val) const;
template<typename T>
status_t readParcelableVector(
- std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
+ std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead")));
template<typename T>
status_t readParcelableVector(std::vector<T>* val) const;
@@ -362,7 +362,7 @@
template<typename T>
status_t readParcelable(std::optional<T>* parcelable) const;
template<typename T>
- status_t readParcelable(std::unique_ptr<T>* parcelable) const;
+ status_t readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")));
template<typename T>
status_t readStrongBinder(sp<T>* val) const;
@@ -371,45 +371,45 @@
status_t readNullableStrongBinder(sp<T>* val) const;
status_t readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const;
- status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const;
+ status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
status_t readByteVector(std::optional<std::vector<int8_t>>* val) const;
- status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const;
+ status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readByteVector(std::vector<int8_t>* val) const;
status_t readByteVector(std::optional<std::vector<uint8_t>>* val) const;
- status_t readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const;
+ status_t readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readByteVector(std::vector<uint8_t>* val) const;
status_t readInt32Vector(std::optional<std::vector<int32_t>>* val) const;
- status_t readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const;
+ status_t readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readInt32Vector(std::vector<int32_t>* val) const;
status_t readInt64Vector(std::optional<std::vector<int64_t>>* val) const;
- status_t readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const;
+ status_t readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readInt64Vector(std::vector<int64_t>* val) const;
status_t readUint64Vector(std::optional<std::vector<uint64_t>>* val) const;
- status_t readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const;
+ status_t readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readUint64Vector(std::vector<uint64_t>* val) const;
status_t readFloatVector(std::optional<std::vector<float>>* val) const;
- status_t readFloatVector(std::unique_ptr<std::vector<float>>* val) const;
+ status_t readFloatVector(std::unique_ptr<std::vector<float>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readFloatVector(std::vector<float>* val) const;
status_t readDoubleVector(std::optional<std::vector<double>>* val) const;
- status_t readDoubleVector(std::unique_ptr<std::vector<double>>* val) const;
+ status_t readDoubleVector(std::unique_ptr<std::vector<double>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readDoubleVector(std::vector<double>* val) const;
status_t readBoolVector(std::optional<std::vector<bool>>* val) const;
- status_t readBoolVector(std::unique_ptr<std::vector<bool>>* val) const;
+ status_t readBoolVector(std::unique_ptr<std::vector<bool>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readBoolVector(std::vector<bool>* val) const;
status_t readCharVector(std::optional<std::vector<char16_t>>* val) const;
- status_t readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const;
+ status_t readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readCharVector(std::vector<char16_t>* val) const;
status_t readString16Vector(
std::optional<std::vector<std::optional<String16>>>* val) const;
status_t readString16Vector(
- std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const;
+ std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readString16Vector(std::vector<String16>* val) const;
status_t readUtf8VectorFromUtf16Vector(
std::optional<std::vector<std::optional<std::string>>>* val) const;
status_t readUtf8VectorFromUtf16Vector(
- std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const;
+ std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
template<typename T>
@@ -423,7 +423,7 @@
template<typename T>
status_t resizeOutVector(std::optional<std::vector<T>>* val) const;
template<typename T>
- status_t resizeOutVector(std::unique_ptr<std::vector<T>>* val) const;
+ status_t resizeOutVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
template<typename T>
status_t reserveOutVector(std::vector<T>* val, size_t* size) const;
template<typename T>
@@ -431,7 +431,7 @@
size_t* size) const;
template<typename T>
status_t reserveOutVector(std::unique_ptr<std::vector<T>>* val,
- size_t* size) const;
+ size_t* size) const __attribute__((deprecated("use std::optional version instead")));
// Like Parcel.java's readExceptionCode(). Reads the first int32
// off of a Parcel's header, returning 0 or the negative error
@@ -467,7 +467,7 @@
status_t readUniqueFileDescriptorVector(
std::optional<std::vector<base::unique_fd>>* val) const;
status_t readUniqueFileDescriptorVector(
- std::unique_ptr<std::vector<base::unique_fd>>* val) const;
+ std::unique_ptr<std::vector<base::unique_fd>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readUniqueFileDescriptorVector(
std::vector<base::unique_fd>* val) const;
@@ -561,7 +561,7 @@
status_t(Parcel::*read_func)(T*) const) const;
template<typename T>
status_t readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
- status_t(Parcel::*read_func)(T*) const) const;
+ status_t(Parcel::*read_func)(T*) const) const __attribute__((deprecated("use std::optional version instead")));
template<typename T>
status_t readTypedVector(std::vector<T>* val,
status_t(Parcel::*read_func)(T*) const) const;
@@ -573,13 +573,13 @@
status_t(Parcel::*write_func)(const T&));
template<typename T>
status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
- status_t(Parcel::*write_func)(const T&));
+ status_t(Parcel::*write_func)(const T&)) __attribute__((deprecated("use std::optional version instead")));
template<typename T>
status_t writeNullableTypedVector(const std::optional<std::vector<T>>& val,
status_t(Parcel::*write_func)(T));
template<typename T>
status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
- status_t(Parcel::*write_func)(T));
+ status_t(Parcel::*write_func)(T)) __attribute__((deprecated("use std::optional version instead")));
template<typename T>
status_t writeTypedVector(const std::vector<T>& val,
status_t(Parcel::*write_func)(const T&));
diff --git a/libs/binder/include/binder/ParcelableHolder.h b/libs/binder/include/binder/ParcelableHolder.h
index 4ea3dd3..ce5027e 100644
--- a/libs/binder/include/binder/ParcelableHolder.h
+++ b/libs/binder/include/binder/ParcelableHolder.h
@@ -30,7 +30,7 @@
class ParcelableHolder : public android::Parcelable {
public:
ParcelableHolder() = delete;
- explicit ParcelableHolder(Stability stability) : mStability(stability){};
+ explicit ParcelableHolder(Stability stability) : mStability(stability){}
virtual ~ParcelableHolder() = default;
ParcelableHolder(const ParcelableHolder& other) {
mParcelable = other.mParcelable;
@@ -40,7 +40,7 @@
mParcelPtr->appendFrom(other.mParcelPtr.get(), 0, other.mParcelPtr->dataSize());
}
mStability = other.mStability;
- };
+ }
status_t writeToParcel(Parcel* parcel) const override;
status_t readFromParcel(const Parcel* parcel) override;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 5e2e1bd..350c658 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -307,7 +307,8 @@
: onCreate(onCreate),
onDestroy(onDestroy),
onTransact(onTransact),
- mInterfaceDescriptor(interfaceDescriptor) {}
+ mInterfaceDescriptor(interfaceDescriptor),
+ mWideInterfaceDescriptor(interfaceDescriptor) {}
AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
AIBinder_Class_onCreate onCreate,
@@ -335,6 +336,12 @@
clazz->handleShellCommand = handleShellCommand;
}
+const char* AIBinder_Class_getDescriptor(const AIBinder_Class* clazz) {
+ CHECK(clazz != nullptr) << "getDescriptor requires non-null clazz";
+
+ return clazz->getInterfaceDescriptorUtf8();
+}
+
void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
CHECK(who == mWho);
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 6236e81..6824306 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -112,7 +112,8 @@
AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
- const ::android::String16& getInterfaceDescriptor() const { return mInterfaceDescriptor; }
+ const ::android::String16& getInterfaceDescriptor() const { return mWideInterfaceDescriptor; }
+ const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); }
// required to be non-null, implemented for every class
const AIBinder_Class_onCreate onCreate = nullptr;
@@ -124,9 +125,11 @@
AIBinder_handleShellCommand handleShellCommand = nullptr;
private:
+ // Copy of the raw char string for when we don't have to return UTF-16
+ const std::string mInterfaceDescriptor;
// This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
// one.
- const ::android::String16 mInterfaceDescriptor;
+ const ::android::String16 mWideInterfaceDescriptor;
};
// Ownership is like this (when linked to death):
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index ce3d1db..5e1ed46 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -642,6 +642,23 @@
#endif //__ANDROID_API__ >= 30
+#if __ANDROID_API__ >= 31
+
+/**
+ * Retrieve the class descriptor for the class.
+ *
+ * Available since API level 31.
+ *
+ * \param clazz the class to fetch the descriptor from
+ *
+ * \return the class descriptor string. This pointer will never be null; a
+ * descriptor is required to define a class. The pointer is owned by the class
+ * and will remain valid as long as the class does.
+ */
+const char* AIBinder_Class_getDescriptor(const AIBinder_Class* clazz) __INTRODUCED_IN(31);
+
+#endif //__ANDROID_API__ >= 31
+
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 6962f86..e233ffd 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -121,6 +121,7 @@
AServiceManager_registerLazyService; # llndk
AServiceManager_waitForService; # apex llndk
+ AIBinder_Class_getDescriptor;
AParcel_appendFrom;
AParcel_create;
AParcel_getDataSize;
diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp
index a588985..2afe5d2 100644
--- a/libs/binder/ndk/tests/iface.cpp
+++ b/libs/binder/ndk/tests/iface.cpp
@@ -25,7 +25,7 @@
const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
const char* IFoo::kInstanceNameToDieFor = "libbinder_ndk-test-IFoo-to-die";
-const char* kIFooDescriptor = "my-special-IFoo-class";
+const char* IFoo::kIFooDescriptor = "my-special-IFoo-class";
struct IFoo_Class_Data {
sp<IFoo> foo;
diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h
index d9dd64b..7408d0c 100644
--- a/libs/binder/ndk/tests/include/iface/iface.h
+++ b/libs/binder/ndk/tests/include/iface/iface.h
@@ -27,6 +27,7 @@
public:
static const char* kSomeInstanceName;
static const char* kInstanceNameToDieFor;
+ static const char* kIFooDescriptor;
static AIBinder_Class* kClass;
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index f84d9d3..b7df115 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -39,6 +39,7 @@
#include <condition_variable>
#include <iostream>
#include <mutex>
+#include "android/binder_ibinder.h"
using namespace android;
@@ -543,6 +544,10 @@
EXPECT_EQ("CMD", shellCmdToString(testService, {"C", "M", "D"}));
}
+TEST(NdkBinder, GetClassInterfaceDescriptor) {
+ ASSERT_STREQ(IFoo::kIFooDescriptor, AIBinder_Class_getDescriptor(IFoo::kClass));
+}
+
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/parcel_fuzzer/binder.cpp
index 96cd215..624def1 100644
--- a/libs/binder/parcel_fuzzer/binder.cpp
+++ b/libs/binder/parcel_fuzzer/binder.cpp
@@ -86,6 +86,8 @@
PARCEL_READ_WITH_STATUS(T, FUN), \
PARCEL_READ_NO_STATUS(T, FUN)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// clang-format off
std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS {
PARCEL_READ_NO_STATUS(size_t, dataSize),
@@ -296,3 +298,4 @@
PARCEL_READ_WITH_STATUS(android::os::PersistableBundle, readParcelable),
};
// clang-format on
+#pragma clang diagnostic pop
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 09f58cc..2f9d85e 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -184,7 +184,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
-IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback");
+IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback")
#pragma clang diagnostic pop
class BnCallback : public SafeBnInterface<ICallback> {
@@ -373,7 +373,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
-IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest");
+IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest")
static sp<IBinder::DeathRecipient> getDeathRecipient() {
static sp<IBinder::DeathRecipient> recipient = new ExitOnDeath;
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index ab4c56a..56d958c 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -245,7 +245,7 @@
double best = (double)m_best / 1.0E6;
double worst = (double)m_worst / 1.0E6;
double average = (double)m_total_time / m_transactions / 1.0E6;
- // FIXME: libjson?
+ // TODO: libjson?
int W = DUMP_PRESICION + 2;
cout << setprecision(DUMP_PRESICION) << "{ \"avg\":" << setw(W) << left
<< average << ",\"wst\":" << setw(W) << left << worst
@@ -376,7 +376,7 @@
if (is_client(num)) {
int no_trans = iterations * 2;
double sync_ratio = (1.0 - (double)no_sync / no_trans);
- // FIXME: libjson?
+ // TODO: libjson?
cout << "\"P" << (num - server_count) << "\":{\"SYNC\":\""
<< ((sync_ratio > GOOD_SYNC_MIN) ? "GOOD" : "POOR") << "\","
<< "\"S\":" << (no_trans - no_sync) << ",\"I\":" << no_trans << ","
@@ -466,7 +466,7 @@
}
vector<Pipe> pipes;
thread_dump("main");
- // FIXME: libjson?
+ // TODO: libjson?
cout << "{" << endl;
cout << "\"cfg\":{\"pair\":" << (no_process / 2)
<< ",\"iterations\":" << iterations << ",\"deadline_us\":" << deadline_us
@@ -495,7 +495,7 @@
// detected in the child process
no_inherent += status;
}
- // FIXME: libjson?
+ // TODO: libjson?
cout << "\"inheritance\": " << (no_inherent == 0 ? "\"PASS\"" : "\"FAIL\"")
<< endl;
cout << "}" << endl;
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index cd7f37b..b878150 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -31,6 +31,9 @@
"libui",
"libutils",
],
+ include_dirs: [
+ "external/skia/src/gpu",
+ ],
whole_static_libs: ["libskia"],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
@@ -75,6 +78,7 @@
filegroup {
name: "librenderengine_skia_sources",
srcs: [
+ "skia/AutoBackendTexture.cpp",
"skia/SkiaRenderEngine.cpp",
"skia/SkiaGLRenderEngine.cpp",
"skia/filters/BlurFilter.cpp",
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index be83ebc..279e648 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -15,6 +15,7 @@
*/
//#define LOG_NDEBUG 0
+#include "EGL/egl.h"
#undef LOG_TAG
#define LOG_TAG "RenderEngine"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -446,19 +447,37 @@
mPlaceholderBuffer, attributes);
ALOGE_IF(mPlaceholderImage == EGL_NO_IMAGE_KHR, "Failed to create placeholder image: %#x",
eglGetError());
+
+ mShadowTexture = std::make_unique<GLShadowTexture>();
}
GLESRenderEngine::~GLESRenderEngine() {
// Destroy the image manager first.
mImageManager = nullptr;
+ mShadowTexture = nullptr;
cleanFramebufferCache();
+ ProgramCache::getInstance().purgeCaches();
std::lock_guard<std::mutex> lock(mRenderingMutex);
+ glDisableVertexAttribArray(Program::position);
unbindFrameBuffer(mDrawingBuffer.get());
mDrawingBuffer = nullptr;
eglDestroyImageKHR(mEGLDisplay, mPlaceholderImage);
mImageCache.clear();
+ if (mStubSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEGLDisplay, mStubSurface);
+ }
+ if (mProtectedStubSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEGLDisplay, mProtectedStubSurface);
+ }
+ if (mEGLContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEGLDisplay, mEGLContext);
+ }
+ if (mProtectedEGLContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEGLDisplay, mProtectedEGLContext);
+ }
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(mEGLDisplay);
+ eglReleaseThread();
}
std::unique_ptr<Framebuffer> GLESRenderEngine::createFramebuffer() {
@@ -1800,7 +1819,7 @@
mState.cornerRadius = 0.0f;
mState.drawShadows = true;
- setupLayerTexturing(mShadowTexture.getTexture());
+ setupLayerTexturing(mShadowTexture->getTexture());
drawMesh(mesh);
mState.drawShadows = false;
}
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index c0449a1..92e1529 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -193,7 +193,7 @@
GLuint mVpWidth;
GLuint mVpHeight;
Description mState;
- GLShadowTexture mShadowTexture;
+ std::unique_ptr<GLShadowTexture> mShadowTexture = nullptr;
mat4 mSrgbToXyz;
mat4 mDisplayP3ToXyz;
@@ -294,7 +294,7 @@
friend class BlurFilter;
friend class GenericProgram;
std::unique_ptr<FlushTracer> mFlushTracer;
- std::unique_ptr<ImageManager> mImageManager = std::make_unique<ImageManager>(this);
+ std::unique_ptr<ImageManager> mImageManager;
};
} // namespace gl
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index 383486b..58d6caa 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -38,6 +38,7 @@
}
GLFramebuffer::~GLFramebuffer() {
+ setNativeWindowBuffer(nullptr, false, false);
glDeleteFramebuffers(1, &mFramebufferName);
glDeleteTextures(1, &mTextureName);
}
diff --git a/libs/renderengine/gl/Program.cpp b/libs/renderengine/gl/Program.cpp
index a172c56..26f6166 100644
--- a/libs/renderengine/gl/Program.cpp
+++ b/libs/renderengine/gl/Program.cpp
@@ -82,6 +82,14 @@
}
}
+Program::~Program() {
+ glDetachShader(mProgram, mVertexShader);
+ glDetachShader(mProgram, mFragmentShader);
+ glDeleteShader(mVertexShader);
+ glDeleteShader(mFragmentShader);
+ glDeleteProgram(mProgram);
+}
+
bool Program::isValid() const {
return mInitialized;
}
diff --git a/libs/renderengine/gl/Program.h b/libs/renderengine/gl/Program.h
index 4292645..41f1bf8 100644
--- a/libs/renderengine/gl/Program.h
+++ b/libs/renderengine/gl/Program.h
@@ -54,7 +54,7 @@
};
Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment);
- ~Program() = default;
+ ~Program();
/* whether this object is usable */
bool isValid() const;
diff --git a/libs/renderengine/gl/ProgramCache.h b/libs/renderengine/gl/ProgramCache.h
index 37bb651..535d21c 100644
--- a/libs/renderengine/gl/ProgramCache.h
+++ b/libs/renderengine/gl/ProgramCache.h
@@ -203,6 +203,8 @@
// if none can be found.
void useProgram(const EGLContext context, const Description& description);
+ void purgeCaches() { mCaches.clear(); }
+
private:
// compute a cache Key from a Description
static Key computeKey(const Description& description);
diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp
new file mode 100644
index 0000000..d126c27
--- /dev/null
+++ b/libs/renderengine/skia/AutoBackendTexture.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2020 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 "AutoBackendTexture.h"
+
+#undef LOG_TAG
+#define LOG_TAG "RenderEngine"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <utils/Trace.h>
+
+#include "log/log_main.h"
+#include "utils/Trace.h"
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+// Converts an android dataspace to a supported SkColorSpace
+// Supported dataspaces are
+// 1. sRGB
+// 2. Display P3
+// 3. BT2020 PQ
+// 4. BT2020 HLG
+// Unknown primaries are mapped to BT709, and unknown transfer functions
+// are mapped to sRGB.
+static sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
+ skcms_Matrix3x3 gamut;
+ switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
+ case HAL_DATASPACE_STANDARD_BT709:
+ gamut = SkNamedGamut::kSRGB;
+ break;
+ case HAL_DATASPACE_STANDARD_BT2020:
+ gamut = SkNamedGamut::kRec2020;
+ break;
+ case HAL_DATASPACE_STANDARD_DCI_P3:
+ gamut = SkNamedGamut::kDisplayP3;
+ break;
+ default:
+ ALOGV("Unsupported Gamut: %d, defaulting to sRGB", dataspace);
+ gamut = SkNamedGamut::kSRGB;
+ break;
+ }
+
+ switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_LINEAR:
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
+ case HAL_DATASPACE_TRANSFER_SRGB:
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut);
+ case HAL_DATASPACE_TRANSFER_HLG:
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut);
+ default:
+ ALOGV("Unsupported Gamma: %d, defaulting to sRGB transfer", dataspace);
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
+ }
+}
+
+AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer,
+ bool isRender) {
+ AHardwareBuffer_Desc desc;
+ AHardwareBuffer_describe(buffer, &desc);
+ bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
+ GrBackendFormat backendFormat =
+ GrAHardwareBufferUtils::GetBackendFormat(context, buffer, desc.format, false);
+ mBackendTexture =
+ GrAHardwareBufferUtils::MakeBackendTexture(context, buffer, desc.width, desc.height,
+ &mDeleteProc, &mUpdateProc, &mImageCtx,
+ createProtectedImage, backendFormat,
+ isRender);
+ mColorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
+}
+
+void AutoBackendTexture::unref(bool releaseLocalResources) {
+ if (releaseLocalResources) {
+ mSurface = nullptr;
+ mImage = nullptr;
+ }
+
+ mUsageCount--;
+ if (mUsageCount <= 0) {
+ if (mBackendTexture.isValid()) {
+ mDeleteProc(mImageCtx);
+ mBackendTexture = {};
+ }
+ delete this;
+ }
+}
+
+// releaseSurfaceProc is invoked by SkSurface, when the texture is no longer in use.
+// "releaseContext" contains an "AutoBackendTexture*".
+void AutoBackendTexture::releaseSurfaceProc(SkSurface::ReleaseContext releaseContext) {
+ AutoBackendTexture* textureRelease = reinterpret_cast<AutoBackendTexture*>(releaseContext);
+ textureRelease->unref(false);
+}
+
+// releaseImageProc is invoked by SkImage, when the texture is no longer in use.
+// "releaseContext" contains an "AutoBackendTexture*".
+void AutoBackendTexture::releaseImageProc(SkImage::ReleaseContext releaseContext) {
+ AutoBackendTexture* textureRelease = reinterpret_cast<AutoBackendTexture*>(releaseContext);
+ textureRelease->unref(false);
+}
+
+sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaType alphaType,
+ GrDirectContext* context) {
+ ATRACE_CALL();
+
+ if (mBackendTexture.isValid()) {
+ mUpdateProc(mImageCtx, context);
+ }
+
+ sk_sp<SkImage> image =
+ SkImage::MakeFromTexture(context, mBackendTexture, kTopLeft_GrSurfaceOrigin, mColorType,
+ alphaType, toSkColorSpace(dataspace), releaseImageProc, this);
+ if (image.get()) {
+ // The following ref will be counteracted by releaseProc, when SkImage is discarded.
+ ref();
+ }
+
+ mImage = image;
+ mDataspace = dataspace;
+ LOG_ALWAYS_FATAL_IF(mImage == nullptr, "Unable to generate SkImage from buffer");
+ return mImage;
+}
+
+sk_sp<SkSurface> AutoBackendTexture::getOrCreateSurface(ui::Dataspace dataspace,
+ GrDirectContext* context) {
+ ATRACE_CALL();
+ if (!mSurface.get() || mDataspace != dataspace) {
+ sk_sp<SkSurface> surface =
+ SkSurface::MakeFromBackendTexture(context, mBackendTexture,
+ kTopLeft_GrSurfaceOrigin, 0, mColorType,
+ toSkColorSpace(dataspace), nullptr,
+ releaseSurfaceProc, this);
+ if (surface.get()) {
+ // The following ref will be counteracted by releaseProc, when SkSurface is discarded.
+ ref();
+ }
+ mSurface = surface;
+ }
+
+ mDataspace = dataspace;
+ LOG_ALWAYS_FATAL_IF(mSurface == nullptr, "Unable to generate SkSurface");
+ return mSurface;
+}
+
+} // namespace skia
+} // namespace renderengine
+} // namespace android
\ No newline at end of file
diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h
new file mode 100644
index 0000000..30f4b77
--- /dev/null
+++ b/libs/renderengine/skia/AutoBackendTexture.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <GrAHardwareBufferUtils.h>
+#include <GrDirectContext.h>
+#include <SkImage.h>
+#include <SkSurface.h>
+#include <sys/types.h>
+
+#include "android-base/macros.h"
+#include "ui/GraphicTypes.h"
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+/**
+ * AutoBackendTexture manages GPU image lifetime. It is a ref-counted object
+ * that keeps GPU resources alive until the last SkImage or SkSurface object using them is
+ * destroyed.
+ */
+class AutoBackendTexture {
+public:
+ // Local reference that supports RAII-style management of an AutoBackendTexture
+ // AutoBackendTexture by itself can't be managed in a similar fashion because
+ // of shared ownership with Skia objects, so we wrap it here instead.
+ class LocalRef {
+ public:
+ LocalRef() {}
+
+ ~LocalRef() {
+ // Destroying the texture is the same as setting it to null
+ setTexture(nullptr);
+ }
+
+ // Sets the texture to locally ref-track.
+ void setTexture(AutoBackendTexture* texture) {
+ if (mTexture != nullptr) {
+ mTexture->unref(true);
+ }
+
+ mTexture = texture;
+ if (mTexture != nullptr) {
+ mTexture->ref();
+ }
+ }
+
+ AutoBackendTexture* getTexture() const { return mTexture; }
+
+ DISALLOW_COPY_AND_ASSIGN(LocalRef);
+
+ private:
+ AutoBackendTexture* mTexture = nullptr;
+ };
+
+ // Creates a GrBackendTexture whose contents come from the provided buffer.
+ AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isRender);
+
+ void ref() { mUsageCount++; }
+
+ // releaseLocalResources is true if the underlying SkImage and SkSurface
+ // should be deleted from local tracking.
+ void unref(bool releaseLocalResources);
+
+ // Makes a new SkImage from the texture content.
+ // As SkImages are immutable but buffer content is not, we create
+ // a new SkImage every time.
+ sk_sp<SkImage> makeImage(ui::Dataspace dataspace, SkAlphaType alphaType,
+ GrDirectContext* context);
+
+ // Makes a new SkSurface from the texture content, if needed.
+ sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace, GrDirectContext* context);
+
+private:
+ // The only way to invoke dtor is with unref, when mUsageCount is 0.
+ ~AutoBackendTexture() {}
+
+ GrBackendTexture mBackendTexture;
+ GrAHardwareBufferUtils::DeleteImageProc mDeleteProc;
+ GrAHardwareBufferUtils::UpdateImageProc mUpdateProc;
+ GrAHardwareBufferUtils::TexImageCtx mImageCtx;
+
+ static void releaseSurfaceProc(SkSurface::ReleaseContext releaseContext);
+ static void releaseImageProc(SkImage::ReleaseContext releaseContext);
+
+ int mUsageCount = 0;
+
+ sk_sp<SkImage> mImage = nullptr;
+ sk_sp<SkSurface> mSurface = nullptr;
+ ui::Dataspace mDataspace = ui::Dataspace::UNKNOWN;
+ SkColorType mColorType = kUnknown_SkColorType;
+};
+
+} // namespace skia
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 579260b..a0660fb 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -16,8 +16,10 @@
//#define LOG_NDEBUG 0
#include <cstdint>
+#include <memory>
#include "SkImageInfo.h"
+#include "log/log_main.h"
#include "system/graphics-base-v1.0.h"
#undef LOG_TAG
#define LOG_TAG "RenderEngine"
@@ -145,47 +147,6 @@
return err;
}
-// Converts an android dataspace to a supported SkColorSpace
-// Supported dataspaces are
-// 1. sRGB
-// 2. Display P3
-// 3. BT2020 PQ
-// 4. BT2020 HLG
-// Unknown primaries are mapped to BT709, and unknown transfer functions
-// are mapped to sRGB.
-static sk_sp<SkColorSpace> toColorSpace(ui::Dataspace dataspace) {
- skcms_Matrix3x3 gamut;
- switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
- case HAL_DATASPACE_STANDARD_BT709:
- gamut = SkNamedGamut::kSRGB;
- break;
- case HAL_DATASPACE_STANDARD_BT2020:
- gamut = SkNamedGamut::kRec2020;
- break;
- case HAL_DATASPACE_STANDARD_DCI_P3:
- gamut = SkNamedGamut::kDisplayP3;
- break;
- default:
- ALOGV("Unsupported Gamut: %d, defaulting to sRGB", dataspace);
- gamut = SkNamedGamut::kSRGB;
- break;
- }
-
- switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
- case HAL_DATASPACE_TRANSFER_LINEAR:
- return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
- case HAL_DATASPACE_TRANSFER_SRGB:
- return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
- case HAL_DATASPACE_TRANSFER_ST2084:
- return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut);
- case HAL_DATASPACE_TRANSFER_HLG:
- return SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut);
- default:
- ALOGV("Unsupported Gamma: %d, defaulting to sRGB transfer", dataspace);
- return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
- }
-}
-
std::unique_ptr<SkiaGLRenderEngine> SkiaGLRenderEngine::create(
const RenderEngineCreationArgs& args) {
// initialize EGL for the default display
@@ -455,9 +416,15 @@
sourceTransfer != destTransfer;
}
+static bool needsLinearEffect(const mat4& colorTransform, ui::Dataspace sourceDataspace,
+ ui::Dataspace destinationDataspace) {
+ return colorTransform != mat4() || needsToneMapping(sourceDataspace, destinationDataspace);
+}
+
void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
std::lock_guard<std::mutex> lock(mRenderingMutex);
- mImageCache.erase(bufferId);
+ mTextureCache.erase(bufferId);
+ mProtectedTextureCache.erase(bufferId);
}
status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
@@ -486,36 +453,36 @@
}
auto grContext = mInProtectedContext ? mProtectedGrContext : mGrContext;
- auto& cache = mInProtectedContext ? mProtectedSurfaceCache : mSurfaceCache;
+ auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache;
AHardwareBuffer_Desc bufferDesc;
AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc);
LOG_ALWAYS_FATAL_IF(!hasUsage(bufferDesc, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE),
"missing usage");
- sk_sp<SkSurface> surface;
+ std::shared_ptr<AutoBackendTexture::LocalRef> surfaceTextureRef = nullptr;
if (useFramebufferCache) {
auto iter = cache.find(buffer->getId());
if (iter != cache.end()) {
ALOGV("Cache hit!");
- surface = iter->second;
+ surfaceTextureRef = iter->second;
}
}
- if (!surface) {
- surface = SkSurface::MakeFromAHardwareBuffer(grContext.get(), buffer->toAHardwareBuffer(),
- GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
- mUseColorManagement
- ? toColorSpace(display.outputDataspace)
- : SkColorSpace::MakeSRGB(),
- nullptr);
- if (useFramebufferCache && surface) {
+
+ if (surfaceTextureRef == nullptr || surfaceTextureRef->getTexture() == nullptr) {
+ surfaceTextureRef = std::make_shared<AutoBackendTexture::LocalRef>();
+ surfaceTextureRef->setTexture(
+ new AutoBackendTexture(mGrContext.get(), buffer->toAHardwareBuffer(), true));
+ if (useFramebufferCache) {
ALOGD("Adding to cache");
- cache.insert({buffer->getId(), surface});
+ cache.insert({buffer->getId(), surfaceTextureRef});
}
}
- if (!surface) {
- ALOGE("Failed to make surface");
- return BAD_VALUE;
- }
+
+ sk_sp<SkSurface> surface =
+ surfaceTextureRef->getTexture()->getOrCreateSurface(mUseColorManagement
+ ? display.outputDataspace
+ : ui::Dataspace::SRGB,
+ mGrContext.get());
auto canvas = surface->getCanvas();
// Clear the entire canvas with a transparent black to prevent ghost images.
@@ -586,28 +553,37 @@
const auto& item = layer->source.buffer;
const auto bufferWidth = item.buffer->getBounds().width();
const auto bufferHeight = item.buffer->getBounds().height();
- sk_sp<SkImage> image;
- auto iter = mImageCache.find(item.buffer->getId());
- if (iter != mImageCache.end()) {
- image = iter->second;
+ std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef = nullptr;
+ auto iter = mTextureCache.find(item.buffer->getId());
+ if (iter != mTextureCache.end()) {
+ imageTextureRef = iter->second;
} else {
- image = SkImage::MakeFromAHardwareBuffer(
- item.buffer->toAHardwareBuffer(),
- item.isOpaque ? kOpaque_SkAlphaType
- : (item.usePremultipliedAlpha ? kPremul_SkAlphaType
- : kUnpremul_SkAlphaType),
- mUseColorManagement
- ? (needsToneMapping(layer->sourceDataspace, display.outputDataspace)
- // If we need to map to linear space, then
- // mark the source image with the same
- // colorspace as the destination surface so
- // that Skia's color management is a no-op.
- ? toColorSpace(display.outputDataspace)
- : toColorSpace(layer->sourceDataspace))
- : SkColorSpace::MakeSRGB());
- mImageCache.insert({item.buffer->getId(), image});
+ imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>();
+ imageTextureRef->setTexture(new AutoBackendTexture(mGrContext.get(),
+ item.buffer->toAHardwareBuffer(),
+ false));
+ mTextureCache.insert({buffer->getId(), imageTextureRef});
}
+ sk_sp<SkImage> image =
+ imageTextureRef->getTexture()
+ ->makeImage(mUseColorManagement
+ ? (needsLinearEffect(layer->colorTransform,
+ layer->sourceDataspace,
+ display.outputDataspace)
+ // If we need to map to linear space,
+ // then mark the source image with the
+ // same colorspace as the destination
+ // surface so that Skia's color
+ // management is a no-op.
+ ? display.outputDataspace
+ : layer->sourceDataspace)
+ : ui::Dataspace::SRGB,
+ item.isOpaque ? kOpaque_SkAlphaType
+ : (item.usePremultipliedAlpha
+ ? kPremul_SkAlphaType
+ : kUnpremul_SkAlphaType),
+ mGrContext.get());
SkMatrix matrix;
if (layer->geometry.roundedCornersRadius > 0) {
const auto roundedRect = getRoundedRect(layer);
@@ -664,13 +640,24 @@
}
if (mUseColorManagement &&
- needsToneMapping(layer->sourceDataspace, display.outputDataspace)) {
+ needsLinearEffect(layer->colorTransform, layer->sourceDataspace,
+ display.outputDataspace)) {
LinearEffect effect = LinearEffect{.inputDataspace = layer->sourceDataspace,
.outputDataspace = display.outputDataspace,
.undoPremultipliedAlpha = !item.isOpaque &&
item.usePremultipliedAlpha};
- sk_sp<SkRuntimeEffect> runtimeEffect = buildRuntimeEffect(effect);
+
+ auto effectIter = mRuntimeEffects.find(effect);
+ sk_sp<SkRuntimeEffect> runtimeEffect = nullptr;
+ if (effectIter == mRuntimeEffects.end()) {
+ runtimeEffect = buildRuntimeEffect(effect);
+ mRuntimeEffects.insert({effect, runtimeEffect});
+ } else {
+ runtimeEffect = effectIter->second;
+ }
+
paint.setShader(createLinearEffectShader(shader, effect, runtimeEffect,
+ layer->colorTransform,
display.maxLuminance,
layer->source.buffer.maxMasteringLuminance,
layer->source.buffer.maxContentLuminance));
@@ -921,10 +908,7 @@
return eglCreatePbufferSurface(display, placeholderConfig, attributes.data());
}
-void SkiaGLRenderEngine::cleanFramebufferCache() {
- mSurfaceCache.clear();
- mProtectedSurfaceCache.clear();
-}
+void SkiaGLRenderEngine::cleanFramebufferCache() {}
} // namespace skia
} // namespace renderengine
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 965cb41..f5eed1e 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -29,9 +29,13 @@
#include <mutex>
#include <unordered_map>
+#include "AutoBackendTexture.h"
#include "EGL/egl.h"
+#include "SkImageInfo.h"
#include "SkiaRenderEngine.h"
+#include "android-base/macros.h"
#include "filters/BlurFilter.h"
+#include "skia/filters/LinearEffect.h"
namespace android {
namespace renderengine {
@@ -92,8 +96,12 @@
const bool mUseColorManagement;
- // Cache of GL images that we'll store per GraphicBuffer ID
- std::unordered_map<uint64_t, sk_sp<SkImage>> mImageCache GUARDED_BY(mRenderingMutex);
+ // Cache of GL textures that we'll store per GraphicBuffer ID
+ std::unordered_map<uint64_t, std::shared_ptr<AutoBackendTexture::LocalRef>> mTextureCache
+ GUARDED_BY(mRenderingMutex);
+ std::unordered_map<uint64_t, std::shared_ptr<AutoBackendTexture::LocalRef>>
+ mProtectedTextureCache GUARDED_BY(mRenderingMutex);
+ std::unordered_map<LinearEffect, sk_sp<SkRuntimeEffect>, LinearEffectHasher> mRuntimeEffects;
// Mutex guarding rendering operations, so that:
// 1. GL operations aren't interleaved, and
// 2. Internal state related to rendering that is potentially modified by
@@ -107,8 +115,6 @@
// Same as above, but for protected content (eg. DRM)
sk_sp<GrDirectContext> mProtectedGrContext;
- std::unordered_map<uint64_t, sk_sp<SkSurface>> mSurfaceCache;
- std::unordered_map<uint64_t, sk_sp<SkSurface>> mProtectedSurfaceCache;
bool mInProtectedContext = false;
};
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 376abdf..7680649 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -16,12 +16,16 @@
#include "LinearEffect.h"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
#include <SkString.h>
+#include <utils/Trace.h>
#include <optional>
#include "log/log.h"
#include "math/mat4.h"
+#include "system/graphics-base-v1.0.h"
#include "ui/ColorSpace.h"
namespace android {
@@ -46,6 +50,30 @@
}
)");
break;
+ case HAL_DATASPACE_TRANSFER_HLG:
+ shader.append(R"(
+ float EOTF_channel(float channel) {
+ const float a = 0.17883277;
+ const float b = 0.28466892;
+ const float c = 0.55991073;
+ return channel <= 0.5 ? channel * channel / 3.0 :
+ (exp((channel - c) / a) + b) / 12.0;
+ }
+
+ float3 EOTF(float3 color) {
+ return float3(EOTF_channel(color.r), EOTF_channel(color.g),
+ EOTF_channel(color.b));
+ }
+ )");
+ break;
+ case HAL_DATASPACE_TRANSFER_LINEAR:
+ shader.append(R"(
+ float3 EOTF(float3 color) {
+ return color;
+ }
+ )");
+ break;
+ case HAL_DATASPACE_TRANSFER_SRGB:
default:
shader.append(R"(
@@ -79,13 +107,8 @@
)");
}
-static void generateOOTF(ui::Dataspace inputDataspace, ui::Dataspace outputDataspace,
- SkString& shader) {
- shader.append(R"(
- uniform float in_displayMaxLuminance;
- uniform float in_inputMaxLuminance;
- uniform float in_maxContentLuminance;
- )");
+// Conversion from relative light to absolute light (maps from [0, 1] to [0, maxNits])
+static void generateLuminanceScalesForOOTF(ui::Dataspace inputDataspace, SkString& shader) {
switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
case HAL_DATASPACE_TRANSFER_ST2084:
shader.append(R"(
@@ -93,9 +116,50 @@
return xyz * 10000.0;
}
)");
+ break;
+ case HAL_DATASPACE_TRANSFER_HLG:
+ shader.append(R"(
+ float3 ScaleLuminance(float3 xyz) {
+ return xyz * 1000.0 * pow(xyz.y, 0.2);
+ }
+ )");
+ break;
+ default:
+ shader.append(R"(
+ float3 ScaleLuminance(float3 xyz) {
+ return xyz * in_displayMaxLuminance;
+ }
+ )");
+ break;
+ }
+}
+static void generateToneMapInterpolation(ui::Dataspace inputDataspace,
+ ui::Dataspace outputDataspace, SkString& shader) {
+ switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ case HAL_DATASPACE_TRANSFER_HLG:
switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ shader.append(R"(
+ float3 ToneMap(float3 xyz) {
+ return xyz;
+ }
+ )");
+ break;
+ case HAL_DATASPACE_TRANSFER_HLG:
+ // PQ has a wider luminance range (10,000 nits vs. 1,000 nits) than HLG, so
+ // we'll clamp the luminance range in case we're mapping from PQ input to HLG
+ // output.
+ shader.append(R"(
+ float3 ToneMap(float3 xyz) {
+ return clamp(xyz, 0.0, 1000.0);
+ }
+ )");
+ break;
default:
+ // Here we're mapping from HDR to SDR content, so interpolate using a Hermitian
+ // polynomial onto the smaller luminance range.
shader.append(R"(
float3 ToneMap(float3 xyz) {
float maxInLumi = in_inputMaxLuminance;
@@ -155,18 +219,70 @@
}
break;
default:
- shader.append(R"(
- float3 ScaleLuminance(float3 xyz) {
- return xyz * in_displayMaxLuminance;
- }
+ switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ case HAL_DATASPACE_TRANSFER_HLG:
+ // Map from SDR onto an HDR output buffer
+ // Here we use a polynomial curve to map from [0, displayMaxLuminance] onto
+ // [0, maxOutLumi] which is hard-coded to be 3000 nits.
+ shader.append(R"(
+ float3 ToneMap(float3 xyz) {
+ const float maxOutLumi = 3000.0;
- float3 ToneMap(float3 xyz) {
- return xyz;
- }
- )");
+ const float x0 = 5.0;
+ const float y0 = 2.5;
+ float x1 = in_displayMaxLuminance * 0.7;
+ float y1 = maxOutLumi * 0.15;
+ float x2 = in_displayMaxLuminance * 0.9;
+ float y2 = maxOutLumi * 0.45;
+ float x3 = in_displayMaxLuminance;
+ float y3 = maxOutLumi;
+
+ float c1 = y1 / 3.0;
+ float c2 = y2 / 2.0;
+ float c3 = y3 / 1.5;
+
+ float nits = xyz.y;
+
+ if (nits <= x0) {
+ // scale [0.0, x0] to [0.0, y0] linearly
+ float slope = y0 / x0;
+ return xyz * slope;
+ } else if (nits <= x1) {
+ // scale [x0, x1] to [y0, y1] using a curve
+ float t = (nits - x0) / (x1 - x0);
+ nits = (1.0 - t) * (1.0 - t) * y0 + 2.0 * (1.0 - t) * t * c1 + t * t * y1;
+ } else if (nits <= x2) {
+ // scale [x1, x2] to [y1, y2] using a curve
+ float t = (nits - x1) / (x2 - x1);
+ nits = (1.0 - t) * (1.0 - t) * y1 + 2.0 * (1.0 - t) * t * c2 + t * t * y2;
+ } else {
+ // scale [x2, x3] to [y2, y3] using a curve
+ float t = (nits - x2) / (x3 - x2);
+ nits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 + t * t * y3;
+ }
+
+ // xyz.y is greater than x0 and is thus non-zero
+ return xyz * (nits / xyz.y);
+ }
+ )");
+ break;
+ default:
+ // For completeness, this is tone-mapping from SDR to SDR, where this is just a
+ // no-op.
+ shader.append(R"(
+ float3 ToneMap(float3 xyz) {
+ return xyz;
+ }
+ )");
+ break;
+ }
break;
}
+}
+// Normalizes from absolute light back to relative light (maps from [0, maxNits] back to [0, 1])
+static void generateLuminanceNormalizationForOOTF(ui::Dataspace outputDataspace, SkString& shader) {
switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
case HAL_DATASPACE_TRANSFER_ST2084:
shader.append(R"(
@@ -175,6 +291,13 @@
}
)");
break;
+ case HAL_DATASPACE_TRANSFER_HLG:
+ shader.append(R"(
+ float3 NormalizeLuminance(float3 xyz) {
+ return xyz / 1000.0 * pow(xyz.y / 1000.0, -0.2 / 1.2);
+ }
+ )");
+ break;
default:
shader.append(R"(
float3 NormalizeLuminance(float3 xyz) {
@@ -183,6 +306,19 @@
)");
break;
}
+}
+
+static void generateOOTF(ui::Dataspace inputDataspace, ui::Dataspace outputDataspace,
+ SkString& shader) {
+ // Input uniforms
+ shader.append(R"(
+ uniform float in_displayMaxLuminance;
+ uniform float in_inputMaxLuminance;
+ )");
+
+ generateLuminanceScalesForOOTF(inputDataspace, shader);
+ generateToneMapInterpolation(inputDataspace, outputDataspace, shader);
+ generateLuminanceNormalizationForOOTF(outputDataspace, shader);
shader.append(R"(
float3 OOTF(float3 xyz) {
@@ -209,6 +345,30 @@
}
)");
break;
+ case HAL_DATASPACE_TRANSFER_HLG:
+ shader.append(R"(
+ float OETF_channel(float channel) {
+ const float a = 0.17883277;
+ const float b = 0.28466892;
+ const float c = 0.55991073;
+ return channel <= 1.0 / 12.0 ? sqrt(3.0 * channel) :
+ a * log(12.0 * channel - b) + c;
+ }
+
+ float3 OETF(float3 linear) {
+ return float3(OETF_channel(linear.r), OETF_channel(linear.g),
+ OETF_channel(linear.b));
+ }
+ )");
+ break;
+ case HAL_DATASPACE_TRANSFER_LINEAR:
+ shader.append(R"(
+ float3 OETF(float3 linear) {
+ return linear;
+ }
+ )");
+ break;
+ case HAL_DATASPACE_TRANSFER_SRGB:
default:
shader.append(R"(
float OETF_sRGB(float linear) {
@@ -270,6 +430,7 @@
}
sk_sp<SkRuntimeEffect> buildRuntimeEffect(const LinearEffect& linearEffect) {
+ ATRACE_CALL();
SkString shaderString;
generateEOTF(linearEffect.inputDataspace, shaderString);
generateXYZTransforms(shaderString);
@@ -286,8 +447,9 @@
sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> shader, const LinearEffect& linearEffect,
sk_sp<SkRuntimeEffect> runtimeEffect,
- float maxDisplayLuminance, float maxMasteringLuminance,
- float maxContentLuminance) {
+ const mat4& colorTransform, float maxDisplayLuminance,
+ float maxMasteringLuminance, float maxContentLuminance) {
+ ATRACE_CALL();
SkRuntimeShaderBuilder effectBuilder(runtimeEffect);
effectBuilder.child("input") = shader;
@@ -296,7 +458,7 @@
ColorSpace outputColorSpace = toColorSpace(linearEffect.outputDataspace);
effectBuilder.uniform("in_rgbToXyz") = mat4(inputColorSpace.getRGBtoXYZ());
- effectBuilder.uniform("in_xyzToRgb") = mat4(outputColorSpace.getXYZtoRGB());
+ effectBuilder.uniform("in_xyzToRgb") = colorTransform * mat4(outputColorSpace.getXYZtoRGB());
effectBuilder.uniform("in_displayMaxLuminance") = maxDisplayLuminance;
effectBuilder.uniform("in_inputMaxLuminance") =
std::min(maxMasteringLuminance, maxContentLuminance);
diff --git a/libs/renderengine/skia/filters/LinearEffect.h b/libs/renderengine/skia/filters/LinearEffect.h
index 2615669..20b8338 100644
--- a/libs/renderengine/skia/filters/LinearEffect.h
+++ b/libs/renderengine/skia/filters/LinearEffect.h
@@ -16,9 +16,10 @@
#pragma once
+#include <math/mat4.h>
+
#include <optional>
-#include "SkColorMatrix.h"
#include "SkRuntimeEffect.h"
#include "SkShader.h"
#include "ui/GraphicTypes.h"
@@ -63,11 +64,31 @@
const bool undoPremultipliedAlpha = false;
};
+static inline bool operator==(const LinearEffect& lhs, const LinearEffect& rhs) {
+ return lhs.inputDataspace == rhs.inputDataspace && lhs.outputDataspace == rhs.outputDataspace &&
+ lhs.undoPremultipliedAlpha == rhs.undoPremultipliedAlpha;
+}
+
+struct LinearEffectHasher {
+ // Inspired by art/runtime/class_linker.cc
+ // Also this is what boost:hash_combine does
+ static size_t HashCombine(size_t seed, size_t val) {
+ return seed ^ (val + 0x9e3779b9 + (seed << 6) + (seed >> 2));
+ }
+ size_t operator()(const LinearEffect& le) const {
+ size_t result = std::hash<ui::Dataspace>{}(le.inputDataspace);
+ result = HashCombine(result, std::hash<ui::Dataspace>{}(le.outputDataspace));
+ return HashCombine(result, std::hash<bool>{}(le.undoPremultipliedAlpha));
+ }
+};
+
sk_sp<SkRuntimeEffect> buildRuntimeEffect(const LinearEffect& linearEffect);
// Generates a shader resulting from applying the a linear effect created from
-// LinearEffectARgs::buildEffect to an inputShader. We also provide additional HDR metadata upon
-// creating the shader:
+// LinearEffectArgs::buildEffect to an inputShader.
+// Optionally, a color transform may also be provided, which combines with the
+// matrix transforming from linear XYZ to linear RGB immediately before OETF.
+// We also provide additional HDR metadata upon creating the shader:
// * The max display luminance is the max luminance of the physical display in nits
// * The max mastering luminance is provided as the max luminance from the SMPTE 2086
// standard.
@@ -76,8 +97,8 @@
sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> inputShader,
const LinearEffect& linearEffect,
sk_sp<SkRuntimeEffect> runtimeEffect,
- float maxDisplayLuminance, float maxMasteringLuminance,
- float maxContentLuminance);
+ const mat4& colorTransform, float maxDisplayLuminance,
+ float maxMasteringLuminance, float maxContentLuminance);
} // namespace skia
} // namespace renderengine
} // namespace android
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index d20fcc4..3dcbf08 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#undef LOG_TAG
+#define LOG_TAG "RenderEngineTest"
+
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
@@ -37,8 +40,19 @@
namespace android {
-struct RenderEngineTest : public ::testing::Test {
- static void SetUpTestSuite() {
+class RenderEngineFactory {
+public:
+ virtual ~RenderEngineFactory() = default;
+
+ virtual std::string name() = 0;
+ virtual std::unique_ptr<renderengine::gl::GLESRenderEngine> createRenderEngine() = 0;
+};
+
+class GLESRenderEngineFactory : public RenderEngineFactory {
+public:
+ std::string name() override { return "GLESRenderEngineFactory"; }
+
+ std::unique_ptr<renderengine::gl::GLESRenderEngine> createRenderEngine() override {
renderengine::RenderEngineCreationArgs reCreationArgs =
renderengine::RenderEngineCreationArgs::Builder()
.setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
@@ -50,20 +64,12 @@
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
.setRenderEngineType(renderengine::RenderEngine::RenderEngineType::GLES)
.build();
- sRE = renderengine::gl::GLESRenderEngine::create(reCreationArgs);
-
- reCreationArgs.useColorManagement = true;
- sRECM = renderengine::gl::GLESRenderEngine::create(reCreationArgs);
+ return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
}
+};
- static void TearDownTestSuite() {
- // The ordering here is important - sCurrentBuffer must live longer
- // than RenderEngine to avoid a null reference on tear-down.
- sRE = nullptr;
- sRECM = nullptr;
- sCurrentBuffer = nullptr;
- }
-
+class RenderEngineTest : public ::testing::TestWithParam<std::shared_ptr<RenderEngineFactory>> {
+public:
static sp<GraphicBuffer> allocateDefaultBuffer() {
return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
HAL_PIXEL_FORMAT_RGBA_8888, 1,
@@ -80,19 +86,24 @@
"input");
}
- RenderEngineTest() { mBuffer = allocateDefaultBuffer(); }
+ RenderEngineTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+ mBuffer = allocateDefaultBuffer();
+ }
~RenderEngineTest() {
if (WRITE_BUFFER_TO_FILE_ON_FAILURE && ::testing::Test::HasFailure()) {
writeBufferToFile("/data/texture_out_");
}
for (uint32_t texName : mTexNames) {
- sRE->deleteTextures(1, &texName);
- EXPECT_FALSE(sRE->isTextureNameKnownForTesting(texName));
+ mRE->deleteTextures(1, &texName);
+ EXPECT_FALSE(mRE->isTextureNameKnownForTesting(texName));
}
- for (uint32_t texName : mTexNamesCM) {
- sRECM->deleteTextures(1, &texName);
- }
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
void writeBufferToFile(const char* basename) {
@@ -261,12 +272,11 @@
void invokeDraw(renderengine::DisplaySettings settings,
std::vector<const renderengine::LayerSettings*> layers,
- sp<GraphicBuffer> buffer, bool useColorManagement = false) {
+ sp<GraphicBuffer> buffer) {
base::unique_fd fence;
- status_t status = useColorManagement
- ? sRECM->drawLayers(settings, layers, buffer, true, base::unique_fd(), &fence)
- : sRE->drawLayers(settings, layers, buffer, true, base::unique_fd(), &fence);
- sCurrentBuffer = buffer;
+ status_t status =
+ mRE->drawLayers(settings, layers, buffer, true, base::unique_fd(), &fence);
+ mCurrentBuffer = buffer;
int fd = fence.release();
if (fd >= 0) {
@@ -276,11 +286,7 @@
ASSERT_EQ(NO_ERROR, status);
if (layers.size() > 0) {
- if (useColorManagement) {
- ASSERT_TRUE(sRECM->isFramebufferImageCachedForTesting(buffer->getId()));
- } else {
- ASSERT_TRUE(sRE->isFramebufferImageCachedForTesting(buffer->getId()));
- }
+ ASSERT_TRUE(mRE->isFramebufferImageCachedForTesting(buffer->getId()));
}
}
@@ -335,15 +341,12 @@
void fillBufferLayerTransform();
template <typename SourceVariant>
- void fillBufferWithColorTransform(bool useColorManagement = false);
+ void fillBufferWithColorTransform();
template <typename SourceVariant>
void fillBufferColorTransform();
template <typename SourceVariant>
- void fillBufferColorTransformCM();
-
- template <typename SourceVariant>
void fillRedBufferWithRoundedCorners();
template <typename SourceVariant>
@@ -381,28 +384,21 @@
// Keep around the same renderengine object to save on initialization time.
// For now, exercise the GL backend directly so that some caching specifics
// can be tested without changing the interface.
- static std::unique_ptr<renderengine::gl::GLESRenderEngine> sRE;
- // renderengine object with Color Management enabled
- static std::unique_ptr<renderengine::gl::GLESRenderEngine> sRECM;
+ std::unique_ptr<renderengine::gl::GLESRenderEngine> mRE;
+
// Dumb hack to avoid NPE in the EGL driver: the GraphicBuffer needs to
// be freed *after* RenderEngine is destroyed, so that the EGL image is
// destroyed first.
- static sp<GraphicBuffer> sCurrentBuffer;
+ sp<GraphicBuffer> mCurrentBuffer;
sp<GraphicBuffer> mBuffer;
std::vector<uint32_t> mTexNames;
- std::vector<uint32_t> mTexNamesCM;
};
-std::unique_ptr<renderengine::gl::GLESRenderEngine> RenderEngineTest::sRE = nullptr;
-std::unique_ptr<renderengine::gl::GLESRenderEngine> RenderEngineTest::sRECM = nullptr;
-
-sp<GraphicBuffer> RenderEngineTest::sCurrentBuffer = nullptr;
-
struct ColorSourceVariant {
static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
- RenderEngineTest* /*fixture*/, bool /*useColorManagement*/ = false) {
+ RenderEngineTest* /*fixture*/) {
layer.source.solidColor = half3(r, g, b);
}
};
@@ -430,16 +426,11 @@
template <typename OpaquenessVariant>
struct BufferSourceVariant {
static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
- RenderEngineTest* fixture, bool useColorManagement = false) {
+ RenderEngineTest* fixture) {
sp<GraphicBuffer> buf = RenderEngineTest::allocateSourceBuffer(1, 1);
uint32_t texName;
- if (useColorManagement) {
- fixture->sRECM->genTextures(1, &texName);
- fixture->mTexNamesCM.push_back(texName);
- } else {
- fixture->sRE->genTextures(1, &texName);
- fixture->mTexNames.push_back(texName);
- }
+ fixture->mRE->genTextures(1, &texName);
+ fixture->mTexNames.push_back(texName);
uint8_t* pixels;
buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -669,7 +660,7 @@
}
template <typename SourceVariant>
-void RenderEngineTest::fillBufferWithColorTransform(bool useColorManagement) {
+void RenderEngineTest::fillBufferWithColorTransform() {
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
settings.clip = Rect(1, 1);
@@ -678,7 +669,7 @@
renderengine::LayerSettings layer;
layer.geometry.boundaries = Rect(1, 1).toFloatRect();
- SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this, useColorManagement);
+ SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
layer.alpha = 1.0f;
// construct a fake color matrix
@@ -692,7 +683,7 @@
layers.push_back(&layer);
- invokeDraw(settings, layers, mBuffer, useColorManagement);
+ invokeDraw(settings, layers, mBuffer);
}
template <typename SourceVariant>
@@ -702,12 +693,6 @@
}
template <typename SourceVariant>
-void RenderEngineTest::fillBufferColorTransformCM() {
- fillBufferWithColorTransform<SourceVariant>(true);
- expectBufferColor(fullscreenRect(), 126, 0, 0, 255, 1);
-}
-
-template <typename SourceVariant>
void RenderEngineTest::fillRedBufferWithRoundedCorners() {
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
@@ -838,7 +823,7 @@
// coordinates so that only the upper left is applied.
sp<GraphicBuffer> buf = allocateSourceBuffer(2, 2);
uint32_t texName;
- RenderEngineTest::sRE->genTextures(1, &texName);
+ RenderEngineTest::mRE->genTextures(1, &texName);
this->mTexNames.push_back(texName);
uint8_t* pixels;
@@ -887,7 +872,7 @@
renderengine::LayerSettings layer;
sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
uint32_t texName;
- RenderEngineTest::sRE->genTextures(1, &texName);
+ RenderEngineTest::mRE->genTextures(1, &texName);
this->mTexNames.push_back(texName);
uint8_t* pixels;
@@ -926,7 +911,7 @@
renderengine::LayerSettings layer;
sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
uint32_t texName;
- RenderEngineTest::sRE->genTextures(1, &texName);
+ RenderEngineTest::mRE->genTextures(1, &texName);
this->mTexNames.push_back(texName);
uint8_t* pixels;
@@ -1010,11 +995,19 @@
invokeDraw(settings, layers, mBuffer);
}
-TEST_F(RenderEngineTest, drawLayers_noLayersToDraw) {
+INSTANTIATE_TEST_SUITE_P(PerRenderEngineType, RenderEngineTest,
+ testing::Values(std::make_shared<GLESRenderEngineFactory>()));
+
+TEST_P(RenderEngineTest, drawLayers_noLayersToDraw) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
drawEmptyLayers();
}
-TEST_F(RenderEngineTest, drawLayers_nullOutputBuffer) {
+TEST_P(RenderEngineTest, drawLayers_nullOutputBuffer) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
renderengine::DisplaySettings settings;
std::vector<const renderengine::LayerSettings*> layers;
renderengine::LayerSettings layer;
@@ -1022,12 +1015,15 @@
BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
layers.push_back(&layer);
base::unique_fd fence;
- status_t status = sRE->drawLayers(settings, layers, nullptr, true, base::unique_fd(), &fence);
+ status_t status = mRE->drawLayers(settings, layers, nullptr, true, base::unique_fd(), &fence);
ASSERT_EQ(BAD_VALUE, status);
}
-TEST_F(RenderEngineTest, drawLayers_nullOutputFence) {
+TEST_P(RenderEngineTest, drawLayers_nullOutputFence) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
settings.clip = fullscreenRect();
@@ -1039,13 +1035,16 @@
layer.alpha = 1.0;
layers.push_back(&layer);
- status_t status = sRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), nullptr);
- sCurrentBuffer = mBuffer;
+ status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), nullptr);
+ mCurrentBuffer = mBuffer;
ASSERT_EQ(NO_ERROR, status);
expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
}
-TEST_F(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) {
+TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
settings.clip = fullscreenRect();
@@ -1057,210 +1056,339 @@
layer.alpha = 1.0;
layers.push_back(&layer);
- status_t status = sRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd(), nullptr);
- sCurrentBuffer = mBuffer;
+ status_t status = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd(), nullptr);
+ mCurrentBuffer = mBuffer;
ASSERT_EQ(NO_ERROR, status);
- ASSERT_FALSE(sRE->isFramebufferImageCachedForTesting(mBuffer->getId()));
+ ASSERT_FALSE(mRE->isFramebufferImageCachedForTesting(mBuffer->getId()));
expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
}
-TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillRedBuffer<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillGreenBuffer<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBlueBuffer<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillRedTransparentBuffer<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferPhysicalOffset<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate0<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate90<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate180<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate270<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferLayerTransform<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferColorTransform<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransformCM_colorSource) {
- fillBufferColorTransformCM<ColorSourceVariant>();
-}
+TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
-TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
fillBufferWithRoundedCorners<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferAndBlurBackground<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_overlayCorners_colorSource) {
+TEST_P(RenderEngineTest, drawLayers_overlayCorners_colorSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
overlayCorners<ColorSourceVariant>();
}
-TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillRedBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillGreenBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBlueBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillRedTransparentBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferPhysicalOffset<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate0<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate90<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate180<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate270<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferColorTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransformCM_opaqueBufferSource) {
- fillBufferColorTransformCM<BufferSourceVariant<ForceOpaqueBufferVariant>>();
-}
+TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
-TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferAndBlurBackground<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_overlayCorners_opaqueBufferSource) {
+TEST_P(RenderEngineTest, drawLayers_overlayCorners_opaqueBufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
overlayCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillRedBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillGreenBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBlueBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillRedTransparentBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferPhysicalOffset<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate0<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate90<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate180<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferCheckersRotate270<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferColorTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransformCM_bufferSource) {
- fillBufferColorTransformCM<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
-}
+TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
-TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferAndBlurBackground<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_overlayCorners_bufferSource) {
+TEST_P(RenderEngineTest, drawLayers_overlayCorners_bufferSource) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
overlayCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
+TEST_P(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferTextureTransform();
}
-TEST_F(RenderEngineTest, drawLayers_fillBuffer_premultipliesAlpha) {
+TEST_P(RenderEngineTest, drawLayers_fillBuffer_premultipliesAlpha) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferWithPremultiplyAlpha();
}
-TEST_F(RenderEngineTest, drawLayers_fillBuffer_withoutPremultiplyingAlpha) {
+TEST_P(RenderEngineTest, drawLayers_fillBuffer_withoutPremultiplyingAlpha) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
fillBufferWithoutPremultiplyAlpha();
}
-TEST_F(RenderEngineTest, drawLayers_clearRegion) {
+TEST_P(RenderEngineTest, drawLayers_clearRegion) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
clearRegion();
}
-TEST_F(RenderEngineTest, drawLayers_fillsBufferAndCachesImages) {
+TEST_P(RenderEngineTest, drawLayers_fillsBufferAndCachesImages) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
settings.clip = fullscreenRect();
@@ -1274,21 +1402,24 @@
layers.push_back(&layer);
invokeDraw(settings, layers, mBuffer);
uint64_t bufferId = layer.source.buffer.buffer->getId();
- EXPECT_TRUE(sRE->isImageCachedForTesting(bufferId));
+ EXPECT_TRUE(mRE->isImageCachedForTesting(bufferId));
std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
- sRE->unbindExternalTextureBufferForTesting(bufferId);
+ mRE->unbindExternalTextureBufferForTesting(bufferId);
std::lock_guard<std::mutex> lock(barrier->mutex);
ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
[&]() REQUIRES(barrier->mutex) {
return barrier->isOpen;
}));
- EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
+ EXPECT_FALSE(mRE->isImageCachedForTesting(bufferId));
EXPECT_EQ(NO_ERROR, barrier->result);
}
-TEST_F(RenderEngineTest, cacheExternalBuffer_withNullBuffer) {
+TEST_P(RenderEngineTest, cacheExternalBuffer_withNullBuffer) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
- sRE->cacheExternalTextureBufferForTesting(nullptr);
+ mRE->cacheExternalTextureBufferForTesting(nullptr);
std::lock_guard<std::mutex> lock(barrier->mutex);
ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
[&]() REQUIRES(barrier->mutex) {
@@ -1298,11 +1429,14 @@
EXPECT_EQ(BAD_VALUE, barrier->result);
}
-TEST_F(RenderEngineTest, cacheExternalBuffer_cachesImages) {
+TEST_P(RenderEngineTest, cacheExternalBuffer_cachesImages) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
uint64_t bufferId = buf->getId();
std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
- sRE->cacheExternalTextureBufferForTesting(buf);
+ mRE->cacheExternalTextureBufferForTesting(buf);
{
std::lock_guard<std::mutex> lock(barrier->mutex);
ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
@@ -1311,8 +1445,8 @@
}));
EXPECT_EQ(NO_ERROR, barrier->result);
}
- EXPECT_TRUE(sRE->isImageCachedForTesting(bufferId));
- barrier = sRE->unbindExternalTextureBufferForTesting(bufferId);
+ EXPECT_TRUE(mRE->isImageCachedForTesting(bufferId));
+ barrier = mRE->unbindExternalTextureBufferForTesting(bufferId);
{
std::lock_guard<std::mutex> lock(barrier->mutex);
ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
@@ -1321,10 +1455,13 @@
}));
EXPECT_EQ(NO_ERROR, barrier->result);
}
- EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
+ EXPECT_FALSE(mRE->isImageCachedForTesting(bufferId));
}
-TEST_F(RenderEngineTest, drawLayers_fillShadow_casterLayerMinSize) {
+TEST_P(RenderEngineTest, drawLayers_fillShadow_casterLayerMinSize) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
const ubyte4 casterColor(255, 0, 0, 255);
const ubyte4 backgroundColor(255, 255, 255, 255);
const float shadowLength = 5.0f;
@@ -1341,7 +1478,10 @@
expectShadowColor(castingLayer, settings, casterColor, backgroundColor);
}
-TEST_F(RenderEngineTest, drawLayers_fillShadow_casterColorLayer) {
+TEST_P(RenderEngineTest, drawLayers_fillShadow_casterColorLayer) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
const ubyte4 casterColor(255, 0, 0, 255);
const ubyte4 backgroundColor(255, 255, 255, 255);
const float shadowLength = 5.0f;
@@ -1358,7 +1498,10 @@
expectShadowColor(castingLayer, settings, casterColor, backgroundColor);
}
-TEST_F(RenderEngineTest, drawLayers_fillShadow_casterOpaqueBufferLayer) {
+TEST_P(RenderEngineTest, drawLayers_fillShadow_casterOpaqueBufferLayer) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
const ubyte4 casterColor(255, 0, 0, 255);
const ubyte4 backgroundColor(255, 255, 255, 255);
const float shadowLength = 5.0f;
@@ -1376,7 +1519,10 @@
expectShadowColor(castingLayer, settings, casterColor, backgroundColor);
}
-TEST_F(RenderEngineTest, drawLayers_fillShadow_casterWithRoundedCorner) {
+TEST_P(RenderEngineTest, drawLayers_fillShadow_casterWithRoundedCorner) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
const ubyte4 casterColor(255, 0, 0, 255);
const ubyte4 backgroundColor(255, 255, 255, 255);
const float shadowLength = 5.0f;
@@ -1396,7 +1542,10 @@
expectShadowColor(castingLayer, settings, casterColor, backgroundColor);
}
-TEST_F(RenderEngineTest, drawLayers_fillShadow_translucentCasterWithAlpha) {
+TEST_P(RenderEngineTest, drawLayers_fillShadow_translucentCasterWithAlpha) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
const ubyte4 casterColor(255, 0, 0, 255);
const ubyte4 backgroundColor(255, 255, 255, 255);
const float shadowLength = 5.0f;
@@ -1421,7 +1570,10 @@
backgroundColor.a);
}
-TEST_F(RenderEngineTest, cleanupPostRender_cleansUpOnce) {
+TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
settings.clip = fullscreenRect();
@@ -1434,22 +1586,25 @@
layers.push_back(&layer);
base::unique_fd fenceOne;
- sRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fenceOne);
+ mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fenceOne);
base::unique_fd fenceTwo;
- sRE->drawLayers(settings, layers, mBuffer, true, std::move(fenceOne), &fenceTwo);
+ mRE->drawLayers(settings, layers, mBuffer, true, std::move(fenceOne), &fenceTwo);
const int fd = fenceTwo.get();
if (fd >= 0) {
sync_wait(fd, -1);
}
// Only cleanup the first time.
- EXPECT_TRUE(sRE->cleanupPostRender(
+ EXPECT_TRUE(mRE->cleanupPostRender(
renderengine::RenderEngine::CleanupMode::CLEAN_OUTPUT_RESOURCES));
- EXPECT_FALSE(sRE->cleanupPostRender(
+ EXPECT_FALSE(mRE->cleanupPostRender(
renderengine::RenderEngine::CleanupMode::CLEAN_OUTPUT_RESOURCES));
}
-TEST_F(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory) {
+TEST_P(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory) {
+ const auto& renderEngineFactory = GetParam();
+ mRE = renderEngineFactory->createRenderEngine();
+
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
settings.clip = fullscreenRect();
@@ -1462,7 +1617,7 @@
layers.push_back(&layer);
base::unique_fd fence;
- sRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence);
+ mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence);
const int fd = fence.get();
if (fd >= 0) {
@@ -1471,15 +1626,15 @@
uint64_t bufferId = layer.source.buffer.buffer->getId();
uint32_t texName = layer.source.buffer.textureName;
- EXPECT_TRUE(sRE->isImageCachedForTesting(bufferId));
- EXPECT_EQ(bufferId, sRE->getBufferIdForTextureNameForTesting(texName));
+ EXPECT_TRUE(mRE->isImageCachedForTesting(bufferId));
+ EXPECT_EQ(bufferId, mRE->getBufferIdForTextureNameForTesting(texName));
- EXPECT_TRUE(sRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL));
+ EXPECT_TRUE(mRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL));
// Now check that our view of memory is good.
- EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
- EXPECT_EQ(std::nullopt, sRE->getBufferIdForTextureNameForTesting(bufferId));
- EXPECT_TRUE(sRE->isTextureNameKnownForTesting(texName));
+ EXPECT_FALSE(mRE->isImageCachedForTesting(bufferId));
+ EXPECT_EQ(std::nullopt, mRE->getBufferIdForTextureNameForTesting(bufferId));
+ EXPECT_TRUE(mRE->isTextureNameKnownForTesting(texName));
}
} // namespace android
diff --git a/libs/vibrator/Android.bp b/libs/vibrator/Android.bp
index 1681fe2..49bc6bf 100644
--- a/libs/vibrator/Android.bp
+++ b/libs/vibrator/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_shared {
+cc_library {
name: "libvibrator",
vendor_available: true,
double_loadable: true,
@@ -47,4 +47,11 @@
],
export_include_dirs: ["include"],
+
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
diff --git a/libs/vibrator/fuzzer/Android.bp b/libs/vibrator/fuzzer/Android.bp
new file mode 100644
index 0000000..8020151
--- /dev/null
+++ b/libs/vibrator/fuzzer/Android.bp
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 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.
+ *
+ *****************************************************************************
+ */
+
+cc_fuzz {
+ name: "vibrator_fuzzer",
+
+ host_supported: true,
+
+ srcs: [
+ "vibrator_fuzzer.cpp",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libvibrator",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libbase",
+ "libutils",
+ ],
+
+ fuzz_config: {
+ componentid: 155276,
+ },
+}
diff --git a/libs/vibrator/fuzzer/README.md b/libs/vibrator/fuzzer/README.md
new file mode 100644
index 0000000..43eb2d2
--- /dev/null
+++ b/libs/vibrator/fuzzer/README.md
@@ -0,0 +1,65 @@
+# Fuzzer for libvibrator
+
+## Plugin Design Considerations
+This fuzzer fuzzes native code present in libvibrator and does not cover the Java implementation ExternalVibration
+The fuzzer plugin is designed based on the understanding of the
+library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+libvibrator supports the following parameters:
+1. Uid (parameter name: `uid`)
+2. Package Name (parameter name: `pkg`)
+3. Audio Content Type (parameter name: `content_type`)
+4. Audio Usage (parameter name: `usage`)
+5. Audio Source (parameter name: `source`)
+6. Audio flags (parameter name: `flags`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `uid` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
+| `pkg` | Any std::string value | Value obtained from FuzzedDataProvider |
+| `content_type` | 0.`AUDIO_CONTENT_TYPE_UNKNOWN` 1.`AUDIO_CONTENT_TYPE_SPEECH` 2.`AUDIO_CONTENT_TYPE_MUSIC` 3.`AUDIO_CONTENT_TYPE_MOVIE` 4.`AUDIO_CONTENT_TYPE_SONIFICATION`| Value obtained from FuzzedDataProvider in the range 0 to 4|
+| `usage` | 0.`AUDIO_USAGE_UNKNOWN` 1.`AUDIO_USAGE_MEDIA` 2.`AUDIO_USAGE_VOICE_COMMUNICATION` 3.`AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING` 4.`AUDIO_USAGE_ALARM` 5.`AUDIO_USAGE_NOTIFICATION` 6.`AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE` 7.`AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST` 8.`AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT` 9.`AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED` 10.`AUDIO_USAGE_NOTIFICATION_EVENT` 11.`AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY` 12.`AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE` 13.`AUDIO_USAGE_ASSISTANCE_SONIFICATION` 14.`AUDIO_USAGE_GAME` 15.`AUDIO_USAGE_VIRTUAL_SOURCE` 16.`AUDIO_USAGE_ASSISTANT` 17.`AUDIO_USAGE_CALL_ASSISTANT` 18.`AUDIO_USAGE_EMERGENCY` 19.`AUDIO_USAGE_SAFETY` 20.`AUDIO_USAGE_VEHICLE_STATUS` 21.`AUDIO_USAGE_ANNOUNCEMENT`| Value obtained from FuzzedDataProvider in the range 0 to 21|
+| `source` | 0.`AUDIO_SOURCE_DEFAULT` 1.`AUDIO_SOURCE_MIC` 2.`AUDIO_SOURCE_VOICE_UPLINK` 3.`AUDIO_SOURCE_VOICE_DOWNLINK` 4.`AUDIO_SOURCE_VOICE_CALL` 5.`AUDIO_SOURCE_CAMCORDER` 6.`AUDIO_SOURCE_VOICE_RECOGNITION` 7.`AUDIO_SOURCE_VOICE_COMMUNICATION` 8.`AUDIO_SOURCE_REMOTE_SUBMIX` 9.`AUDIO_SOURCE_UNPROCESSED` 10.`AUDIO_SOURCE_VOICE_PERFORMANCE` 11.`AUDIO_SOURCE_ECHO_REFERENCE` 12.`AUDIO_SOURCE_FM_TUNER` | Value obtained from FuzzedDataProvider in the range 0 to 12 |
+| `flags` | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesn't `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build vibrator_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) vibrator_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some files to that folder
+Push this directory to device.
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/vibrator_fuzzer/vibrator_fuzzer CORPUS_DIR
+```
+
+To run on host
+```
+ $ $ANDROID_HOST_OUT/fuzz/x86_64/vibrator_fuzzer/vibrator_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/libs/vibrator/fuzzer/vibrator_fuzzer.cpp b/libs/vibrator/fuzzer/vibrator_fuzzer.cpp
new file mode 100644
index 0000000..68b3ca6
--- /dev/null
+++ b/libs/vibrator/fuzzer/vibrator_fuzzer.cpp
@@ -0,0 +1,130 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 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 <binder/Parcel.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <vibrator/ExternalVibration.h>
+
+using namespace android;
+
+constexpr size_t MAX_STRING_LENGTH = 100;
+constexpr audio_content_type_t AUDIO_CONTENT_TYPE[] = {AUDIO_CONTENT_TYPE_UNKNOWN,
+ AUDIO_CONTENT_TYPE_SPEECH,
+ AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_CONTENT_TYPE_MOVIE,
+ AUDIO_CONTENT_TYPE_SONIFICATION};
+constexpr audio_usage_t AUDIO_USAGE[] = {
+ AUDIO_USAGE_UNKNOWN,
+ AUDIO_USAGE_MEDIA,
+ AUDIO_USAGE_VOICE_COMMUNICATION,
+ AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ AUDIO_USAGE_ALARM,
+ AUDIO_USAGE_NOTIFICATION,
+ AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+ AUDIO_USAGE_NOTIFICATION_EVENT,
+ AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+ AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ AUDIO_USAGE_ASSISTANCE_SONIFICATION,
+ AUDIO_USAGE_GAME,
+ AUDIO_USAGE_VIRTUAL_SOURCE,
+ AUDIO_USAGE_ASSISTANT,
+ AUDIO_USAGE_CALL_ASSISTANT,
+ AUDIO_USAGE_EMERGENCY,
+ AUDIO_USAGE_SAFETY,
+ AUDIO_USAGE_VEHICLE_STATUS,
+ AUDIO_USAGE_ANNOUNCEMENT,
+};
+constexpr audio_source_t AUDIO_SOURCE[] = {
+ AUDIO_SOURCE_DEFAULT, AUDIO_SOURCE_MIC,
+ AUDIO_SOURCE_VOICE_UPLINK, AUDIO_SOURCE_VOICE_DOWNLINK,
+ AUDIO_SOURCE_VOICE_CALL, AUDIO_SOURCE_CAMCORDER,
+ AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_SOURCE_VOICE_COMMUNICATION,
+ AUDIO_SOURCE_REMOTE_SUBMIX, AUDIO_SOURCE_UNPROCESSED,
+ AUDIO_SOURCE_VOICE_PERFORMANCE, AUDIO_SOURCE_ECHO_REFERENCE,
+ AUDIO_SOURCE_FM_TUNER,
+};
+constexpr size_t NUM_AUDIO_CONTENT_TYPE = std::size(AUDIO_CONTENT_TYPE);
+constexpr size_t NUM_AUDIO_USAGE = std::size(AUDIO_USAGE);
+constexpr size_t NUM_AUDIO_SOURCE = std::size(AUDIO_SOURCE);
+
+class TestVibrationController : public os::IExternalVibrationController {
+public:
+ explicit TestVibrationController() {}
+ IBinder *onAsBinder() override { return nullptr; }
+ binder::Status mute(/*out*/ bool *ret) override {
+ *ret = false;
+ return binder::Status::ok();
+ };
+ binder::Status unmute(/*out*/ bool *ret) override {
+ *ret = false;
+ return binder::Status::ok();
+ };
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ // Initialize the parameters using FuzzedDataProvider
+ int32_t uid = fdp.ConsumeIntegral<int32_t>();
+ std::string pkg = fdp.ConsumeRandomLengthString(MAX_STRING_LENGTH);
+ audio_attributes_t attributes;
+ attributes.content_type =
+ AUDIO_CONTENT_TYPE[fdp.ConsumeIntegralInRange<uint32_t>(0, NUM_AUDIO_CONTENT_TYPE - 1)];
+ attributes.usage = AUDIO_USAGE[fdp.ConsumeIntegralInRange<uint32_t>(0, NUM_AUDIO_USAGE - 1)];
+ attributes.source = AUDIO_SOURCE[fdp.ConsumeIntegralInRange<uint32_t>(0, NUM_AUDIO_SOURCE - 1)];
+ attributes.flags = static_cast<audio_flags_mask_t>(fdp.ConsumeIntegral<uint32_t>());
+
+ // Create an instance of TestVibrationController
+ sp<TestVibrationController> vibrationController = new TestVibrationController();
+ if (!vibrationController) {
+ return 0;
+ }
+
+ // Set all the parameters in the constructor call
+ sp<os::ExternalVibration> extVibration =
+ new os::ExternalVibration(uid, pkg, attributes, vibrationController);
+ if (!extVibration) {
+ return 0;
+ }
+
+ // Get all the parameters that were previously set
+ extVibration->getUid();
+ extVibration->getPackage();
+ extVibration->getAudioAttributes();
+ extVibration->getController();
+
+ // Set the parameters in a Parcel object and send it to libvibrator
+ // This parcel shall be read by libvibrator
+ Parcel parcel;
+ parcel.writeInt32(uid);
+ parcel.writeString16(String16(pkg.c_str()));
+ parcel.writeStrongBinder(IInterface::asBinder(vibrationController));
+ parcel.setDataPosition(0);
+ extVibration->readFromParcel(&parcel);
+
+ // Send a Parcel to libvibrator
+ // Parameters shall be written to this parcel by libvibrator
+ extVibration->writeToParcel(&parcel);
+ return 0;
+}