Notify listeners about active picture profiles
Bug: 337330263
Test: atest ActivePictureUpdaterTest
Test: atest SurfaceControlPictureProfileTest
Flag: com.android.graphics.libgui.flags.apply_picture_profiles
Change-Id: If08b79faf3d3c4c07248ecd7385a75cfe5357726
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1f35173..dfaf8b6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -126,6 +126,7 @@
#include <gui/SchedulingPolicy.h>
#include <gui/SyncScreenCaptureListener.h>
#include <ui/DisplayIdentification.h>
+#include "ActivePictureUpdater.h"
#include "BackgroundExecutor.h"
#include "Client.h"
#include "ClientCache.h"
@@ -372,6 +373,7 @@
const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER");
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
const String16 sControlDisplayBrightness("android.permission.CONTROL_DISPLAY_BRIGHTNESS");
+const String16 sObservePictureProfiles("android.permission.OBSERVE_PICTURE_PROFILES");
const String16 sDump("android.permission.DUMP");
const String16 sCaptureBlackoutContent("android.permission.CAPTURE_BLACKOUT_CONTENT");
const String16 sInternalSystemWindow("android.permission.INTERNAL_SYSTEM_WINDOW");
@@ -2851,6 +2853,9 @@
if (compositionResult.lastClientCompositionFence) {
layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
}
+ if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ mActivePictureUpdater.onLayerComposed(*layer, *layerFE, compositionResult);
+ }
}
SFTRACE_NAME("postComposition");
@@ -3146,30 +3151,6 @@
layer->releasePendingBuffer(presentTime.ns());
}
- std::vector<std::pair<std::shared_ptr<compositionengine::Display>, sp<HdrLayerInfoReporter>>>
- hdrInfoListeners;
- bool haveNewListeners = false;
- {
- Mutex::Autolock lock(mStateLock);
- if (mFpsReporter) {
- mFpsReporter->dispatchLayerFps(mLayerHierarchyBuilder.getHierarchy());
- }
-
- if (mTunnelModeEnabledReporter) {
- mTunnelModeEnabledReporter->updateTunnelModeStatus();
- }
- hdrInfoListeners.reserve(mHdrLayerInfoListeners.size());
- for (const auto& [displayId, reporter] : mHdrLayerInfoListeners) {
- if (reporter && reporter->hasListeners()) {
- if (const auto display = getDisplayDeviceLocked(displayId)) {
- hdrInfoListeners.emplace_back(display->getCompositionDisplay(), reporter);
- }
- }
- }
- haveNewListeners = mAddingHDRLayerInfoListener; // grab this with state lock
- mAddingHDRLayerInfoListener = false;
- }
-
for (const auto& layerEvent : mLayerEvents) {
auto result =
stats::stats_write(stats::SURFACE_CONTROL_EVENT,
@@ -3180,10 +3161,40 @@
ALOGW("Failed to report layer event with error: %d", result);
}
}
-
mLayerEvents.clear();
- if (haveNewListeners || mHdrLayerInfoChanged) {
+ std::vector<std::pair<std::shared_ptr<compositionengine::Display>, sp<HdrLayerInfoReporter>>>
+ hdrInfoListeners;
+ bool haveNewHdrInfoListeners = false;
+ sp<gui::IActivePictureListener> activePictureListener;
+ bool haveNewActivePictureListener = false;
+ {
+ Mutex::Autolock lock(mStateLock);
+ if (mFpsReporter) {
+ mFpsReporter->dispatchLayerFps(mLayerHierarchyBuilder.getHierarchy());
+ }
+
+ if (mTunnelModeEnabledReporter) {
+ mTunnelModeEnabledReporter->updateTunnelModeStatus();
+ }
+
+ hdrInfoListeners.reserve(mHdrLayerInfoListeners.size());
+ for (const auto& [displayId, reporter] : mHdrLayerInfoListeners) {
+ if (reporter && reporter->hasListeners()) {
+ if (const auto display = getDisplayDeviceLocked(displayId)) {
+ hdrInfoListeners.emplace_back(display->getCompositionDisplay(), reporter);
+ }
+ }
+ }
+ haveNewHdrInfoListeners = mAddingHDRLayerInfoListener; // grab this with state lock
+ mAddingHDRLayerInfoListener = false;
+
+ activePictureListener = mActivePictureListener;
+ haveNewActivePictureListener = mHaveNewActivePictureListener;
+ mHaveNewActivePictureListener = false;
+ }
+
+ if (haveNewHdrInfoListeners || mHdrLayerInfoChanged) {
for (auto& [compositionDisplay, listener] : hdrInfoListeners) {
HdrLayerInfoReporter::HdrLayerInfo info;
int32_t maxArea = 0;
@@ -3233,9 +3244,19 @@
listener->dispatchHdrLayerInfo(info);
}
}
-
mHdrLayerInfoChanged = false;
+ if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ // Track, update and notify changes to active pictures - layers that are undergoing picture
+ // processing
+ if (mActivePictureUpdater.updateAndHasChanged() || haveNewActivePictureListener) {
+ if (activePictureListener) {
+ activePictureListener->onActivePicturesChanged(
+ mActivePictureUpdater.getActivePictures());
+ }
+ }
+ }
+
mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */);
mTransactionCallbackInvoker.clearCompletedTransactions();
@@ -8073,6 +8094,14 @@
}));
}
+void SurfaceFlinger::setActivePictureListener(const sp<gui::IActivePictureListener>& listener) {
+ if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ Mutex::Autolock lock(mStateLock);
+ mActivePictureListener = listener;
+ mHaveNewActivePictureListener = listener != nullptr;
+ }
+}
+
std::shared_ptr<renderengine::ExternalTexture> SurfaceFlinger::getExternalTextureFromBufferData(
BufferData& bufferData, const char* layerName, uint64_t transactionId) {
if (bufferData.buffer &&
@@ -9008,6 +9037,15 @@
return binderStatusFromStatusT(status);
}
+binder::Status SurfaceComposerAIDL::setActivePictureListener(
+ const sp<gui::IActivePictureListener>& listener) {
+ status_t status = checkObservePictureProfilesPermission();
+ if (status == OK) {
+ mFlinger->setActivePictureListener(listener);
+ }
+ return binderStatusFromStatusT(status);
+}
+
binder::Status SurfaceComposerAIDL::notifyPowerBoost(int boostId) {
status_t status = checkAccessPermission();
if (status == OK) {
@@ -9263,6 +9301,17 @@
return OK;
}
+status_t SurfaceComposerAIDL::checkObservePictureProfilesPermission() {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if (!PermissionCache::checkPermission(sObservePictureProfiles, pid, uid)) {
+ ALOGE("Permission Denial: can't manage picture profiles pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ return OK;
+}
+
void SurfaceFlinger::forceFutureUpdate(int delayInMs) {
static_cast<void>(mScheduler->scheduleDelayed([&]() { scheduleRepaint(); }, ms2ns(delayInMs)));
}