Merge "Add GLES specific setting for layers"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index d950b7c..d6ca0bf 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -91,7 +91,12 @@
chmod 0666 /sys/kernel/tracing/events/sync/enable
chmod 0666 /sys/kernel/debug/tracing/events/fence/enable
chmod 0666 /sys/kernel/tracing/events/fence/enable
-
+ chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/enable
+ chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_heap_grow/enable
+ chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_grow/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_heap_shrink/enable
+ chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_shrink/enable
# disk
chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 9d0d8ba..2e9701f 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -14,6 +14,7 @@
"CacheItem.cpp",
"CacheTracker.cpp",
"InstalldNativeService.cpp",
+ "QuotaUtils.cpp",
"dexopt.cpp",
"globals.cpp",
"utils.cpp",
@@ -33,6 +34,21 @@
"libutils",
],
+ product_variables: {
+ arc: {
+ exclude_srcs: [
+ "QuotaUtils.cpp",
+ ],
+ static_libs: [
+ "libarcdiskquota",
+ "arc_services_aidl",
+ ],
+ cflags: [
+ "-DUSE_ARC",
+ ],
+ },
+ },
+
clang: true,
tidy: true,
@@ -59,6 +75,26 @@
aidl: {
export_aidl_headers: true,
},
+
+ product_variables: {
+ arc: {
+ exclude_srcs: [
+ "QuotaUtils.cpp",
+ ],
+ static_libs: [
+ "libarcdiskquota",
+ "arc_services_aidl",
+ ],
+ cflags: [
+ "-DUSE_ARC",
+ ],
+ },
+ },
+}
+
+cc_library_headers {
+ name: "libinstalld_headers",
+ export_include_dirs: ["."],
}
//
@@ -73,6 +109,21 @@
static_libs: ["libdiskusage"],
init_rc: ["installd.rc"],
+
+ product_variables: {
+ arc: {
+ exclude_srcs: [
+ "QuotaUtils.cpp",
+ ],
+ static_libs: [
+ "libarcdiskquota",
+ "arc_services_aidl",
+ ],
+ cflags: [
+ "-DUSE_ARC",
+ ],
+ },
+ },
}
// OTA chroot tool
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index a7242c3..8b868fb 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -19,13 +19,13 @@
#include "CacheTracker.h"
#include <fts.h>
-#include <sys/quota.h>
#include <sys/xattr.h>
#include <utils/Trace.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
+#include "QuotaUtils.h"
#include "utils.h"
using android::base::StringPrintf;
@@ -33,9 +33,13 @@
namespace android {
namespace installd {
-CacheTracker::CacheTracker(userid_t userId, appid_t appId, const std::string& quotaDevice) :
- cacheUsed(0), cacheQuota(0), mUserId(userId), mAppId(appId), mQuotaDevice(quotaDevice),
- mItemsLoaded(false) {
+CacheTracker::CacheTracker(userid_t userId, appid_t appId, const std::string& uuid)
+ : cacheUsed(0),
+ cacheQuota(0),
+ mUserId(userId),
+ mAppId(appId),
+ mItemsLoaded(false),
+ mUuid(uuid) {
}
CacheTracker::~CacheTracker() {
@@ -72,26 +76,18 @@
bool CacheTracker::loadQuotaStats() {
int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
- if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) {
- struct dqblk dq;
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
- }
- return false;
+ if (IsQuotaSupported(mUuid) && cacheGid != -1 && extCacheGid != -1) {
+ int64_t space;
+ if ((space = GetOccupiedSpaceForGid(mUuid, cacheGid)) != -1) {
+ cacheUsed += space;
} else {
- cacheUsed += dq.dqb_curspace;
+ return false;
}
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
- }
- return false;
+ if ((space = GetOccupiedSpaceForGid(mUuid, extCacheGid)) != -1) {
+ cacheUsed += space;
} else {
- cacheUsed += dq.dqb_curspace;
+ return false;
}
return true;
} else {
diff --git a/cmds/installd/CacheTracker.h b/cmds/installd/CacheTracker.h
index 44359b4..b0527e7 100644
--- a/cmds/installd/CacheTracker.h
+++ b/cmds/installd/CacheTracker.h
@@ -39,7 +39,7 @@
*/
class CacheTracker {
public:
- CacheTracker(userid_t userId, appid_t appId, const std::string& quotaDevice);
+ CacheTracker(userid_t userId, appid_t appId, const std::string& uuid);
~CacheTracker();
std::string toString();
@@ -61,8 +61,8 @@
private:
userid_t mUserId;
appid_t mAppId;
- std::string mQuotaDevice;
bool mItemsLoaded;
+ const std::string& mUuid;
std::vector<std::string> mDataPaths;
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index a475fcc..81055d8 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -31,7 +31,6 @@
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <sys/quota.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
@@ -64,6 +63,7 @@
#include "CacheTracker.h"
#include "MatchExtensionGen.h"
+#include "QuotaUtils.h"
#ifndef LOG_TAG
#define LOG_TAG "installd"
@@ -257,11 +257,6 @@
for (const auto& n : mStorageMounts) {
out << " " << n.first << " = " << n.second << endl;
}
-
- out << endl << "Quota reverse mounts:" << endl;
- for (const auto& n : mQuotaReverseMounts) {
- out << " " << n.first << " = " << n.second << endl;
- }
}
{
@@ -988,9 +983,9 @@
CHECK_ARGUMENT_UUID(uuid);
std::lock_guard<std::recursive_mutex> lock(mLock);
+ auto uuidString = uuid ? *uuid : "";
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
auto data_path = create_data_path(uuid_);
- auto device = findQuotaDeviceForUuid(uuid);
auto noop = (flags & FLAG_FREE_CACHE_NOOP);
int64_t free = data_disk_free(data_path);
@@ -1037,7 +1032,7 @@
search->second->addDataPath(p->fts_path);
} else {
auto tracker = std::shared_ptr<CacheTracker>(new CacheTracker(
- multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
+ multiuser_get_user_id(uid), multiuser_get_app_id(uid), uuidString));
tracker->addDataPath(p->fts_path);
{
std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
@@ -1202,53 +1197,26 @@
}
#endif
-static void collectQuotaStats(const std::string& device, int32_t userId,
+static void collectQuotaStats(const std::string& uuid, int32_t userId,
int32_t appId, struct stats* stats, struct stats* extStats) {
- if (device.empty()) return;
-
- struct dqblk dq;
-
+ int64_t space;
if (stats != nullptr) {
uid_t uid = multiuser_get_uid(userId, appId);
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
-#endif
- stats->dataSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
+ stats->dataSize += space;
}
int cacheGid = multiuser_get_cache_gid(userId, appId);
if (cacheGid != -1) {
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace;
-#endif
- stats->cacheSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) {
+ stats->cacheSize += space;
}
}
int sharedGid = multiuser_get_shared_gid(0, appId);
if (sharedGid != -1) {
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
-#endif
- stats->codeSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuid, sharedGid)) != -1) {
+ stats->codeSize += space;
}
}
}
@@ -1256,32 +1224,16 @@
if (extStats != nullptr) {
int extGid = multiuser_get_ext_gid(userId, appId);
if (extGid != -1) {
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace;
-#endif
- extStats->dataSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuid, extGid)) != -1) {
+ extStats->dataSize += space;
}
}
int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
if (extCacheGid != -1) {
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extCacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extCacheGid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << extCacheGid << " " << dq.dqb_curspace;
-#endif
- extStats->dataSize += dq.dqb_curspace;
- extStats->cacheSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuid, extCacheGid)) != -1) {
+ extStats->dataSize += space;
+ extStats->cacheSize += space;
}
}
}
@@ -1445,10 +1397,10 @@
memset(&stats, 0, sizeof(stats));
memset(&extStats, 0, sizeof(extStats));
+ auto uuidString = uuid ? *uuid : "";
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
- auto device = findQuotaDeviceForUuid(uuid);
- if (device.empty()) {
+ if (!IsQuotaSupported(uuidString)) {
flags &= ~FLAG_USE_QUOTA;
}
@@ -1468,7 +1420,7 @@
ATRACE_END();
ATRACE_BEGIN("quota");
- collectQuotaStats(device, userId, appId, &stats, &extStats);
+ collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
ATRACE_END();
} else {
ATRACE_BEGIN("code");
@@ -1553,27 +1505,19 @@
memset(&stats, 0, sizeof(stats));
memset(&extStats, 0, sizeof(extStats));
+ auto uuidString = uuid ? *uuid : "";
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
- auto device = findQuotaDeviceForUuid(uuid);
- if (device.empty()) {
+ if (!IsQuotaSupported(uuidString)) {
flags &= ~FLAG_USE_QUOTA;
}
if (flags & FLAG_USE_QUOTA) {
- struct dqblk dq;
+ int64_t space;
ATRACE_BEGIN("obb");
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << AID_MEDIA_OBB;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
-#endif
- extStats.codeSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
+ extStats.codeSize += space;
}
ATRACE_END();
@@ -1599,16 +1543,8 @@
ATRACE_BEGIN("external");
uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
-#endif
- extStats.dataSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
+ extStats.dataSize += space;
}
ATRACE_END();
@@ -1625,7 +1561,7 @@
int64_t dataSize = extStats.dataSize;
for (auto appId : appIds) {
if (appId >= AID_APP_START) {
- collectQuotaStats(device, userId, appId, &stats, &extStats);
+ collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
#if MEASURE_DEBUG
// Sleep to make sure we don't lose logs
@@ -1707,6 +1643,7 @@
LOG(INFO) << "Measuring external " << userId;
#endif
+ auto uuidString = uuid ? *uuid : "";
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
int64_t totalSize = 0;
@@ -1716,58 +1653,33 @@
int64_t appSize = 0;
int64_t obbSize = 0;
- auto device = findQuotaDeviceForUuid(uuid);
- if (device.empty()) {
+ if (!IsQuotaSupported(uuidString)) {
flags &= ~FLAG_USE_QUOTA;
}
if (flags & FLAG_USE_QUOTA) {
- struct dqblk dq;
+ int64_t space;
ATRACE_BEGIN("quota");
uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
-#endif
- totalSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
+ totalSize = space;
}
gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid,
- reinterpret_cast<char*>(&dq)) == 0) {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace;
-#endif
- audioSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, audioGid)) != -1) {
+ audioSize = space;
}
gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid,
- reinterpret_cast<char*>(&dq)) == 0) {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace;
-#endif
- videoSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, videoGid)) != -1) {
+ videoSize = space;
}
gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid,
- reinterpret_cast<char*>(&dq)) == 0) {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace;
-#endif
- imageSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, imageGid)) != -1) {
+ imageSize = space;
}
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
- reinterpret_cast<char*>(&dq)) == 0) {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
-#endif
- obbSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
+ obbSize = space;
}
ATRACE_END();
@@ -1776,7 +1688,7 @@
memset(&extStats, 0, sizeof(extStats));
for (auto appId : appIds) {
if (appId >= AID_APP_START) {
- collectQuotaStats(device, userId, appId, nullptr, &extStats);
+ collectQuotaStats(uuidString, userId, appId, nullptr, &extStats);
}
}
appSize = extStats.dataSize;
@@ -2564,7 +2476,12 @@
std::lock_guard<std::recursive_mutex> lock(mMountsLock);
mStorageMounts.clear();
- mQuotaReverseMounts.clear();
+
+#if !BYPASS_QUOTA
+ if (!InvalidateQuotaMounts()) {
+ return error("Failed to read mounts");
+ }
+#endif
std::ifstream in("/proc/mounts");
if (!in.is_open()) {
@@ -2585,17 +2502,6 @@
mStorageMounts[source] = target;
}
#endif
-
-#if !BYPASS_QUOTA
- if (source.compare(0, 11, "/dev/block/") == 0) {
- struct dqblk dq;
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
- reinterpret_cast<char*>(&dq)) == 0) {
- LOG(DEBUG) << "Found quota mount " << source << " at " << target;
- mQuotaReverseMounts[target] = source;
- }
- }
-#endif
}
return ok();
}
@@ -2613,16 +2519,10 @@
return StringPrintf("%s/%u", resolved.c_str(), userid);
}
-std::string InstalldNativeService::findQuotaDeviceForUuid(
- const std::unique_ptr<std::string>& uuid) {
- std::lock_guard<std::recursive_mutex> lock(mMountsLock);
- auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
- return mQuotaReverseMounts[path];
-}
-
binder::Status InstalldNativeService::isQuotaSupported(
- const std::unique_ptr<std::string>& volumeUuid, bool* _aidl_return) {
- *_aidl_return = !findQuotaDeviceForUuid(volumeUuid).empty();
+ const std::unique_ptr<std::string>& uuid, bool* _aidl_return) {
+ auto uuidString = uuid ? *uuid : "";
+ *_aidl_return = IsQuotaSupported(uuidString);
return ok();
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index cebd3f9..367f2c1 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -150,14 +150,11 @@
/* Map of all storage mounts from source to target */
std::unordered_map<std::string, std::string> mStorageMounts;
- /* Map of all quota mounts from target to source */
- std::unordered_map<std::string, std::string> mQuotaReverseMounts;
/* Map from UID to cache quota size */
std::unordered_map<uid_t, int64_t> mCacheQuotas;
std::string findDataMediaPath(const std::unique_ptr<std::string>& uuid, userid_t userid);
- std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
};
} // namespace installd
diff --git a/cmds/installd/QuotaUtils.cpp b/cmds/installd/QuotaUtils.cpp
new file mode 100644
index 0000000..b238dd3
--- /dev/null
+++ b/cmds/installd/QuotaUtils.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2018 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 "QuotaUtils.h"
+
+#include <fstream>
+#include <unordered_map>
+
+#include <sys/quota.h>
+
+#include <android-base/logging.h>
+
+#include "utils.h"
+
+namespace android {
+namespace installd {
+
+namespace {
+
+std::recursive_mutex mMountsLock;
+
+/* Map of all quota mounts from target to source */
+std::unordered_map<std::string, std::string> mQuotaReverseMounts;
+
+std::string& FindQuotaDeviceForUuid(const std::string& uuid) {
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+ auto path = create_data_path(uuid.empty() ? nullptr : uuid.c_str());
+ return mQuotaReverseMounts[path];
+}
+
+} // namespace
+
+bool InvalidateQuotaMounts() {
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+
+ mQuotaReverseMounts.clear();
+
+ std::ifstream in("/proc/mounts");
+ if (!in.is_open()) {
+ return false;
+ }
+
+ std::string source;
+ std::string target;
+ std::string ignored;
+ while (!in.eof()) {
+ std::getline(in, source, ' ');
+ std::getline(in, target, ' ');
+ std::getline(in, ignored);
+
+ if (source.compare(0, 11, "/dev/block/") == 0) {
+ struct dqblk dq;
+ if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
+ reinterpret_cast<char*>(&dq)) == 0) {
+ LOG(DEBUG) << "Found quota mount " << source << " at " << target;
+ mQuotaReverseMounts[target] = source;
+ }
+ }
+ }
+ return true;
+}
+
+bool IsQuotaSupported(const std::string& uuid) {
+ return !FindQuotaDeviceForUuid(uuid).empty();
+}
+
+int64_t GetOccupiedSpaceForUid(const std::string& uuid, uid_t uid) {
+ const std::string device = FindQuotaDeviceForUuid(uuid);
+ if (device == "") {
+ return -1;
+ }
+ struct dqblk dq;
+ if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
+ }
+ return -1;
+ } else {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
+#endif
+ return dq.dqb_curspace;
+ }
+}
+
+int64_t GetOccupiedSpaceForGid(const std::string& uuid, gid_t gid) {
+ const std::string device = FindQuotaDeviceForUuid(uuid);
+ if (device == "") {
+ return -1;
+ }
+ struct dqblk dq;
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), gid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << gid;
+ }
+ return -1;
+ } else {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for GID " << gid << " " << dq.dqb_curspace;
+#endif
+ return dq.dqb_curspace;
+ }
+
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/QuotaUtils.h b/cmds/installd/QuotaUtils.h
new file mode 100644
index 0000000..9ad170f
--- /dev/null
+++ b/cmds/installd/QuotaUtils.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef ANDROID_INSTALLD_QUOTA_UTILS_H_
+#define ANDROID_INSTALLD_QUOTA_UTILS_H_
+
+#include <memory>
+#include <string>
+
+namespace android {
+namespace installd {
+
+/* Clear and recompute the reverse mounts map */
+bool InvalidateQuotaMounts();
+
+/* Whether quota is supported in the device with the given uuid */
+bool IsQuotaSupported(const std::string& uuid);
+
+/* Get the current occupied space in bytes for a uid or -1 if fails */
+int64_t GetOccupiedSpaceForUid(const std::string& uuid, uid_t uid);
+
+/* Get the current occupied space in bytes for a gid or -1 if fails */
+int64_t GetOccupiedSpaceForGid(const std::string& uuid, gid_t gid);
+
+} // namespace installd
+} // namespace android
+
+#endif // ANDROID_INSTALLD_QUOTA_UTILS_H_
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 174ab21..b6038f9 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -2693,6 +2693,13 @@
return false;
}
+ // Return false for empty class path since it may otherwise return true below if profiles is
+ // empty.
+ if (classpath.empty()) {
+ PLOG(ERROR) << "Class path is empty";
+ return false;
+ }
+
// Open and create the snapshot profile.
unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index f216c53..eb69e78 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -143,6 +143,20 @@
"AAAACADojmFLPcugSwoBAAAUAgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAA/Ns"
"+ll1eAsAAQQj5QIABIgTAABQSwUGAAAAAAEAAQBRAAAATwEAAAAA";
+class DexoptTestEnvTest : public testing::Test {
+};
+
+TEST_F(DexoptTestEnvTest, CheckSelinux) {
+ ASSERT_EQ(1, is_selinux_enabled());
+
+ // Crude cutout for virtual devices.
+#if !defined(__i386__) && !defined(__x86_64__)
+ constexpr bool kIsX86 = false;
+#else
+ constexpr bool kIsX86 = true;
+#endif
+ ASSERT_TRUE(1 == security_getenforce() || kIsX86);
+}
class DexoptTest : public testing::Test {
protected:
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 6b9cf0d..74ad184 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -43,6 +43,7 @@
#define DEBUG_XATTRS 0
using android::base::EndsWith;
+using android::base::Fdopendir;
using android::base::StringPrintf;
using android::base::unique_fd;
@@ -1036,7 +1037,7 @@
continue;
}
- DIR* subdir = fdopendir(subdir_fd);
+ DIR* subdir = Fdopendir(std::move(subdir_fd));
if (subdir == nullptr) {
PLOG(WARNING) << "Could not open dir path " << local_path;
result = false;
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 79f666b..c541511 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -150,19 +150,81 @@
* Move to the next system font.
*
* \param iterator an iterator for the system fonts. Passing NULL is not allowed.
- * \return true if more system fonts are available, otherwise false.
+ * \return a font. If no more font is available, returns nullptr. You need to release the returned
+ * font by ASystemFont_close when it is no longer needed.
*/
ASystemFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29);
/**
* Close an ASystemFont returned by ASystemFontIterator_next.
*
- * \param font a font returned by ASystemFontIterator_next. Do nothing if NULL is passed.
+ * \param font a font returned by ASystemFontIterator_next or ASystemFont_matchFamilyStyleCharacter.
+ * Do nothing if NULL is passed.
*/
void ASystemFont_close(ASystemFont* _Nullable font) __INTRODUCED_IN(29);
/**
+ * Select the best font from given parameters.
+ *
+ * Only generic font families are supported.
+ * For more information about generic font families, read [W3C spec](https://www.w3.org/TR/css-fonts-4/#generic-font-families)
+ *
+ * Even if no font can render the given text, this function will return a non-null result for
+ * drawing Tofu character.
+ *
+ * Examples:
+ * <code>
+ * // Simple font query for the ASCII character.
+ * std::vector<uint16_t> text = { 'A' };
+ * ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
+ * "sans", 400, false, "en-US", text.data(), text.length(), &runLength);
+ * // runLength will be 1 and the font will points a valid font file.
+ *
+ * // Querying font for CJK characters
+ * std::vector<uint16_t> text = { 0x9AA8 };
+ * ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
+ * "sans", 400, false, "zh-CN,ja-JP", text.data(), text.length(), &runLength);
+ * // runLength will be 1 and the font will points a Simplified Chinese font.
+ * ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
+ * "sans", 400, false, "ja-JP,zh-CN", text.data(), text.length(), &runLength);
+ * // runLength will be 1 and the font will points a Japanese font.
+ *
+ * // Querying font for text/color emoji
+ * std::vector<uint16_t> text = { 0xD83D, 0xDC68, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC68 };
+ * ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
+ * "sans", 400, false, "en-US", text.data(), text.length(), &runLength);
+ * // runLength will be 8 and the font will points a color emoji font.
+ *
+ * // Mixture of multiple script of characters.
+ * // 0x05D0 is a Hebrew character and 0x0E01 is a Thai character.
+ * std::vector<uint16_t> text = { 0x05D0, 0x0E01 };
+ * ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
+ * "sans", 400, false, "en-US", text.data(), text.length(), &runLength);
+ * // runLength will be 1 and the font will points a Hebrew font.
+ * </code>
+ *
+ * \param familyName a null character terminated font family name
+ * \param weight a font weight value. Only from 0 to 1000 value is valid
+ * \param italic true if italic, otherwise false.
+ * \param languageTags a null character terminated comma separated IETF BCP47 compliant language
+ * tags.
+ * \param text a UTF-16 encoded text buffer to be rendered.
+ * \param textLength a length of the given text buffer.
+ * \param runLengthOut if not null, the font run length will be filled.
+ * \return a font to be used for given text and params. You need to release the returned font by
+ * ASystemFont_close when it is no longer needed.
+ */
+ASystemFont* _Nonnull ASystemFont_matchFamilyStyleCharacter(
+ const char* _Nonnull familyName,
+ uint16_t weight,
+ bool italic,
+ const char* _Nonnull languageTags,
+ const uint16_t* _Nonnull text,
+ uint32_t textLength,
+ uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29);
+
+/**
* Return an absolute path to the current font file.
*
* Here is a list of font formats returned by this method:
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 5461b4f..d16502f 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -38,6 +38,8 @@
"libbinder",
"libutils",
],
+
+ version_script: "libbinder_ndk.map.txt",
}
ndk_headers {
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index cc0a29d..e52a1d6 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -31,6 +31,7 @@
#include <android/binder_status.h>
#include <assert.h>
+#include <unistd.h>
#ifdef __cplusplus
@@ -113,23 +114,23 @@
/**
* This baseclass owns a single object, used to make various classes RAII.
*/
-template <typename T, void (*Destroy)(T*)>
+template <typename T, typename R, R (*Destroy)(T), T DEFAULT>
class ScopedAResource {
public:
/**
* Takes ownership of t.
*/
- explicit ScopedAResource(T* t = nullptr) : mT(t) {}
+ explicit ScopedAResource(T t = DEFAULT) : mT(t) {}
/**
* This deletes the underlying object if it exists. See set.
*/
- ~ScopedAResource() { set(nullptr); }
+ ~ScopedAResource() { set(DEFAULT); }
/**
* Takes ownership of t.
*/
- void set(T* t) {
+ void set(T t) {
Destroy(mT);
mT = t;
}
@@ -137,12 +138,12 @@
/**
* This returns the underlying object to be modified but does not affect ownership.
*/
- T* get() { return mT; }
+ T get() { return mT; }
/**
* This returns the const underlying object but does not affect ownership.
*/
- const T* get() const { return mT; }
+ const T get() const { return mT; }
/**
* This allows the value in this class to be set from beneath it. If you call this method and
@@ -156,7 +157,7 @@
* Other usecases are discouraged.
*
*/
- T** getR() { return &mT; }
+ T* getR() { return &mT; }
// copy-constructing, or move/copy assignment is disallowed
ScopedAResource(const ScopedAResource&) = delete;
@@ -167,13 +168,13 @@
ScopedAResource(ScopedAResource&&) = default;
private:
- T* mT;
+ T mT;
};
/**
* Convenience wrapper. See AParcel.
*/
-class ScopedAParcel : public ScopedAResource<AParcel, AParcel_delete> {
+class ScopedAParcel : public ScopedAResource<AParcel*, void, AParcel_delete, nullptr> {
public:
/**
* Takes ownership of a.
@@ -186,7 +187,7 @@
/**
* Convenience wrapper. See AStatus.
*/
-class ScopedAStatus : public ScopedAResource<AStatus, AStatus_delete> {
+class ScopedAStatus : public ScopedAResource<AStatus*, void, AStatus_delete, nullptr> {
public:
/**
* Takes ownership of a.
@@ -205,7 +206,8 @@
* Convenience wrapper. See AIBinder_DeathRecipient.
*/
class ScopedAIBinder_DeathRecipient
- : public ScopedAResource<AIBinder_DeathRecipient, AIBinder_DeathRecipient_delete> {
+ : public ScopedAResource<AIBinder_DeathRecipient*, void, AIBinder_DeathRecipient_delete,
+ nullptr> {
public:
/**
* Takes ownership of a.
@@ -219,7 +221,8 @@
/**
* Convenience wrapper. See AIBinder_Weak.
*/
-class ScopedAIBinder_Weak : public ScopedAResource<AIBinder_Weak, AIBinder_Weak_delete> {
+class ScopedAIBinder_Weak
+ : public ScopedAResource<AIBinder_Weak*, void, AIBinder_Weak_delete, nullptr> {
public:
/**
* Takes ownership of a.
@@ -234,6 +237,19 @@
SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
};
+/**
+ * Convenience wrapper for a file descriptor.
+ */
+class ScopedFileDescriptor : public ScopedAResource<int, int, close, -1> {
+public:
+ /**
+ * Takes ownership of a.
+ */
+ explicit ScopedFileDescriptor(int a = -1) : ScopedAResource(a) {}
+ ~ScopedFileDescriptor() {}
+ ScopedFileDescriptor(ScopedFileDescriptor&&) = default;
+};
+
} // namespace ndk
#endif // __cplusplus
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 33c3f6c..4e0132b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -193,6 +193,23 @@
__INTRODUCED_IN(29);
/**
+ * Writes a file descriptor to the next location in a non-null parcel. This does not take ownership
+ * of fd.
+ *
+ * This corresponds to the SDK's android.os.ParcelFileDescriptor.
+ */
+binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd);
+
+/**
+ * Reads an int from the next location in a non-null parcel.
+ *
+ * The returned fd must be closed.
+ *
+ * This corresponds to the SDK's android.os.ParcelFileDescriptor.
+ */
+binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd);
+
+/**
* Writes an AStatus object to the next location in a non-null parcel.
*
* If the status is considered to be a low-level status and has no additional information other
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index f84814f..ec6587a 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -38,6 +38,7 @@
AParcel_readInt64;
AParcel_readInt64Array;
AParcel_readNullableStrongBinder;
+ AParcel_readParcelFileDescriptor;
AParcel_readStatusHeader;
AParcel_readString;
AParcel_readStrongBinder;
@@ -59,6 +60,7 @@
AParcel_writeInt32Array;
AParcel_writeInt64;
AParcel_writeInt64Array;
+ AParcel_writeParcelFileDescriptor;
AParcel_writeStatusHeader;
AParcel_writeString;
AParcel_writeStrongBinder;
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 5ac3965..77c0558 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -23,13 +23,17 @@
#include <limits>
#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
#include <binder/Parcel.h>
+#include <binder/ParcelFileDescriptor.h>
#include <utils/Unicode.h>
using ::android::IBinder;
using ::android::Parcel;
using ::android::sp;
using ::android::status_t;
+using ::android::base::unique_fd;
+using ::android::os::ParcelFileDescriptor;
template <typename T>
using ContiguousArrayAllocator = T* (*)(void* arrayData, size_t length);
@@ -210,6 +214,28 @@
*binder = ret.get();
return PruneStatusT(status);
}
+
+binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
+ ParcelFileDescriptor parcelFd((unique_fd(fd)));
+
+ status_t status = parcel->get()->writeParcelable(parcelFd);
+
+ // ownership is retained by caller
+ (void)parcelFd.release().release();
+
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
+ ParcelFileDescriptor parcelFd;
+ // status_t status = parcelFd.readFromParcel(parcel->get());
+ status_t status = parcel->get()->readParcelable(&parcelFd);
+ if (status != STATUS_OK) return PruneStatusT(status);
+
+ *fd = parcelFd.release().release();
+ return STATUS_OK;
+}
+
binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
return PruneStatusT(status->get()->writeToParcel(parcel->get()));
}
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index 1a7c2d3..ed773e0 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -20,7 +20,6 @@
#include <log/log.h>
#include <system/window.h>
#include <ui/BufferHubBuffer.h>
-#include <ui/DetachedBufferHandle.h>
namespace android {
@@ -276,14 +275,10 @@
status_or_handle.error());
return BAD_VALUE;
}
- std::unique_ptr<DetachedBufferHandle> handle =
- DetachedBufferHandle::Create(status_or_handle.take());
- if (!handle->isValid()) {
- ALOGE("detachBuffer: Failed to create a DetachedBufferHandle at slot %zu.", slot);
- return BAD_VALUE;
- }
- return graphic_buffer->setDetachedBufferHandle(std::move(handle));
+ // TODO(b/70912269): Reimplement BufferHubProducer::DetachBufferLocked() once GraphicBuffer can
+ // be directly backed by BufferHub.
+ return INVALID_OPERATION;
}
status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) {
@@ -373,7 +368,7 @@
ALOGE("attachBuffer: out_slot cannot be NULL.");
return BAD_VALUE;
}
- if (buffer == nullptr || !buffer->isDetachedBuffer()) {
+ if (buffer == nullptr) {
ALOGE("attachBuffer: invalid GraphicBuffer.");
return BAD_VALUE;
}
@@ -394,45 +389,9 @@
return BAD_VALUE;
}
- // Creates a BufferProducer from the GraphicBuffer.
- std::unique_ptr<DetachedBufferHandle> detached_handle = buffer->takeDetachedBufferHandle();
- if (detached_handle == nullptr) {
- ALOGE("attachBuffer: DetachedBufferHandle cannot be NULL.");
- return BAD_VALUE;
- }
- std::shared_ptr<BufferProducer> buffer_producer =
- BufferProducer::Import(std::move(detached_handle->handle()));
- if (buffer_producer == nullptr) {
- ALOGE("attachBuffer: Failed to import BufferProducer.");
- return BAD_VALUE;
- }
-
- // Adds the BufferProducer into the Queue.
- auto status_or_slot = queue_->InsertBuffer(buffer_producer);
- if (!status_or_slot.ok()) {
- ALOGE("attachBuffer: Failed to insert buffer, error=%d.", status_or_slot.error());
- return BAD_VALUE;
- }
-
- size_t slot = status_or_slot.get();
- ALOGV("attachBuffer: returning slot %zu.", slot);
- if (slot >= static_cast<size_t>(max_buffer_count_)) {
- ALOGE("attachBuffer: Invalid slot: %zu.", slot);
- return BAD_VALUE;
- }
-
- // The just attached buffer should be in dequeued state according to IGraphicBufferProducer
- // interface. In BufferHub's language the buffer should be in Gained state.
- buffers_[slot].mGraphicBuffer = buffer;
- buffers_[slot].mBufferState.attachProducer();
- buffers_[slot].mEglFence = EGL_NO_SYNC_KHR;
- buffers_[slot].mFence = Fence::NO_FENCE;
- buffers_[slot].mRequestBufferCalled = true;
- buffers_[slot].mAcquireCalled = false;
- buffers_[slot].mNeedsReallocation = false;
-
- *out_slot = static_cast<int>(slot);
- return NO_ERROR;
+ // TODO(b/70912269): Reimplement BufferHubProducer::DetachBufferLocked() once GraphicBuffer can
+ // be directly backed by BufferHub.
+ return INVALID_OPERATION;
}
status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input,
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index cc0a307..e66c0e5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -565,8 +565,10 @@
return reply.readParcelableVector(outLayers);
}
- virtual status_t getCompositionPreference(ui::Dataspace* dataSpace,
- ui::PixelFormat* pixelFormat) const {
+ virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
+ ui::PixelFormat* defaultPixelFormat,
+ ui::Dataspace* wideColorGamutDataspace,
+ ui::PixelFormat* wideColorGamutPixelFormat) const {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -578,8 +580,10 @@
}
error = static_cast<status_t>(reply.readInt32());
if (error == NO_ERROR) {
- *dataSpace = static_cast<ui::Dataspace>(reply.readInt32());
- *pixelFormat = static_cast<ui::PixelFormat>(reply.readInt32());
+ *defaultDataspace = static_cast<ui::Dataspace>(reply.readInt32());
+ *defaultPixelFormat = static_cast<ui::PixelFormat>(reply.readInt32());
+ *wideColorGamutDataspace = static_cast<ui::Dataspace>(reply.readInt32());
+ *wideColorGamutPixelFormat = static_cast<ui::PixelFormat>(reply.readInt32());
}
return error;
}
@@ -925,13 +929,19 @@
}
case GET_COMPOSITION_PREFERENCE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::Dataspace dataSpace;
- ui::PixelFormat pixelFormat;
- status_t error = getCompositionPreference(&dataSpace, &pixelFormat);
+ ui::Dataspace defaultDataspace;
+ ui::PixelFormat defaultPixelFormat;
+ ui::Dataspace wideColorGamutDataspace;
+ ui::PixelFormat wideColorGamutPixelFormat;
+ status_t error =
+ getCompositionPreference(&defaultDataspace, &defaultPixelFormat,
+ &wideColorGamutDataspace, &wideColorGamutPixelFormat);
reply->writeInt32(error);
if (error == NO_ERROR) {
- reply->writeInt32(static_cast<int32_t>(dataSpace));
- reply->writeInt32(static_cast<int32_t>(pixelFormat));
+ reply->writeInt32(static_cast<int32_t>(defaultDataspace));
+ reply->writeInt32(static_cast<int32_t>(defaultPixelFormat));
+ reply->writeInt32(static_cast<int32_t>(wideColorGamutDataspace));
+ reply->writeInt32(static_cast<int32_t>(wideColorGamutDataspace));
}
return NO_ERROR;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 7498f36..e5a2454 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -866,9 +866,12 @@
ComposerService::getComposerService()->setPowerMode(token, mode);
}
-status_t SurfaceComposerClient::getCompositionPreference(ui::Dataspace* dataSpace,
- ui::PixelFormat* pixelFormat) {
- return ComposerService::getComposerService()->getCompositionPreference(dataSpace, pixelFormat);
+status_t SurfaceComposerClient::getCompositionPreference(
+ ui::Dataspace* defaultDataspace, ui::PixelFormat* defaultPixelFormat,
+ ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat) {
+ return ComposerService::getComposerService()
+ ->getCompositionPreference(defaultDataspace, defaultPixelFormat,
+ wideColorGamutDataspace, wideColorGamutPixelFormat);
}
status_t SurfaceComposerClient::clearAnimationFrameStats() {
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 35cb3be..9316ae6 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -280,10 +280,19 @@
*/
virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const = 0;
- virtual status_t getCompositionPreference(ui::Dataspace* dataSpace,
- ui::PixelFormat* pixelFormat) const = 0;
-
virtual bool isColorManagementUsed() const = 0;
+
+ /* Gets the composition preference of the default data space and default pixel format,
+ * as well as the wide color gamut data space and wide color gamut pixel format.
+ * If the wide color gamut data space is V0_SRGB, then it implies that the platform
+ * has no wide color gamut support.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
+ ui::PixelFormat* defaultPixelFormat,
+ ui::Dataspace* wideColorGamutDataspace,
+ ui::PixelFormat* wideColorGamutPixelFormat) const = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 1b4eda7..8ccee05 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -101,9 +101,15 @@
/* Triggers screen on/off or low power mode and waits for it to complete */
static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
- //
- static status_t getCompositionPreference(ui::Dataspace* dataSpace,
- ui::PixelFormat* pixelFormat);
+ /* Returns the composition preference of the default data space and default pixel format,
+ * as well as the wide color gamut data space and wide color gamut pixel format.
+ * If the wide color gamut data space is V0_SRGB, then it implies that the platform
+ * has no wide color gamut support.
+ */
+ static status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
+ ui::PixelFormat* defaultPixelFormat,
+ ui::Dataspace* wideColorGamutDataspace,
+ ui::PixelFormat* wideColorGamutPixelFormat);
// ------------------------------------------------------------------------
// surface creation / destruction
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 6d03374..aef7aed 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -777,14 +777,6 @@
ASSERT_OK(mProducer->detachBuffer(slot));
EXPECT_OK(buffer->initCheck());
- if (GetParam() == USE_BUFFER_HUB_PRODUCER) {
- // For a GraphicBuffer backed by BufferHub, once detached from an IGBP, it should have
- // isDetachedBuffer() set. Note that this only applies to BufferHub.
- EXPECT_TRUE(buffer->isDetachedBuffer());
- } else {
- EXPECT_FALSE(buffer->isDetachedBuffer());
- }
-
ASSERT_OK(mProducer->disconnect(TEST_API));
ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
@@ -801,16 +793,7 @@
ASSERT_OK(mProducer->detachBuffer(slot));
EXPECT_OK(buffer->initCheck());
- if (GetParam() == USE_BUFFER_HUB_PRODUCER) {
- // For a GraphicBuffer backed by BufferHub, once detached from an IGBP, it should have
- // isDetachedBuffer() set. Note that this only applies to BufferHub.
- EXPECT_TRUE(buffer->isDetachedBuffer());
- } else {
- EXPECT_FALSE(buffer->isDetachedBuffer());
- }
-
EXPECT_OK(mProducer->attachBuffer(&slot, buffer));
- EXPECT_FALSE(buffer->isDetachedBuffer());
EXPECT_OK(buffer->initCheck());
}
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 25f762b..a3e9249 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -628,8 +628,10 @@
status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* /*layers*/) const override {
return NO_ERROR;
}
- status_t getCompositionPreference(ui::Dataspace* /*outDataSpace*/,
- ui::PixelFormat* /*outPixelFormat*/) const override {
+ status_t getCompositionPreference(
+ ui::Dataspace* /*outDefaultDataspace*/, ui::PixelFormat* /*outDefaultPixelFormat*/,
+ ui::Dataspace* /*outWideColorGamutDataspace*/,
+ ui::PixelFormat* /*outWideColorGamutPixelFormat*/) const override {
return NO_ERROR;
}
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index a6e6d73..8cc1a4e 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -37,7 +37,6 @@
#pragma clang diagnostic pop
#include <ui/BufferHubBuffer.h>
-#include <ui/DetachedBufferHandle.h>
#include <poll.h>
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index c50d1d0..5a1ddee 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -22,7 +22,6 @@
#include <grallocusage/GrallocUsageConversion.h>
-#include <ui/DetachedBufferHandle.h>
#include <ui/Gralloc2.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
@@ -490,24 +489,6 @@
return NO_ERROR;
}
-bool GraphicBuffer::isDetachedBuffer() const {
- return mDetachedBufferHandle && mDetachedBufferHandle->isValid();
-}
-
-status_t GraphicBuffer::setDetachedBufferHandle(std::unique_ptr<DetachedBufferHandle> channel) {
- if (isDetachedBuffer()) {
- ALOGW("setDetachedBuffer: there is already a BufferHub channel associated with this "
- "GraphicBuffer. Replacing the old one.");
- }
-
- mDetachedBufferHandle = std::move(channel);
- return NO_ERROR;
-}
-
-std::unique_ptr<DetachedBufferHandle> GraphicBuffer::takeDetachedBufferHandle() {
- return std::move(mDetachedBufferHandle);
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/ui/include/ui/DetachedBufferHandle.h b/libs/ui/include/ui/DetachedBufferHandle.h
deleted file mode 100644
index f3c328d..0000000
--- a/libs/ui/include/ui/DetachedBufferHandle.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef ANDROID_DETACHED_BUFFER_HUB_HANDLE_H
-#define ANDROID_DETACHED_BUFFER_HUB_HANDLE_H
-
-#include <pdx/channel_handle.h>
-
-#include <memory>
-
-namespace android {
-
-// A wrapper that holds a pdx::LocalChannelHandle object. From the handle, a BufferHub buffer can be
-// created. Current implementation assumes that the underlying transport is using libpdx (thus
-// holding a pdx::LocalChannelHandle object), but future implementation can change it to a Binder
-// backend if ever needed.
-class DetachedBufferHandle {
-public:
- static std::unique_ptr<DetachedBufferHandle> Create(pdx::LocalChannelHandle handle) {
- return std::unique_ptr<DetachedBufferHandle>(new DetachedBufferHandle(std::move(handle)));
- }
-
- // Accessors to get or take the internal pdx::LocalChannelHandle.
- pdx::LocalChannelHandle& handle() { return mHandle; }
- const pdx::LocalChannelHandle& handle() const { return mHandle; }
-
- // Returns whether the DetachedBufferHandle holds a BufferHub channel.
- bool isValid() const { return mHandle.valid(); }
-
-private:
- // Constructs a DetachedBufferHandle from a pdx::LocalChannelHandle.
- explicit DetachedBufferHandle(pdx::LocalChannelHandle handle) : mHandle(std::move(handle)) {}
-
- pdx::LocalChannelHandle mHandle;
-};
-
-} // namespace android
-
-#endif // ANDROID_DETACHED_BUFFER_HUB_HANDLE_H
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index cc38982..e794462 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -34,7 +34,6 @@
namespace android {
-class DetachedBufferHandle;
class GraphicBufferMapper;
// ===========================================================================
@@ -191,11 +190,6 @@
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
- // Sets and takes DetachedBuffer. Should only be called from BufferHub.
- bool isDetachedBuffer() const;
- status_t setDetachedBufferHandle(std::unique_ptr<DetachedBufferHandle> detachedBuffer);
- std::unique_ptr<DetachedBufferHandle> takeDetachedBufferHandle();
-
private:
~GraphicBuffer();
@@ -246,17 +240,6 @@
// match the BufferQueue's internal generation number (set through
// IGBP::setGenerationNumber), attempts to attach the buffer will fail.
uint32_t mGenerationNumber;
-
- // Stores a BufferHub handle that can be used to re-attach this GraphicBuffer back into a
- // BufferHub producer/consumer set. In terms of GraphicBuffer's relationship with BufferHub,
- // there are three different modes:
- // 1. Legacy mode: GraphicBuffer is not backed by BufferHub and mDetachedBufferHandle must be
- // invalid.
- // 2. Detached mode: GraphicBuffer is backed by BufferHub, but not part of a producer/consumer
- // set. In this mode, mDetachedBufferHandle must be valid.
- // 3. Attached mode: GraphicBuffer is backed by BufferHub and it's part of a producer/consumer
- // set. In this mode, mDetachedBufferHandle must be invalid.
- std::unique_ptr<DetachedBufferHandle> mDetachedBufferHandle;
};
}; // namespace android
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index e8bda67..1521e1d 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -29,13 +29,6 @@
}
cc_test {
- name: "GraphicBuffer_test",
- shared_libs: ["libpdx_default_transport", "libui", "libutils"],
- srcs: ["GraphicBuffer_test.cpp"],
- cflags: ["-Wall", "-Werror"],
-}
-
-cc_test {
name: "BufferHubBuffer_test",
header_libs: [
"libbufferhub_headers",
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
deleted file mode 100644
index eb679ac..0000000
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#define LOG_TAG "GraphicBufferTest"
-
-#include <ui/DetachedBufferHandle.h>
-#include <ui/GraphicBuffer.h>
-
-#include <gtest/gtest.h>
-
-namespace android {
-
-namespace {
-
-constexpr uint32_t kTestWidth = 1024;
-constexpr uint32_t kTestHeight = 1;
-constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB;
-constexpr uint32_t kTestLayerCount = 1;
-constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN;
-
-} // namespace
-
-class GraphicBufferTest : public testing::Test {};
-
-TEST_F(GraphicBufferTest, DetachedBuffer) {
- sp<GraphicBuffer> buffer(
- new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount, kTestUsage));
-
- // Currently a newly allocated GraphicBuffer is in legacy mode, i.e. not associated with
- // BufferHub. But this may change in the future.
- EXPECT_FALSE(buffer->isDetachedBuffer());
-
- pdx::LocalChannelHandle channel{nullptr, 1234};
- EXPECT_TRUE(channel.valid());
-
- std::unique_ptr<DetachedBufferHandle> handle = DetachedBufferHandle::Create(std::move(channel));
- EXPECT_FALSE(channel.valid());
- EXPECT_TRUE(handle->isValid());
- EXPECT_TRUE(handle->handle().valid());
-
- buffer->setDetachedBufferHandle(std::move(handle));
- EXPECT_TRUE(handle == nullptr);
- EXPECT_TRUE(buffer->isDetachedBuffer());
-
- handle = buffer->takeDetachedBufferHandle();
- EXPECT_TRUE(handle != nullptr);
- EXPECT_TRUE(handle->isValid());
- EXPECT_FALSE(buffer->isDetachedBuffer());
-}
-
-} // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 18b97db..73ca69b 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -5,7 +5,6 @@
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <ui/BufferHubBuffer.h>
-#include <ui/DetachedBufferHandle.h>
#include <mutex>
#include <thread>
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 1daa4d2..547a669 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -485,58 +485,29 @@
}
// Returns a list of color spaces understood by the vendor EGL driver.
-static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp,
- android_pixel_format format) {
+static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp) {
std::vector<EGLint> colorSpaces;
- if (!dp->hasColorSpaceSupport) return colorSpaces;
- // OpenGL drivers only support sRGB encoding with 8-bit formats.
- // RGB_888 is never returned by getNativePixelFormat, but is included for completeness.
- const bool formatSupportsSRGBEncoding =
- format == HAL_PIXEL_FORMAT_RGBA_8888 || format == HAL_PIXEL_FORMAT_RGBX_8888 ||
- format == HAL_PIXEL_FORMAT_RGB_888;
- const bool formatIsFloatingPoint = format == HAL_PIXEL_FORMAT_RGBA_FP16;
+ // sRGB and linear are always supported when color space support is present.
+ colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
+ colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
- if (formatSupportsSRGBEncoding) {
- // sRGB and linear are always supported when color space support is present.
- colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
- colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
- // DCI-P3 uses the sRGB transfer function, so it's only relevant for 8-bit formats.
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_display_p3")) {
- colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
- }
+ if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3")) {
+ colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
}
-
- // According to the spec, scRGB is only supported for floating point formats.
- // For non-linear scRGB, the application is responsible for applying the
- // transfer function.
- if (formatIsFloatingPoint) {
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_scrgb")) {
- colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT);
- }
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_scrgb_linear")) {
- colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
- }
+ if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_scrgb")) {
+ colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT);
}
-
- // BT2020 can be used with any pixel format. PQ encoding must be applied by the
- // application and does not affect the behavior of OpenGL.
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_bt2020_linear")) {
+ if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_scrgb_linear")) {
+ colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
+ }
+ if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_bt2020_linear")) {
colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT);
}
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_bt2020_pq")) {
+ if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_bt2020_pq")) {
colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
}
-
- // Linear DCI-P3 simply uses different primaries than standard RGB and thus
- // can be used with any pixel format.
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_display_p3_linear")) {
+ if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3_linear")) {
colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
}
return colorSpaces;
@@ -547,18 +518,32 @@
// unmodified.
template <typename AttrType>
static EGLBoolean processAttributes(egl_display_ptr dp, ANativeWindow* window,
- android_pixel_format format, const AttrType* attrib_list,
- EGLint* colorSpace, std::vector<AttrType>* strippedAttribList) {
+ const AttrType* attrib_list, EGLint* colorSpace,
+ std::vector<AttrType>* strippedAttribList) {
for (const AttrType* attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) {
bool copyAttribute = true;
if (attr[0] == EGL_GL_COLORSPACE_KHR) {
- // Fail immediately if the driver doesn't have color space support at all.
- if (!dp->hasColorSpaceSupport) return false;
+ switch (attr[1]) {
+ case EGL_GL_COLORSPACE_LINEAR_KHR:
+ case EGL_GL_COLORSPACE_SRGB_KHR:
+ case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+ case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
+ case EGL_GL_COLORSPACE_SCRGB_EXT:
+ case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT:
+ case EGL_GL_COLORSPACE_BT2020_PQ_EXT:
+ case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
+ // Fail immediately if the driver doesn't have color space support at all.
+ if (!dp->hasColorSpaceSupport) return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ break;
+ default:
+ // BAD_ATTRIBUTE if attr is not any of the EGL_GL_COLORSPACE_*
+ return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
*colorSpace = static_cast<EGLint>(attr[1]);
// Strip the attribute if the driver doesn't understand it.
copyAttribute = false;
- std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp, format);
+ std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp);
for (auto driverColorSpace : driverColorSpaces) {
if (static_cast<EGLint>(attr[1]) == driverColorSpace) {
copyAttribute = true;
@@ -585,10 +570,8 @@
// If the passed color space has wide color gamut, check whether the target native window
// supports wide color.
- const bool colorSpaceIsNarrow =
- *colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
- *colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR ||
- *colorSpace == EGL_UNKNOWN;
+ const bool colorSpaceIsNarrow = *colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
+ *colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR || *colorSpace == EGL_UNKNOWN;
if (window && !colorSpaceIsNarrow) {
bool windowSupportsWideColor = true;
// Ordinarily we'd put a call to native_window_get_wide_color_support
@@ -606,12 +589,12 @@
ALOGE("processAttributes: invalid window (win=%p) "
"failed (%#x) (already connected to another API?)",
window, err);
- return false;
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
}
if (!windowSupportsWideColor) {
// Application has asked for a wide-color colorspace but
// wide-color support isn't available on the display the window is on.
- return false;
+ return setError(EGL_BAD_MATCH, EGL_FALSE);
}
}
return true;
@@ -695,8 +678,7 @@
native_window_set_buffers_smpte2086_metadata(s->getNativeWindow(), &smpteMetadata);
s->resetSmpte2086Metadata();
if (err != 0) {
- ALOGE("error setting native window smpte2086 metadata: %s (%d)",
- strerror(-err), err);
+ ALOGE("error setting native window smpte2086 metadata: %s (%d)", strerror(-err), err);
return EGL_FALSE;
}
}
@@ -706,8 +688,7 @@
native_window_set_buffers_cta861_3_metadata(s->getNativeWindow(), &cta8613Metadata);
s->resetCta8613Metadata();
if (err != 0) {
- ALOGE("error setting native window CTS 861.3 metadata: %s (%d)",
- strerror(-err), err);
+ ALOGE("error setting native window CTS 861.3 metadata: %s (%d)", strerror(-err), err);
return EGL_FALSE;
}
}
@@ -749,10 +730,12 @@
// now select correct colorspace and dataspace based on user's attribute list
EGLint colorSpace = EGL_UNKNOWN;
std::vector<AttrType> strippedAttribList;
- if (!processAttributes<AttrType>(dp, window, format, attrib_list, &colorSpace,
- &strippedAttribList)) {
+ if (!processAttributes<AttrType>(dp, window, attrib_list, &colorSpace, &strippedAttribList)) {
ALOGE("error invalid colorspace: %d", colorSpace);
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ }
+ return EGL_NO_SURFACE;
}
attrib_list = strippedAttribList.data();
@@ -765,13 +748,14 @@
}
android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace);
- if (dataSpace != HAL_DATASPACE_UNKNOWN) {
- err = native_window_set_buffers_data_space(window, dataSpace);
- if (err != 0) {
- ALOGE("error setting native window pixel dataSpace: %s (%d)", strerror(-err), err);
- native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
- return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
- }
+ // Set dataSpace even if it could be HAL_DATASPACE_UNKNOWN.
+ // HAL_DATASPACE_UNKNOWN is the default value, but it may have changed
+ // at this point.
+ err = native_window_set_buffers_data_space(window, dataSpace);
+ if (err != 0) {
+ ALOGE("error setting native window pixel dataSpace: %s (%d)", strerror(-err), err);
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
}
@@ -873,9 +857,8 @@
return EGL_NO_SURFACE;
}
-EGLSurface eglCreatePbufferSurfaceImpl( EGLDisplay dpy, EGLConfig config,
- const EGLint *attrib_list)
-{
+EGLSurface eglCreatePbufferSurfaceImpl(EGLDisplay dpy, EGLConfig config,
+ const EGLint* attrib_list) {
egl_connection_t* cnx = nullptr;
egl_display_ptr dp = validate_display_connection(dpy, cnx);
if (dp) {
@@ -886,35 +869,30 @@
// Select correct colorspace based on user's attribute list
EGLint colorSpace = EGL_UNKNOWN;
std::vector<EGLint> strippedAttribList;
- if (!processAttributes(dp, nullptr, format, attrib_list, &colorSpace,
- &strippedAttribList)) {
+ if (!processAttributes(dp, nullptr, attrib_list, &colorSpace, &strippedAttribList)) {
ALOGE("error invalid colorspace: %d", colorSpace);
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ return EGL_NO_SURFACE;
}
attrib_list = strippedAttribList.data();
- EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
- dp->disp.dpy, config, attrib_list);
+ EGLSurface surface = cnx->egl.eglCreatePbufferSurface(dp->disp.dpy, config, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s =
- new egl_surface_t(dp.get(), config, nullptr, surface,
- getReportedColorSpace(colorSpace), cnx);
+ egl_surface_t* s = new egl_surface_t(dp.get(), config, nullptr, surface,
+ getReportedColorSpace(colorSpace), cnx);
return s;
}
}
return EGL_NO_SURFACE;
}
-EGLBoolean eglDestroySurfaceImpl(EGLDisplay dpy, EGLSurface surface)
-{
+EGLBoolean eglDestroySurfaceImpl(EGLDisplay dpy, EGLSurface surface) {
const egl_display_ptr dp = validate_display(dpy);
if (!dp) return EGL_FALSE;
SurfaceRef _s(dp.get(), surface);
- if (!_s.get())
- return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
- egl_surface_t * const s = get_surface(surface);
+ egl_surface_t* const s = get_surface(surface);
EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
if (result == EGL_TRUE) {
_s.terminate();
@@ -922,17 +900,15 @@
return result;
}
-EGLBoolean eglQuerySurfaceImpl( EGLDisplay dpy, EGLSurface surface,
- EGLint attribute, EGLint *value)
-{
+EGLBoolean eglQuerySurfaceImpl(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
+ EGLint* value) {
const egl_display_ptr dp = validate_display(dpy);
if (!dp) return EGL_FALSE;
SurfaceRef _s(dp.get(), surface);
- if (!_s.get())
- return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
- egl_surface_t const * const s = get_surface(surface);
+ egl_surface_t const* const s = get_surface(surface);
if (s->getColorSpaceAttribute(attribute, value)) {
return EGL_TRUE;
} else if (s->getSmpte2086Attribute(attribute, value)) {
diff --git a/opengl/libs/libEGL.map.txt b/opengl/libs/libEGL.map.txt
index fa26e33..b2d7957 100644
--- a/opengl/libs/libEGL.map.txt
+++ b/opengl/libs/libEGL.map.txt
@@ -3,23 +3,30 @@
eglBindAPI;
eglBindTexImage;
eglChooseConfig;
+ eglClientWaitSync; # introduced=29
eglClientWaitSyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
eglCopyBuffers;
eglCreateContext;
+ eglCreateImage; # introduced=29
eglCreateImageKHR;
eglCreateNativeClientBufferANDROID; # introduced=24
eglCreatePbufferFromClientBuffer;
eglCreatePbufferSurface;
eglCreatePixmapSurface;
+ eglCreatePlatformPixmapSurface; # introduced=29
+ eglCreatePlatformWindowSurface; # introduced=29
eglCreateStreamFromFileDescriptorKHR; # introduced=23
eglCreateStreamKHR; # introduced=23
eglCreateStreamProducerSurfaceKHR; # introduced=23
+ eglCreateSync; # introduced=29
eglCreateSyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
eglCreateWindowSurface;
eglDestroyContext;
+ eglDestroyImage; # introduced=29
eglDestroyImageKHR;
eglDestroyStreamKHR; # introduced=23
eglDestroySurface;
+ eglDestroySync; # introduced=29
eglDestroySyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
eglDupNativeFenceFDANDROID; # vndk
eglGetConfigAttrib;
@@ -30,8 +37,10 @@
eglGetDisplay;
eglGetError;
eglGetNativeClientBufferANDROID; # introduced=26
+ eglGetPlatformDisplay; # introduced=29
eglGetProcAddress;
eglGetStreamFileDescriptorKHR; # introduced=23
+ eglGetSyncAttrib; # introduced=29
eglGetSyncAttribKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
eglGetSystemTimeFrequencyNV; # introduced-arm=14 introduced-arm64=21 introduced-mips=14 introduced-mips64=21 introduced-x86=14 introduced-x86_64=21
eglGetSystemTimeNV; # introduced-arm=14 introduced-arm64=21 introduced-mips=14 introduced-mips64=21 introduced-x86=14 introduced-x86_64=21
@@ -64,6 +73,7 @@
eglWaitClient;
eglWaitGL;
eglWaitNative;
+ eglWaitSync; # introduced=29
eglWaitSyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
local:
*;
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 2cad986..2e984d9 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -2545,6 +2545,9 @@
uint32_t policyFlags = args->policyFlags;
int32_t flags = args->flags;
int32_t metaState = args->metaState;
+ // InputDispatcher tracks and generates key repeats on behalf of
+ // whatever notifies it, so repeatCount should always be set to 0
+ constexpr int32_t repeatCount = 0;
if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
policyFlags |= POLICY_FLAG_VIRTUAL;
flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
@@ -2560,7 +2563,7 @@
KeyEvent event;
event.initialize(args->deviceId, args->source, args->displayId, args->action,
- flags, keyCode, args->scanCode, metaState, 0,
+ flags, keyCode, args->scanCode, metaState, repeatCount,
args->downTime, args->eventTime);
android::base::Timer t;
@@ -2585,7 +2588,6 @@
mLock.lock();
}
- int32_t repeatCount = 0;
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, args->displayId, policyFlags,
args->action, flags, keyCode, args->scanCode,
@@ -2756,7 +2758,7 @@
accelerateMetaShortcuts(keyEvent.getDeviceId(), action,
/*byref*/ keyCode, /*byref*/ metaState);
keyEvent.initialize(keyEvent.getDeviceId(), keyEvent.getSource(), keyEvent.getDisplayId(),
- action, flags, keyCode, keyEvent.getScanCode(), metaState, 0,
+ action, flags, keyCode, keyEvent.getScanCode(), metaState, keyEvent.getRepeatCount(),
keyEvent.getDownTime(), keyEvent.getEventTime());
if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 5df8ade..73098bf 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -470,8 +470,7 @@
}
// TODO(marissaw): properly support mTimeStats
- mTimeStats.setLayerName(layerID, getName().c_str());
- mTimeStats.setPostTime(layerID, getFrameNumber(), latchTime);
+ mTimeStats.setPostTime(layerID, getFrameNumber(), getName().c_str(), latchTime);
mTimeStats.setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime());
mTimeStats.setLatchTime(layerID, getFrameNumber(), latchTime);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 88c3c8a..2e564e7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1476,9 +1476,8 @@
void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
FrameEventHistoryDelta* outDelta) {
if (newTimestamps) {
- const int32_t layerID = getSequence();
- mTimeStats.setLayerName(layerID, getName().c_str());
- mTimeStats.setPostTime(layerID, newTimestamps->frameNumber, newTimestamps->postedTime);
+ mTimeStats.setPostTime(getSequence(), newTimestamps->frameNumber, getName().c_str(),
+ newTimestamps->postedTime);
}
Mutex::Autolock lock(mFrameEventHistoryMutex);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fc8ca54..5c31ada 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -196,8 +196,10 @@
int SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault;
bool SurfaceFlinger::useColorManagement;
bool SurfaceFlinger::useContextPriority;
-Dataspace SurfaceFlinger::compositionDataSpace = Dataspace::V0_SRGB;
-ui::PixelFormat SurfaceFlinger::compositionPixelFormat = ui::PixelFormat::RGBA_8888;
+Dataspace SurfaceFlinger::defaultCompositionDataspace = Dataspace::V0_SRGB;
+ui::PixelFormat SurfaceFlinger::defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
+Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRGB;
+ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
std::string getHwcServiceName() {
char value[PROPERTY_VALUE_MAX] = {};
@@ -303,10 +305,13 @@
auto surfaceFlingerConfigsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService();
if (surfaceFlingerConfigsServiceV1_2) {
surfaceFlingerConfigsServiceV1_2->getCompositionPreference(
- [&](Dataspace tmpDataSpace, ui::PixelFormat tmpPixelFormat) {
- compositionDataSpace = tmpDataSpace;
- compositionPixelFormat = tmpPixelFormat;
- });
+ [&](auto tmpDefaultDataspace, auto tmpDefaultPixelFormat,
+ auto tmpWideColorGamutDataspace, auto tmpWideColorGamutPixelFormat) {
+ defaultCompositionDataspace = tmpDefaultDataspace;
+ defaultCompositionPixelFormat = tmpDefaultPixelFormat;
+ wideColorGamutCompositionDataspace = tmpWideColorGamutDataspace;
+ wideColorGamutCompositionPixelFormat = tmpWideColorGamutPixelFormat;
+ });
}
useContextPriority = getBool<ISurfaceFlingerConfigs,
@@ -638,8 +643,8 @@
// TODO(b/77156734): We need to stop casting and use HAL types when possible.
getBE().mRenderEngine =
- renderengine::RenderEngine::create(static_cast<int32_t>(compositionPixelFormat),
- renderEngineFeature);
+ renderengine::RenderEngine::create(static_cast<int32_t>(defaultCompositionPixelFormat),
+ renderEngineFeature);
LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
@@ -1157,10 +1162,14 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::getCompositionPreference(Dataspace* outDataSpace,
- ui::PixelFormat* outPixelFormat) const {
- *outDataSpace = compositionDataSpace;
- *outPixelFormat = compositionPixelFormat;
+status_t SurfaceFlinger::getCompositionPreference(
+ Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
+ Dataspace* outWideColorGamutDataspace,
+ ui::PixelFormat* outWideColorGamutPixelFormat) const {
+ *outDataspace = defaultCompositionDataspace;
+ *outPixelFormat = defaultCompositionPixelFormat;
+ *outWideColorGamutDataspace = wideColorGamutCompositionDataspace;
+ *outWideColorGamutPixelFormat = wideColorGamutCompositionPixelFormat;
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 73c9d95..d60765c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -294,8 +294,14 @@
// The data space and pixel format that SurfaceFlinger expects hardware composer
// to composite efficiently. Meaning under most scenarios, hardware composer
// will accept layers with the data space and pixel format.
- static ui::Dataspace compositionDataSpace;
- static ui::PixelFormat compositionPixelFormat;
+ static ui::Dataspace defaultCompositionDataspace;
+ static ui::PixelFormat defaultCompositionPixelFormat;
+
+ // The data space and pixel format that SurfaceFlinger expects hardware composer
+ // to composite efficiently for wide color gamut surfaces. Meaning under most scenarios,
+ // hardware composer will accept layers with the data space and pixel format.
+ static ui::Dataspace wideColorGamutCompositionDataspace;
+ static ui::PixelFormat wideColorGamutCompositionPixelFormat;
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
@@ -460,9 +466,10 @@
virtual status_t enableVSyncInjections(bool enable);
virtual status_t injectVSync(nsecs_t when);
virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const;
- status_t getCompositionPreference(ui::Dataspace* outDataSpace,
- ui::PixelFormat* outPixelFormat) const override;
virtual bool isColorManagementUsed() const;
+ status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
+ ui::Dataspace* outWideColorGamutDataspace,
+ ui::PixelFormat* outWideColorGamutPixelFormat) const override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index c219afd..ace7c1b 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -241,25 +241,18 @@
return std::regex_match(layerName.begin(), layerName.end(), layerNameRegex);
}
-void TimeStats::setLayerName(int32_t layerID, const std::string& layerName) {
+void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
+ nsecs_t postTime) {
if (!mEnabled.load()) return;
ATRACE_CALL();
- ALOGV("[%d]-[%s]", layerID, layerName.c_str());
+ ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerID, frameNumber, layerName.c_str(),
+ postTime);
std::lock_guard<std::mutex> lock(mMutex);
if (!mTimeStatsTracker.count(layerID) && layerNameIsValid(layerName)) {
mTimeStatsTracker[layerID].layerName = layerName;
}
-}
-
-void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, nsecs_t postTime) {
- if (!mEnabled.load()) return;
-
- ATRACE_CALL();
- ALOGV("[%d]-[%" PRIu64 "]-PostTime[%" PRId64 "]", layerID, frameNumber, postTime);
-
- std::lock_guard<std::mutex> lock(mMutex);
if (!mTimeStatsTracker.count(layerID)) return;
LayerRecord& layerRecord = mTimeStatsTracker[layerID];
if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) {
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index d1e554c..184bf40 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -86,8 +86,8 @@
void incrementMissedFrames();
void incrementClientCompositionFrames();
- void setLayerName(int32_t layerID, const std::string& layerName);
- void setPostTime(int32_t layerID, uint64_t frameNumber, nsecs_t postTime);
+ void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
+ nsecs_t postTime);
void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime);
void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime);
void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime);
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index ea9bb1f..5debd3d 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -45,7 +45,10 @@
"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
],
export_include_dirs: ["include"],
- header_libs: ["libdvr_headers"],
+ header_libs: [
+ "libdvr_headers",
+ "libnativewindow_headers",
+ ],
shared_libs: sharedLibraries,
static_libs: [
"libbufferhub",
diff --git a/services/vr/bufferhubd/buffer_channel.cpp b/services/vr/bufferhubd/buffer_channel.cpp
index a2fa0f1..589b31a 100644
--- a/services/vr/bufferhubd/buffer_channel.cpp
+++ b/services/vr/bufferhubd/buffer_channel.cpp
@@ -49,9 +49,9 @@
BufferHubChannel::BufferInfo BufferChannel::GetBufferInfo() const {
return BufferInfo(
- buffer_id(), /*consumer_count=*/0, buffer_node_->buffer().width(),
- buffer_node_->buffer().height(), buffer_node_->buffer().layer_count(),
- buffer_node_->buffer().format(), buffer_node_->buffer().usage(),
+ buffer_id(), /*consumer_count=*/0, buffer_node_->buffer_desc().width,
+ buffer_node_->buffer_desc().height, buffer_node_->buffer_desc().layers,
+ buffer_node_->buffer_desc().format, buffer_node_->buffer_desc().usage,
/*pending_count=*/0, /*state=*/0, /*signaled_mask=*/0,
/*index=*/0);
}
@@ -85,17 +85,17 @@
// TODO(b/112057680) Move away from the GraphicBuffer-based IonBuffer.
return BufferTraits<BorrowedHandle>{
- /*buffer_handle=*/buffer_node_->buffer().handle(),
+ /*buffer_handle=*/buffer_node_->buffer_handle(),
/*metadata_handle=*/buffer_node_->metadata().ashmem_handle().Borrow(),
/*id=*/buffer_id(),
/*client_state_mask=*/client_state_mask_,
/*metadata_size=*/buffer_node_->metadata().metadata_size(),
- /*width=*/buffer_node_->buffer().width(),
- /*height=*/buffer_node_->buffer().height(),
- /*layer_count=*/buffer_node_->buffer().layer_count(),
- /*format=*/buffer_node_->buffer().format(),
- /*usage=*/buffer_node_->buffer().usage(),
- /*stride=*/buffer_node_->buffer().stride(),
+ /*width=*/buffer_node_->buffer_desc().width,
+ /*height=*/buffer_node_->buffer_desc().height,
+ /*layer_count=*/buffer_node_->buffer_desc().layers,
+ /*format=*/buffer_node_->buffer_desc().format,
+ /*usage=*/buffer_node_->buffer_desc().usage,
+ /*stride=*/buffer_node_->buffer_desc().stride,
/*acquire_fence_fd=*/BorrowedHandle{},
/*released_fence_fd=*/BorrowedHandle{}};
}
diff --git a/services/vr/bufferhubd/buffer_node.cpp b/services/vr/bufferhubd/buffer_node.cpp
index 1eba4ae..31c6ef0 100644
--- a/services/vr/bufferhubd/buffer_node.cpp
+++ b/services/vr/bufferhubd/buffer_node.cpp
@@ -1,6 +1,9 @@
#include <errno.h>
+
+#include <private/dvr/IBufferHub.h>
#include <private/dvr/buffer_hub_defs.h>
#include <private/dvr/buffer_node.h>
+#include <ui/GraphicBufferAllocator.h>
namespace android {
namespace dvr {
@@ -19,14 +22,26 @@
BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layer_count,
uint32_t format, uint64_t usage,
size_t user_metadata_size) {
- if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
- ALOGE(
- "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
- "buffer: %s",
- strerror(-ret));
+ uint32_t out_stride = 0;
+ // graphicBufferId is not used in GraphicBufferAllocator::allocate
+ int ret = GraphicBufferAllocator::get().allocate(
+ width, height, format, layer_count, usage,
+ const_cast<const native_handle_t**>(&buffer_handle_), &out_stride,
+ /*graphicBufferId=*/0, IBufferHub::getServiceName());
+
+ if (ret != OK || buffer_handle_ == nullptr) {
+ ALOGE("BufferNode::BufferNode: Failed to allocate buffer: %s",
+ strerror(-ret));
return;
}
+ buffer_desc_.width = width;
+ buffer_desc_.height = height;
+ buffer_desc_.layers = layer_count;
+ buffer_desc_.format = format;
+ buffer_desc_.usage = usage;
+ buffer_desc_.stride = out_stride;
+
metadata_ = BufferHubMetadata::Create(user_metadata_size);
if (!metadata_.IsValid()) {
ALOGE("BufferNode::BufferNode: Failed to allocate metadata.");
@@ -35,6 +50,17 @@
InitializeMetadata();
}
+// Free the handle
+BufferNode::~BufferNode() {
+ if (buffer_handle_ != nullptr) {
+ status_t ret = GraphicBufferAllocator::get().free(buffer_handle_);
+ if (ret != OK) {
+ ALOGE("BufferNode::~BufferNode: Failed to free handle; Got error: %d",
+ ret);
+ }
+ }
+}
+
uint64_t BufferNode::GetActiveClientsBitMask() const {
return active_clients_bit_mask_->load(std::memory_order_acquire);
}
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_node.h b/services/vr/bufferhubd/include/private/dvr/buffer_node.h
index 4f356f0..bc0a34e 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_node.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_node.h
@@ -1,6 +1,7 @@
#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_
#define ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_
+#include <android/hardware_buffer.h>
#include <private/dvr/ion_buffer.h>
#include <ui/BufferHubMetadata.h>
@@ -13,14 +14,16 @@
BufferNode(uint32_t width, uint32_t height, uint32_t layer_count,
uint32_t format, uint64_t usage, size_t user_metadata_size);
- // Returns whether the object holds a valid graphic buffer.
- bool IsValid() const { return buffer_.IsValid() && metadata_.IsValid(); }
+ ~BufferNode();
+
+ // Returns whether the object holds a valid metadata.
+ bool IsValid() const { return metadata_.IsValid(); }
size_t user_metadata_size() const { return metadata_.user_metadata_size(); }
- // Accessors of the IonBuffer.
- IonBuffer& buffer() { return buffer_; }
- const IonBuffer& buffer() const { return buffer_; }
+ // Accessors of the buffer description and handle
+ const native_handle_t* buffer_handle() const { return buffer_handle_; }
+ const AHardwareBuffer_Desc& buffer_desc() const { return buffer_desc_; }
// Accessors of metadata.
const BufferHubMetadata& metadata() const { return metadata_; }
@@ -48,7 +51,8 @@
void InitializeMetadata();
// Gralloc buffer handles.
- IonBuffer buffer_;
+ native_handle_t* buffer_handle_;
+ AHardwareBuffer_Desc buffer_desc_;
// Metadata in shared memory.
BufferHubMetadata metadata_;
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
index a80691f..c77d2d2 100644
--- a/services/vr/bufferhubd/tests/Android.bp
+++ b/services/vr/bufferhubd/tests/Android.bp
@@ -33,7 +33,10 @@
"-DTRACE=0",
"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
],
- header_libs: ["libdvr_headers"],
+ header_libs: [
+ "libdvr_headers",
+ "libnativewindow_headers",
+ ],
static_libs: [
"libbufferhub",
"libbufferhubd",
diff --git a/services/vr/bufferhubd/tests/buffer_node-test.cpp b/services/vr/bufferhubd/tests/buffer_node-test.cpp
index 6671e97..30ecbec 100644
--- a/services/vr/bufferhubd/tests/buffer_node-test.cpp
+++ b/services/vr/bufferhubd/tests/buffer_node-test.cpp
@@ -2,12 +2,15 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <private/dvr/buffer_node.h>
+#include <ui/GraphicBufferMapper.h>
namespace android {
namespace dvr {
namespace {
+using testing::NotNull;
+
const uint32_t kWidth = 640;
const uint32_t kHeight = 480;
const uint32_t kLayerCount = 1;
@@ -35,6 +38,16 @@
TEST_F(BufferNodeTest, TestCreateBufferNode) {
EXPECT_EQ(buffer_node->user_metadata_size(), kUserMetadataSize);
+ // Test the handle just allocated is good (i.e. able to be imported)
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ const native_handle_t* outHandle;
+ status_t ret = mapper.importBuffer(
+ buffer_node->buffer_handle(), buffer_node->buffer_desc().width,
+ buffer_node->buffer_desc().height, buffer_node->buffer_desc().layers,
+ buffer_node->buffer_desc().format, buffer_node->buffer_desc().usage,
+ buffer_node->buffer_desc().stride, &outHandle);
+ EXPECT_EQ(ret, OK);
+ EXPECT_THAT(outHandle, NotNull());
}
TEST_F(BufferNodeTest, TestAddNewActiveClientsBitToMask_twoNewClients) {