Merge "add function to traversal the crates"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 9e3520d..f8a68b4 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -31,6 +31,7 @@
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/mount.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
@@ -87,6 +88,9 @@
static constexpr const char* kCpPath = "/system/bin/cp";
static constexpr const char* kXattrDefault = "user.default";
+static constexpr const char* kDataMirrorCePath = "/data_mirror/data_ce";
+static constexpr const char* kDataMirrorDePath = "/data_mirror/data_de";
+
static constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M
static constexpr const char* PKG_LIB_POSTFIX = "/lib";
@@ -100,6 +104,13 @@
static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode";
static constexpr const char* kFuseProp = "persist.sys.fuse";
+/**
+ * Property to control if app data isolation is enabled.
+ */
+static constexpr const char* kAppDataIsolationEnabledProperty = "persist.zygote.app_data_isolation";
+
+static std::atomic<bool> sAppDataIsolationEnabled(false);
+
namespace {
constexpr const char* kDump = "android.permission.DUMP";
@@ -259,6 +270,8 @@
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
+ sAppDataIsolationEnabled = android::base::GetBoolProperty(
+ kAppDataIsolationEnabledProperty, false);
return android::OK;
}
@@ -451,9 +464,12 @@
// And return the CE inode of the top-level data directory so we can
// clear contents while CE storage is locked
- if ((_aidl_return != nullptr)
- && get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) != 0) {
- return error("Failed to get_path_inode for " + path);
+ if (_aidl_return != nullptr) {
+ ino_t result;
+ if (get_path_inode(path, &result) != 0) {
+ return error("Failed to get_path_inode for " + path);
+ }
+ *_aidl_return = static_cast<uint64_t>(result);
}
}
if (flags & FLAG_STORAGE_DE) {
@@ -2690,6 +2706,89 @@
return ok();
}
+// Mount volume's CE and DE storage to mirror
+binder::Status InstalldNativeService::onPrivateVolumeMounted(
+ const std::unique_ptr<std::string>& uuid) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID(uuid);
+ if (!sAppDataIsolationEnabled) {
+ return ok();
+ }
+ if (!uuid) {
+ return error("Should not happen, mounting uuid == null");
+ }
+
+ const char* uuid_ = uuid->c_str();
+ // Mount CE mirror
+ std::string mirrorVolCePath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_));
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+ if (fs_prepare_dir(mirrorVolCePath.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
+ return error("Failed to create CE mirror");
+ }
+ auto cePath = StringPrintf("%s/user_ce", create_data_path(uuid_).c_str());
+ if (TEMP_FAILURE_RETRY(mount(cePath.c_str(), mirrorVolCePath.c_str(), NULL,
+ MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) {
+ return error("Failed to mount " + mirrorVolCePath);
+ }
+
+ // Mount DE mirror
+ std::string mirrorVolDePath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_));
+ if (fs_prepare_dir(mirrorVolDePath.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
+ return error("Failed to create DE mirror");
+ }
+ auto dePath = StringPrintf("%s/user_de", create_data_path(uuid_).c_str());
+ if (TEMP_FAILURE_RETRY(mount(dePath.c_str(), mirrorVolDePath.c_str(), NULL,
+ MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) {
+ return error("Failed to mount " + mirrorVolDePath);
+ }
+ return ok();
+}
+
+// Unmount volume's CE and DE storage from mirror
+binder::Status InstalldNativeService::onPrivateVolumeRemoved(
+ const std::unique_ptr<std::string>& uuid) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID(uuid);
+ if (!sAppDataIsolationEnabled) {
+ return ok();
+ }
+ if (!uuid) {
+ // It happens when private volume failed to mount.
+ LOG(INFO) << "Ignore unmount uuid=null";
+ return ok();
+ }
+ const char* uuid_ = uuid->c_str();
+
+ binder::Status res = ok();
+
+ std::string mirrorCeVolPath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_));
+ std::string mirrorDeVolPath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_));
+
+ // Unmount CE storage
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+ if (TEMP_FAILURE_RETRY(umount(mirrorCeVolPath.c_str())) != 0) {
+ if (errno != ENOENT) {
+ res = error(StringPrintf("Failed to umount %s %s", mirrorCeVolPath.c_str(),
+ strerror(errno)));
+ }
+ }
+ if (delete_dir_contents_and_dir(mirrorCeVolPath, true) != 0) {
+ res = error("Failed to delete " + mirrorCeVolPath);
+ }
+
+ // Unmount DE storage
+ if (TEMP_FAILURE_RETRY(umount(mirrorDeVolPath.c_str())) != 0) {
+ if (errno != ENOENT) {
+ res = error(StringPrintf("Failed to umount %s %s", mirrorDeVolPath.c_str(),
+ strerror(errno)));
+ }
+ }
+ if (delete_dir_contents_and_dir(mirrorDeVolPath, true) != 0) {
+ res = error("Failed to delete " + mirrorDeVolPath);
+ }
+ return res;
+}
+
std::string InstalldNativeService::findDataMediaPath(
const std::unique_ptr<std::string>& uuid, userid_t userid) {
std::lock_guard<std::recursive_mutex> lock(mMountsLock);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index aff3733..bf11002 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -156,6 +156,8 @@
binder::Status invalidateMounts();
binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid,
bool* _aidl_return);
+ binder::Status onPrivateVolumeMounted(const std::unique_ptr<std::string>& volumeUuid);
+ binder::Status onPrivateVolumeRemoved(const std::unique_ptr<std::string>& volumeUuid);
binder::Status prepareAppProfile(const std::string& packageName,
int32_t userId, int32_t appId, const std::string& profileName,
diff --git a/cmds/installd/QuotaUtils.cpp b/cmds/installd/QuotaUtils.cpp
index b238dd3..a71e01c 100644
--- a/cmds/installd/QuotaUtils.cpp
+++ b/cmds/installd/QuotaUtils.cpp
@@ -61,6 +61,10 @@
std::getline(in, target, ' ');
std::getline(in, ignored);
+ if (target.compare(0, 13, "/data_mirror/") == 0) {
+ continue;
+ }
+
if (source.compare(0, 11, "/dev/block/") == 0) {
struct dqblk dq;
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index f6a4530..891b26d 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -117,6 +117,8 @@
int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags);
void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, long ceSnapshotInode, int snapshotId, int storageFlags);
+ void onPrivateVolumeMounted(@nullable @utf8InCpp String volumeUuid);
+ void onPrivateVolumeRemoved(@nullable @utf8InCpp String volumeUuid);
void migrateLegacyObbData();
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
index 7871667..2ef97a3 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -421,13 +421,41 @@
}
/**
+ * Convenience API for writing a non-null parcelable.
+ */
+template <typename P>
+static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) {
+ binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null
+ if (status != STATUS_OK) {
+ return status;
+ }
+ return p.writeToParcel(parcel);
+}
+
+/**
+ * Convenience API for reading a non-null parcelable.
+ */
+template <typename P>
+static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) {
+ int32_t null;
+ binder_status_t status = AParcel_readInt32(parcel, &null);
+ if (status != STATUS_OK) {
+ return status;
+ }
+ if (null == 0) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+ return p->readFromParcel(parcel);
+}
+
+/**
* Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
*/
template <typename P>
binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData,
size_t index) {
const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData);
- return vector->at(index).writeToParcel(parcel);
+ return AParcel_writeParcelable(parcel, vector->at(index));
}
/**
@@ -437,7 +465,7 @@
binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData,
size_t index) {
std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData);
- return vector->at(index).readFromParcel(parcel);
+ return AParcel_readParcelable(parcel, &vector->at(index));
}
/**
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 34254e0..4f96ad3 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -62,8 +62,11 @@
class ComposerCallbackBridge : public Hwc2::IComposerCallback {
public:
- ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)
- : mCallback(callback), mSequenceId(sequenceId) {}
+ ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId,
+ bool vsyncSwitchingSupported)
+ : mCallback(callback),
+ mSequenceId(sequenceId),
+ mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
Return<void> onHotplug(Hwc2::Display display,
IComposerCallback::Connection conn) override
@@ -81,15 +84,23 @@
Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
{
- mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
+ if (!mVsyncSwitchingSupported) {
+ mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
+ } else {
+ ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
+ }
return Void();
}
Return<void> onVsync_2_4(Hwc2::Display display, int64_t timestamp,
Hwc2::VsyncPeriodNanos vsyncPeriodNanos) override {
- // TODO(b/140201379): use vsyncPeriodNanos in the new DispSync
- mCallback->onVsyncReceived(mSequenceId, display, timestamp,
- std::make_optional(vsyncPeriodNanos));
+ if (mVsyncSwitchingSupported) {
+ // TODO(b/140201379): use vsyncPeriodNanos in the new DispSync
+ mCallback->onVsyncReceived(mSequenceId, display, timestamp,
+ std::make_optional(vsyncPeriodNanos));
+ } else {
+ ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
+ }
return Void();
}
@@ -107,6 +118,7 @@
private:
ComposerCallback* mCallback;
int32_t mSequenceId;
+ const bool mVsyncSwitchingSupported;
};
} // namespace anonymous
@@ -126,7 +138,8 @@
}
mRegisteredCallback = true;
sp<ComposerCallbackBridge> callbackBridge(
- new ComposerCallbackBridge(callback, sequenceId));
+ new ComposerCallbackBridge(callback, sequenceId,
+ mComposer->isVsyncPeriodSwitchSupported()));
mComposer->registerCallback(callbackBridge);
}
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 38a80a7..6598bd8 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -18,26 +18,139 @@
#include "Client.h"
#include "Layer.h"
+#include <gui/IProducerListener.h>
+
+#undef LOG_TAG
+#define LOG_TAG "RefreshRateOverlay"
+
namespace android {
+void RefreshRateOverlay::SevenSegmentDrawer::drawRect(const Rect& r, const half4& color,
+ const sp<GraphicBuffer>& buffer,
+ uint8_t* pixels) {
+ for (int32_t j = r.top; j < r.bottom; j++) {
+ if (j >= buffer->getHeight()) {
+ break;
+ }
+
+ for (int32_t i = r.left; i < r.right; i++) {
+ if (i >= buffer->getWidth()) {
+ break;
+ }
+
+ uint8_t* iter = pixels + 4 * (i + (buffer->getStride() * j));
+ iter[0] = uint8_t(color.r * 255);
+ iter[1] = uint8_t(color.g * 255);
+ iter[2] = uint8_t(color.b * 255);
+ iter[3] = uint8_t(color.a * 255);
+ }
+ }
+}
+
+void RefreshRateOverlay::SevenSegmentDrawer::drawSegment(Segment segment, int left,
+ const half4& color,
+ const sp<GraphicBuffer>& buffer,
+ uint8_t* pixels) {
+ const Rect rect = [&]() {
+ switch (segment) {
+ case Segment::Upper:
+ return Rect(left, 0, left + DIGIT_WIDTH, DIGIT_SPACE);
+ case Segment::UpperLeft:
+ return Rect(left, 0, left + DIGIT_SPACE, DIGIT_HEIGHT / 2);
+ case Segment::UpperRight:
+ return Rect(left + DIGIT_WIDTH - DIGIT_SPACE, 0, left + DIGIT_WIDTH,
+ DIGIT_HEIGHT / 2);
+ case Segment::Middle:
+ return Rect(left, DIGIT_HEIGHT / 2 - DIGIT_SPACE / 2, left + DIGIT_WIDTH,
+ DIGIT_HEIGHT / 2 + DIGIT_SPACE / 2);
+ case Segment::LowerLeft:
+ return Rect(left, DIGIT_HEIGHT / 2, left + DIGIT_SPACE, DIGIT_HEIGHT);
+ case Segment::LowerRight:
+ return Rect(left + DIGIT_WIDTH - DIGIT_SPACE, DIGIT_HEIGHT / 2, left + DIGIT_WIDTH,
+ DIGIT_HEIGHT);
+ case Segment::Buttom:
+ return Rect(left, DIGIT_HEIGHT - DIGIT_SPACE, left + DIGIT_WIDTH, DIGIT_HEIGHT);
+ }
+ }();
+
+ drawRect(rect, color, buffer, pixels);
+}
+
+void RefreshRateOverlay::SevenSegmentDrawer::drawDigit(int digit, int left, const half4& color,
+ const sp<GraphicBuffer>& buffer,
+ uint8_t* pixels) {
+ if (digit < 0 || digit > 9) return;
+
+ if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 7 ||
+ digit == 8 || digit == 9)
+ drawSegment(Segment::Upper, left, color, buffer, pixels);
+ if (digit == 0 || digit == 4 || digit == 5 || digit == 6 || digit == 8 || digit == 9)
+ drawSegment(Segment::UpperLeft, left, color, buffer, pixels);
+ if (digit == 0 || digit == 1 || digit == 2 || digit == 3 || digit == 4 || digit == 7 ||
+ digit == 8 || digit == 9)
+ drawSegment(Segment::UpperRight, left, color, buffer, pixels);
+ if (digit == 2 || digit == 3 || digit == 4 || digit == 5 || digit == 6 || digit == 8 ||
+ digit == 9)
+ drawSegment(Segment::Middle, left, color, buffer, pixels);
+ if (digit == 0 || digit == 2 || digit == 6 || digit == 8)
+ drawSegment(Segment::LowerLeft, left, color, buffer, pixels);
+ if (digit == 0 || digit == 1 || digit == 3 || digit == 4 || digit == 5 || digit == 6 ||
+ digit == 7 || digit == 8 || digit == 9)
+ drawSegment(Segment::LowerRight, left, color, buffer, pixels);
+ if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 8 ||
+ digit == 9)
+ drawSegment(Segment::Buttom, left, color, buffer, pixels);
+}
+
+sp<GraphicBuffer> RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number,
+ const half4& color) {
+ if (number < 0 || number > 1000) return nullptr;
+
+ const auto hundreds = number / 100;
+ const auto tens = (number / 10) % 10;
+ const auto ones = number % 10;
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ GRALLOC_USAGE_SW_WRITE_RARELY, "RefreshRateOverlayBuffer");
+ uint8_t* pixels;
+ buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
+ int left = 0;
+ if (hundreds != 0) {
+ drawDigit(hundreds, left, color, buffer, pixels);
+ left += DIGIT_WIDTH + DIGIT_SPACE;
+ }
+
+ if (tens != 0) {
+ drawDigit(tens, left, color, buffer, pixels);
+ left += DIGIT_WIDTH + DIGIT_SPACE;
+ }
+
+ drawDigit(ones, left, color, buffer, pixels);
+ buffer->unlock();
+ return buffer;
+}
+
RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger)
: mFlinger(flinger), mClient(new Client(&mFlinger)) {
createLayer();
+ primeCache();
}
bool RefreshRateOverlay::createLayer() {
const status_t ret =
- mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0,
- PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor,
- LayerMetadata(), &mIBinder, &mGbp, nullptr);
+ mFlinger.createLayer(String8("RefreshRateOverlay"), mClient,
+ SevenSegmentDrawer::getWidth(), SevenSegmentDrawer::getHeight(),
+ PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceBufferState, LayerMetadata(),
+ &mIBinder, &mGbp, nullptr);
if (ret) {
- ALOGE("failed to create color layer");
+ ALOGE("failed to create buffer state layer");
return false;
}
Mutex::Autolock _l(mFlinger.mStateLock);
mLayer = mClient->getLayerUser(mIBinder);
- mLayer->setCrop_legacy(Rect(50, 70, 200, 100));
// setting Layer's Z requires resorting layersSortedByZ
ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer);
@@ -49,9 +162,41 @@
return true;
}
+void RefreshRateOverlay::primeCache() {
+ auto allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
+ if (allRefreshRates.size() == 1) {
+ auto fps = allRefreshRates.begin()->second.fps;
+ half4 color = {LOW_FPS_COLOR, ALPHA};
+ mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
+ return;
+ }
+
+ std::vector<uint32_t> supportedFps;
+ supportedFps.reserve(allRefreshRates.size());
+ for (auto [ignored, refreshRate] : allRefreshRates) {
+ supportedFps.push_back(refreshRate.fps);
+ }
+
+ std::sort(supportedFps.begin(), supportedFps.end());
+ const auto mLowFps = supportedFps[0];
+ const auto mHighFps = supportedFps[supportedFps.size() - 1];
+ for (auto fps : supportedFps) {
+ const auto fpsScale = float(fps - mLowFps) / (mHighFps - mLowFps);
+ half4 color;
+ color.r = HIGH_FPS_COLOR.r * fpsScale + LOW_FPS_COLOR.r * (1 - fpsScale);
+ color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale);
+ color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale);
+ color.a = ALPHA;
+ mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
+ }
+}
+
void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
- const half3& color = (refreshRate.fps > 65.0f) ? GREEN : RED;
- mLayer->setColor(color);
+ auto buffer = mBufferCache[refreshRate.fps];
+ mLayer->setBuffer(buffer, 0, 0, {});
+ mLayer->setFrame(Rect(20, 120, 20 + SevenSegmentDrawer::getWidth(),
+ 120 + SevenSegmentDrawer::getHeight()));
+
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
index 414bc47..6d34df2 100644
--- a/services/surfaceflinger/RefreshRateOverlay.h
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -28,7 +28,32 @@
void changeRefreshRate(const RefreshRate& refreshRate);
private:
+ class SevenSegmentDrawer {
+ public:
+ static sp<GraphicBuffer> drawNumber(int number, const half4& color);
+ static uint32_t getHeight() { return BUFFER_HEIGHT; }
+ static uint32_t getWidth() { return BUFFER_WIDTH; }
+
+ private:
+ enum class Segment { Upper, UpperLeft, UpperRight, Middle, LowerLeft, LowerRight, Buttom };
+
+ static void drawRect(const Rect& r, const half4& color, const sp<GraphicBuffer>& buffer,
+ uint8_t* pixels);
+ static void drawSegment(Segment segment, int left, const half4& color,
+ const sp<GraphicBuffer>& buffer, uint8_t* pixels);
+ static void drawDigit(int digit, int left, const half4& color,
+ const sp<GraphicBuffer>& buffer, uint8_t* pixels);
+
+ static constexpr uint32_t DIGIT_HEIGHT = 100;
+ static constexpr uint32_t DIGIT_WIDTH = 64;
+ static constexpr uint32_t DIGIT_SPACE = 16;
+ static constexpr uint32_t BUFFER_HEIGHT = DIGIT_HEIGHT;
+ static constexpr uint32_t BUFFER_WIDTH =
+ 3 * DIGIT_WIDTH + 2 * DIGIT_SPACE; // Digit|Space|Digit|Space|Digit
+ };
+
bool createLayer();
+ void primeCache();
SurfaceFlinger& mFlinger;
sp<Client> mClient;
@@ -36,8 +61,11 @@
sp<IBinder> mIBinder;
sp<IGraphicBufferProducer> mGbp;
- const half3 RED = half3(1.0f, 0.0f, 0.0f);
- const half3 GREEN = half3(0.0f, 1.0f, 0.0f);
+ std::unordered_map<int, sp<GraphicBuffer>> mBufferCache;
+
+ static constexpr float ALPHA = 0.8f;
+ const half3 LOW_FPS_COLOR = half3(1.0f, 0.0f, 0.0f);
+ const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f);
};
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9d5081c..537489f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4844,15 +4844,15 @@
return NO_ERROR;
}
case 1034: {
- // TODO(b/129297325): expose this via developer menu option
n = data.readInt32();
- if (n && !mRefreshRateOverlay &&
- mRefreshRateConfigs->refreshRateSwitchingSupported()) {
+ if (n == 1 && !mRefreshRateOverlay) {
mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
auto current = mRefreshRateConfigs->getCurrentRefreshRate();
mRefreshRateOverlay->changeRefreshRate(current);
- } else if (!n) {
+ } else if (n == 0) {
mRefreshRateOverlay.reset();
+ } else {
+ reply->writeBool(mRefreshRateOverlay != nullptr);
}
return NO_ERROR;
}
diff --git a/services/surfaceflinger/tests/CommonTypes_test.cpp b/services/surfaceflinger/tests/CommonTypes_test.cpp
index a3e16f9..ab4af09 100644
--- a/services/surfaceflinger/tests/CommonTypes_test.cpp
+++ b/services/surfaceflinger/tests/CommonTypes_test.cpp
@@ -100,21 +100,21 @@
static_cast<uint32_t>(HidlDataspace::RANGE_LIMITED));
static_assert(static_cast<uint32_t>(AidlDataspace::RANGE_EXTENDED) ==
static_cast<uint32_t>(HidlDataspace::RANGE_EXTENDED));
-static_assert(static_cast<uint32_t>(AidlDataspace::V0_SRGB_LINEAR) ==
+static_assert(static_cast<uint32_t>(AidlDataspace::SRGB_LINEAR) ==
static_cast<uint32_t>(HidlDataspace::V0_SRGB_LINEAR));
-static_assert(static_cast<uint32_t>(AidlDataspace::V0_SCRGB_LINEAR) ==
+static_assert(static_cast<uint32_t>(AidlDataspace::SCRGB_LINEAR) ==
static_cast<uint32_t>(HidlDataspace::V0_SCRGB_LINEAR));
-static_assert(static_cast<uint32_t>(AidlDataspace::V0_SRGB) ==
+static_assert(static_cast<uint32_t>(AidlDataspace::SRGB) ==
static_cast<uint32_t>(HidlDataspace::V0_SRGB));
-static_assert(static_cast<uint32_t>(AidlDataspace::V0_SCRGB) ==
+static_assert(static_cast<uint32_t>(AidlDataspace::SCRGB) ==
static_cast<uint32_t>(HidlDataspace::V0_SCRGB));
-static_assert(static_cast<uint32_t>(AidlDataspace::V0_JFIF) ==
+static_assert(static_cast<uint32_t>(AidlDataspace::JFIF) ==
static_cast<uint32_t>(HidlDataspace::V0_JFIF));
-static_assert(static_cast<uint32_t>(AidlDataspace::V0_BT601_625) ==
+static_assert(static_cast<uint32_t>(AidlDataspace::BT601_625) ==
static_cast<uint32_t>(HidlDataspace::V0_BT601_625));
-static_assert(static_cast<uint32_t>(AidlDataspace::V0_BT601_525) ==
+static_assert(static_cast<uint32_t>(AidlDataspace::BT601_525) ==
static_cast<uint32_t>(HidlDataspace::V0_BT601_525));
-static_assert(static_cast<uint32_t>(AidlDataspace::V0_BT709) ==
+static_assert(static_cast<uint32_t>(AidlDataspace::BT709) ==
static_cast<uint32_t>(HidlDataspace::V0_BT709));
static_assert(static_cast<uint32_t>(AidlDataspace::DCI_P3_LINEAR) ==
static_cast<uint32_t>(HidlDataspace::DCI_P3_LINEAR));
@@ -152,19 +152,3 @@
static_cast<uint32_t>(HidlDataspace::JPEG_APP_SEGMENTS));
static_assert(static_cast<uint32_t>(AidlDataspace::HEIF) ==
static_cast<uint32_t>(HidlDataspace::HEIF));
-
-// Below are the dataspaces that have been deprecated for sometime. They are required to behave
-// the same as their V0_* counterparts. We redefined them in AIDL to be the same as the
-// their V0_* counterparts.
-static_assert(static_cast<uint32_t>(AidlDataspace::SRGB_LINEAR) ==
- static_cast<uint32_t>(AidlDataspace::V0_SRGB_LINEAR));
-static_assert(static_cast<uint32_t>(AidlDataspace::SRGB) ==
- static_cast<uint32_t>(AidlDataspace::V0_SRGB));
-static_assert(static_cast<uint32_t>(AidlDataspace::JFIF) ==
- static_cast<uint32_t>(AidlDataspace::V0_JFIF));
-static_assert(static_cast<uint32_t>(AidlDataspace::BT601_625) ==
- static_cast<uint32_t>(AidlDataspace::V0_BT601_625));
-static_assert(static_cast<uint32_t>(AidlDataspace::BT601_525) ==
- static_cast<uint32_t>(AidlDataspace::V0_BT601_525));
-static_assert(static_cast<uint32_t>(AidlDataspace::BT709) ==
- static_cast<uint32_t>(AidlDataspace::V0_BT709));
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index a020e74..aa7c19a 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -694,20 +694,6 @@
const InstanceData& instance_data = GetData(pdev);
- // TODO(b/143296550): Fill out the set of supported formats. Longer term,
- // add a new gralloc method to query whether a (format, usage) pair is
- // supported, and check that for each gralloc format that corresponds to a
- // Vulkan format. Shorter term, just add a few more formats to the ones
- // hardcoded below.
-
- const VkSurfaceFormatKHR kFormats[] = {
- {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
- {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
- {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
- };
- const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
- uint32_t total_num_formats = kNumFormats;
-
bool wide_color_support = false;
Surface& surface = *SurfaceFromHandle(surface_handle);
int err = native_window_get_wide_color_support(surface.window.get(),
@@ -720,43 +706,72 @@
wide_color_support &&
instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
- const VkSurfaceFormatKHR kWideColorFormats[] = {
- {VK_FORMAT_R8G8B8A8_UNORM,
- VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
- {VK_FORMAT_R8G8B8A8_SRGB,
- VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
- {VK_FORMAT_R16G16B16A16_SFLOAT,
- VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT},
- {VK_FORMAT_R16G16B16A16_SFLOAT,
- VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT},
- {VK_FORMAT_A2B10G10R10_UNORM_PACK32,
- VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
- };
- const uint32_t kNumWideColorFormats =
- sizeof(kWideColorFormats) / sizeof(kWideColorFormats[0]);
+ AHardwareBuffer_Desc desc = {};
+ desc.width = 1;
+ desc.height = 1;
+ desc.layers = 1;
+ desc.usage = surface.consumer_usage |
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
+ AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
+
+ // We must support R8G8B8A8
+ std::vector<VkSurfaceFormatKHR> all_formats = {
+ {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+ {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
+
if (wide_color_support) {
- total_num_formats += kNumWideColorFormats;
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
+ }
+
+ desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
+ if (AHardwareBuffer_isSupported(&desc)) {
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
+ }
+
+ desc.format = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
+ if (AHardwareBuffer_isSupported(&desc)) {
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
+ if (wide_color_support) {
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
+ VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT});
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
+ VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT});
+ }
+ }
+
+ desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
+ if (AHardwareBuffer_isSupported(&desc)) {
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+ VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
+ if (wide_color_support) {
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+ VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
+ }
}
VkResult result = VK_SUCCESS;
if (formats) {
- uint32_t out_count = 0;
- uint32_t transfer_count = 0;
- if (*count < total_num_formats)
+ uint32_t transfer_count = all_formats.size();
+ if (transfer_count > *count) {
+ transfer_count = *count;
result = VK_INCOMPLETE;
- transfer_count = std::min(*count, kNumFormats);
- std::copy(kFormats, kFormats + transfer_count, formats);
- out_count += transfer_count;
- if (wide_color_support) {
- transfer_count = std::min(*count - out_count, kNumWideColorFormats);
- std::copy(kWideColorFormats, kWideColorFormats + transfer_count,
- formats + out_count);
- out_count += transfer_count;
}
- *count = out_count;
+ std::copy(all_formats.begin(), all_formats.begin() + transfer_count,
+ formats);
+ *count = transfer_count;
} else {
- *count = total_num_formats;
+ *count = all_formats.size();
}
+
return result;
}