Merge "Revert "Revert "Revert "Make libbinder not available to media.sw..."" into rvc-dev
diff --git a/data/etc/android.software.controls.xml b/data/etc/android.software.controls.xml
new file mode 100644
index 0000000..2cba34b
--- /dev/null
+++ b/data/etc/android.software.controls.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard feature indicating device controls support on the device,
+ as specified in the CDD. ONLY devices that meet the CDD's requirements may
+ declare this feature. -->
+<permissions>
+ <feature name="android.software.controls" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 619d017..dc6963f 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -59,6 +59,9 @@
<!-- Feature to specify if the device support managed users. -->
<feature name="android.software.managed_users" notLowRam="true"/>
+ <!-- Feature to specify if the device supports controls. -->
+ <feature name="android.software.controls" />
+
<!-- Devices with all optimizations required to support VR Mode and
pass all CDD requirements for this feature may include
android.hardware.vr.high_performance -->
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 52524ca..e878f86 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -59,6 +59,9 @@
<!-- Feature to specify if the device support managed users. -->
<feature name="android.software.managed_users" />
+ <!-- Feature to specify if the device supports controls. -->
+ <feature name="android.software.controls" />
+
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with a rear-facing camera must include one of these as appropriate:
android.hardware.camera.xml or
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 3997134..e8d3684 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -100,6 +100,7 @@
"libgraphicsenv",
"libnativewindow",
"libbacktrace",
+ "libbase",
],
target: {
vendor: {
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 74c4d7d..74fb019 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -21,7 +21,7 @@
#include <errno.h>
#include <inttypes.h>
-#include <cutils/properties.h>
+#include <android-base/properties.h>
#include <log/log.h>
#include <chrono>
@@ -165,7 +165,8 @@
}
size_t BlobCache::getFlattenedSize() const {
- size_t size = align4(sizeof(Header) + PROPERTY_VALUE_MAX);
+ auto buildId = base::GetProperty("ro.build.id", "");
+ size_t size = align4(sizeof(Header) + buildId.size());
for (const CacheEntry& e : mCacheEntries) {
std::shared_ptr<Blob> const& keyBlob = e.getKey();
std::shared_ptr<Blob> const& valueBlob = e.getValue();
@@ -185,9 +186,9 @@
header->mBlobCacheVersion = blobCacheVersion;
header->mDeviceVersion = blobCacheDeviceVersion;
header->mNumEntries = mCacheEntries.size();
- char buildId[PROPERTY_VALUE_MAX];
- header->mBuildIdLength = property_get("ro.build.id", buildId, "");
- memcpy(header->mBuildId, buildId, header->mBuildIdLength);
+ auto buildId = base::GetProperty("ro.build.id", "");
+ header->mBuildIdLength = buildId.size();
+ memcpy(header->mBuildId, buildId.c_str(), header->mBuildIdLength);
// Write cache entries
uint8_t* byteBuffer = reinterpret_cast<uint8_t*>(buffer);
@@ -238,12 +239,11 @@
ALOGE("unflatten: bad magic number: %" PRIu32, header->mMagicNumber);
return -EINVAL;
}
- char buildId[PROPERTY_VALUE_MAX];
- int len = property_get("ro.build.id", buildId, "");
+ auto buildId = base::GetProperty("ro.build.id", "");
if (header->mBlobCacheVersion != blobCacheVersion ||
- header->mDeviceVersion != blobCacheDeviceVersion ||
- len != header->mBuildIdLength ||
- strncmp(buildId, header->mBuildId, len)) {
+ header->mDeviceVersion != blobCacheDeviceVersion ||
+ buildId.size() != header->mBuildIdLength ||
+ strncmp(buildId.c_str(), header->mBuildId, buildId.size())) {
// We treat version mismatches as an empty cache.
return 0;
}
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index d664e4d..d66ef2b 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -24,8 +24,8 @@
#include <dirent.h>
#include <dlfcn.h>
+#include <android-base/properties.h>
#include <android/dlext.h>
-#include <cutils/properties.h>
#include <log/log.h>
#include <utils/Timers.h>
@@ -241,12 +241,12 @@
// i.e.:
// libGLES_${prop}.so, or:
// libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
- char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) <= 0) {
+ auto prop = base::GetProperty(key, "");
+ if (prop.empty()) {
continue;
}
- hnd = attempt_to_load_system_driver(cnx, prop, true);
+ hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
if (hnd) {
break;
} else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
@@ -510,9 +510,9 @@
.library_namespace = ns,
};
void* so = nullptr;
- char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) <= 0) {
+ auto prop = base::GetProperty(key, "");
+ if (prop.empty()) {
continue;
}
std::string name = std::string("lib") + kind + "_" + prop + ".so";
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index d5d57d7..43f7a07 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -18,7 +18,7 @@
#include <EGL/egl.h>
-#include <cutils/properties.h>
+#include <android-base/properties.h>
#include <log/log.h>
@@ -58,9 +58,7 @@
} else {
LOG_ALWAYS_FATAL(error);
}
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.callstack", value, "0");
- if (atoi(value)) {
+ if (base::GetBoolProperty("debug.egl.callstack", false)) {
CallStack::log(LOG_TAG);
}
}
@@ -224,9 +222,7 @@
pthread_mutex_unlock(&sLogPrintMutex);
if (printLog) {
ALOGE("called unimplemented OpenGL ES API");
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.callstack", value, "0");
- if (atoi(value)) {
+ if (base::GetBoolProperty("debug.egl.callstack", false)) {
CallStack::log(LOG_TAG);
}
}
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index 00caff2..97dc0f1 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -16,7 +16,6 @@
#if defined(__ANDROID__)
-#include <cutils/properties.h>
#include "Loader.h"
#include "egl_angle_platform.h"
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 6af7cd2..3b1cf71 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -24,7 +24,6 @@
#include <EGL/eglext_angle.h>
#include <private/EGL/display.h>
-#include <cutils/properties.h>
#include "Loader.h"
#include "egl_angle_platform.h"
#include "egl_cache.h"
@@ -32,6 +31,7 @@
#include "egl_tls.h"
#include <SurfaceFlingerProperties.h>
+#include <android-base/properties.h>
#include <android/dlext.h>
#include <dlfcn.h>
#include <graphicsenv/GraphicsEnv.h>
@@ -73,7 +73,7 @@
}
bool needsAndroidPEglMitigation() {
- static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1);
+ static const int32_t vndk_version = base::GetIntProperty("ro.vndk.version", -1);
return vndk_version <= 28;
}
@@ -151,10 +151,8 @@
attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
- char prop[PROPERTY_VALUE_MAX];
- property_get("debug.angle.validation", prop, "0");
attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
- attrs.push_back(atoi(prop));
+ attrs.push_back(base::GetBoolProperty("debug.angle.validation", false));
attrs.push_back(EGL_NONE);
@@ -372,16 +370,8 @@
egl_cache_t::get()->initialize(this);
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.finish", value, "0");
- if (atoi(value)) {
- finishOnSwap = true;
- }
-
- property_get("debug.egl.traceGpuCompletion", value, "0");
- if (atoi(value)) {
- traceGpuCompletion = true;
- }
+ finishOnSwap = base::GetBoolProperty("debug.egl.finish", false);
+ traceGpuCompletion = base::GetBoolProperty("debug.egl.traceGpuCompletion", false);
// TODO: If device doesn't provide 1.4 or 1.5 then we'll be
// changing the behavior from the past where we always advertise
diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp
index 44a1c0b..ea86c9a 100644
--- a/opengl/libs/EGL/egl_layers.cpp
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -18,9 +18,9 @@
#include <EGL/egl.h>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android/dlext.h>
-#include <cutils/properties.h>
#include <dlfcn.h>
#include <graphicsenv/GraphicsEnv.h>
#include <log/log.h>
@@ -157,9 +157,7 @@
if (debug_layers.empty()) {
// Only check system properties if Java settings are empty
- char prop[PROPERTY_VALUE_MAX];
- property_get("debug.gles.layers", prop, "");
- debug_layers = prop;
+ debug_layers = base::GetProperty("debug.gles.layers", "");
}
return debug_layers;
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index c976c60..99283be 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -27,13 +27,13 @@
#include <EGL/eglext.h>
#include <EGL/eglext_angle.h>
-#include <android/hardware_buffer.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
+#include <android/hardware_buffer.h>
#include <graphicsenv/GraphicsEnv.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <cutils/compiler.h>
-#include <cutils/properties.h>
#include <log/log.h>
#include <condition_variable>
@@ -381,10 +381,7 @@
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso) {
if (attrib_list) {
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.force_msaa", value, "false");
-
- if (!strcmp(value, "true")) {
+ if (base::GetBoolProperty("debug.egl.force_msaa", false)) {
size_t attribCount = 0;
EGLint attrib = attrib_list[0];
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index aaecb62..8d118e0 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -18,7 +18,7 @@
#include <stdlib.h>
-#include <cutils/properties.h>
+#include <android-base/properties.h>
#include <log/log.h>
#include "CallStack.h"
#include "egl_platform_entries.h"
@@ -96,9 +96,7 @@
if (!quiet) {
ALOGE("%s:%d error %x (%s)",
caller, line, error, egl_strerror(error));
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.callstack", value, "0");
- if (atoi(value)) {
+ if (base::GetBoolProperty("debug.egl.callstack", false)) {
CallStack::log(LOG_TAG);
}
}
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index 49630ad..a1eb007 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -37,6 +37,8 @@
return "MOVE";
case AMOTION_EVENT_ACTION_UP:
return "UP";
+ case AMOTION_EVENT_ACTION_CANCEL:
+ return "CANCEL";
case AMOTION_EVENT_ACTION_POINTER_DOWN:
return "POINTER_DOWN";
case AMOTION_EVENT_ACTION_POINTER_UP:
@@ -57,6 +59,7 @@
}
return StringPrintf("%" PRId32, action);
}
+
VerifiedKeyEvent verifiedKeyEventFromKeyEntry(const KeyEntry& entry) {
return {{VerifiedInputEvent::Type::KEY, entry.deviceId, entry.eventTime, entry.source,
entry.displayId},
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 1dbcf98..a239723 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1152,14 +1152,16 @@
}
setInjectionResult(entry, injectionResult);
+ if (injectionResult == INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
+ ALOGW("Permission denied, dropping the motion (isPointer=%s)", toString(isPointerEvent));
+ return true;
+ }
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
- if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
- CancelationOptions::Mode mode(isPointerEvent
- ? CancelationOptions::CANCEL_POINTER_EVENTS
- : CancelationOptions::CANCEL_NON_POINTER_EVENTS);
- CancelationOptions options(mode, "input event injection failed");
- synthesizeCancelationEventsForMonitorsLocked(options);
- }
+ CancelationOptions::Mode mode(isPointerEvent
+ ? CancelationOptions::CANCEL_POINTER_EVENTS
+ : CancelationOptions::CANCEL_NON_POINTER_EVENTS);
+ CancelationOptions options(mode, "input event injection failed");
+ synthesizeCancelationEventsForMonitorsLocked(options);
return true;
}
@@ -1345,13 +1347,6 @@
}
}
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) {
- if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
- return currentTime - mInputTargetWaitStartTime;
- }
- return 0;
-}
-
void InputDispatcher::resetAnrTimeoutsLocked() {
if (DEBUG_FOCUS) {
ALOGD("Resetting ANR timeouts.");
@@ -1394,7 +1389,6 @@
const EventEntry& entry,
std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime) {
- int32_t injectionResult;
std::string reason;
int32_t displayId = getTargetDisplayId(entry);
@@ -1407,54 +1401,38 @@
// then drop the event.
if (focusedWindowHandle == nullptr) {
if (focusedApplicationHandle != nullptr) {
- injectionResult =
- handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
- nullptr, nextWakeupTime,
- "Waiting because no window has focus but there is "
- "a focused application that may eventually add a "
- "window when it finishes starting up.");
- goto Unresponsive;
+ return handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
+ nullptr, nextWakeupTime,
+ "Waiting because no window has focus but there is "
+ "a focused application that may eventually add a "
+ "window when it finishes starting up.");
}
ALOGI("Dropping event because there is no focused window or focused application in display "
"%" PRId32 ".",
displayId);
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
+ return INPUT_EVENT_INJECTION_FAILED;
}
// Check permissions.
if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
- injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- goto Failed;
+ return INPUT_EVENT_INJECTION_PERMISSION_DENIED;
}
// Check whether the window is ready for more input.
reason = checkWindowReadyForMoreInputLocked(currentTime, focusedWindowHandle, entry, "focused");
if (!reason.empty()) {
- injectionResult =
- handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
- focusedWindowHandle, nextWakeupTime, reason.c_str());
- goto Unresponsive;
+ return handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
+ focusedWindowHandle, nextWakeupTime, reason.c_str());
}
// Success! Output targets.
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
addWindowTargetLocked(focusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
BitSet32(0), inputTargets);
// Done.
-Failed:
-Unresponsive:
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
- if (DEBUG_FOCUS) {
- ALOGD("findFocusedWindow finished: injectionResult=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, timeSpentWaitingForApplication / 1000000.0);
- }
- return injectionResult;
+ return INPUT_EVENT_INJECTION_SUCCEEDED;
}
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
@@ -1751,10 +1729,9 @@
checkWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle,
entry, "touched");
if (!reason.empty()) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry, nullptr,
- touchedWindow.windowHandle,
- nextWakeupTime, reason.c_str());
- goto Unresponsive;
+ return handleTargetsNotReadyLocked(currentTime, entry, nullptr,
+ touchedWindow.windowHandle, nextWakeupTime,
+ reason.c_str());
}
}
}
@@ -1814,98 +1791,85 @@
}
}
+ if (injectionPermission != INJECTION_PERMISSION_GRANTED) {
+ return injectionResult;
+ }
+
// Update final pieces of touch state if the injector had permission.
- if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
- if (!wrongDevice) {
- if (switchedDevice) {
+ if (!wrongDevice) {
+ if (switchedDevice) {
+ if (DEBUG_FOCUS) {
+ ALOGD("Conflicting pointer actions: Switched to a different device.");
+ }
+ *outConflictingPointerActions = true;
+ }
+
+ if (isHoverAction) {
+ // Started hovering, therefore no longer down.
+ if (oldState && oldState->down) {
if (DEBUG_FOCUS) {
- ALOGD("Conflicting pointer actions: Switched to a different device.");
+ ALOGD("Conflicting pointer actions: Hover received while pointer was "
+ "down.");
}
*outConflictingPointerActions = true;
}
+ mTempTouchState.reset();
+ if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
+ maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+ mTempTouchState.deviceId = entry.deviceId;
+ mTempTouchState.source = entry.source;
+ mTempTouchState.displayId = displayId;
+ }
+ } else if (maskedAction == AMOTION_EVENT_ACTION_UP ||
+ maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
+ // All pointers up or canceled.
+ mTempTouchState.reset();
+ } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+ // First pointer went down.
+ if (oldState && oldState->down) {
+ if (DEBUG_FOCUS) {
+ ALOGD("Conflicting pointer actions: Down received while already down.");
+ }
+ *outConflictingPointerActions = true;
+ }
+ } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+ // One pointer went up.
+ if (isSplit) {
+ int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+ uint32_t pointerId = entry.pointerProperties[pointerIndex].id;
- if (isHoverAction) {
- // Started hovering, therefore no longer down.
- if (oldState && oldState->down) {
- if (DEBUG_FOCUS) {
- ALOGD("Conflicting pointer actions: Hover received while pointer was "
- "down.");
- }
- *outConflictingPointerActions = true;
- }
- mTempTouchState.reset();
- if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
- maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- mTempTouchState.deviceId = entry.deviceId;
- mTempTouchState.source = entry.source;
- mTempTouchState.displayId = displayId;
- }
- } else if (maskedAction == AMOTION_EVENT_ACTION_UP ||
- maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
- // All pointers up or canceled.
- mTempTouchState.reset();
- } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- // First pointer went down.
- if (oldState && oldState->down) {
- if (DEBUG_FOCUS) {
- ALOGD("Conflicting pointer actions: Down received while already down.");
- }
- *outConflictingPointerActions = true;
- }
- } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
- // One pointer went up.
- if (isSplit) {
- int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- uint32_t pointerId = entry.pointerProperties[pointerIndex].id;
-
- for (size_t i = 0; i < mTempTouchState.windows.size();) {
- TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
- touchedWindow.pointerIds.clearBit(pointerId);
- if (touchedWindow.pointerIds.isEmpty()) {
- mTempTouchState.windows.erase(mTempTouchState.windows.begin() + i);
- continue;
- }
+ for (size_t i = 0; i < mTempTouchState.windows.size();) {
+ TouchedWindow& touchedWindow = mTempTouchState.windows[i];
+ if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
+ touchedWindow.pointerIds.clearBit(pointerId);
+ if (touchedWindow.pointerIds.isEmpty()) {
+ mTempTouchState.windows.erase(mTempTouchState.windows.begin() + i);
+ continue;
}
- i += 1;
}
+ i += 1;
}
}
+ }
- // Save changes unless the action was scroll in which case the temporary touch
- // state was only valid for this one action.
- if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
- if (mTempTouchState.displayId >= 0) {
- if (oldStateIndex >= 0) {
- mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState);
- } else {
- mTouchStatesByDisplay.add(displayId, mTempTouchState);
- }
- } else if (oldStateIndex >= 0) {
- mTouchStatesByDisplay.removeItemsAt(oldStateIndex);
+ // Save changes unless the action was scroll in which case the temporary touch
+ // state was only valid for this one action.
+ if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
+ if (mTempTouchState.displayId >= 0) {
+ if (oldStateIndex >= 0) {
+ mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState);
+ } else {
+ mTouchStatesByDisplay.add(displayId, mTempTouchState);
}
+ } else if (oldStateIndex >= 0) {
+ mTouchStatesByDisplay.removeItemsAt(oldStateIndex);
}
+ }
- // Update hover state.
- mLastHoverWindowHandle = newHoverWindowHandle;
- }
- } else {
- if (DEBUG_FOCUS) {
- ALOGD("Not updating touch focus because injection was denied.");
- }
+ // Update hover state.
+ mLastHoverWindowHandle = newHoverWindowHandle;
}
-Unresponsive:
- // Reset temporary touch state to ensure we release unnecessary references to input channels.
- mTempTouchState.reset();
-
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
- if (DEBUG_FOCUS) {
- ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
- }
return injectionResult;
}
@@ -4664,6 +4628,7 @@
dispatchEntry->eventEntry->appendDescription(msg);
ALOGI("%s", msg.c_str());
}
+ reportDispatchStatistics(std::chrono::nanoseconds(eventDuration), *connection, handled);
bool restartEvent;
if (dispatchEntry->eventEntry->type == EventEntry::Type::KEY) {
@@ -4898,9 +4863,8 @@
return event;
}
-void InputDispatcher::updateDispatchStatistics(nsecs_t currentTime, const EventEntry& entry,
- int32_t injectionResult,
- nsecs_t timeSpentWaitingForApplication) {
+void InputDispatcher::reportDispatchStatistics(std::chrono::nanoseconds eventDuration,
+ const Connection& connection, bool handled) {
// TODO Write some statistics about how long we spend waiting.
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 670d0e1..d122282 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -497,8 +497,8 @@
LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD};
void reportTouchEventForStatistics(const MotionEntry& entry);
- void updateDispatchStatistics(nsecs_t currentTime, const EventEntry& entry,
- int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
+ void reportDispatchStatistics(std::chrono::nanoseconds eventDuration,
+ const Connection& connection, bool handled);
void traceInboundQueueLengthLocked() REQUIRES(mLock);
void traceOutboundQueueLength(const sp<Connection>& connection);
void traceWaitQueueLength(const sp<Connection>& connection);
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index f8d0150..8317b05 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -22,7 +22,6 @@
#include <input/Input.h>
#include <input/TouchVideoFrame.h>
#include <utils/RefBase.h>
-#include <utils/Vector.h>
namespace android {
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 264d287..a1514af 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -1318,7 +1318,7 @@
// joystick and gamepad buttons which are handled like keyboards for the most part.
bool haveKeyboardKeys =
containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) ||
- containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
+ containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_WHEEL),
sizeof_bit_array(KEY_MAX + 1));
bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
sizeof_bit_array(BTN_MOUSE)) ||
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 7be4a58..e009221 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -233,7 +233,7 @@
}
bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
- return scanCode < BTN_MOUSE || scanCode >= KEY_OK ||
+ return scanCode < BTN_MOUSE || scanCode >= BTN_WHEEL ||
(scanCode >= BTN_MISC && scanCode < BTN_MOUSE) ||
(scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index eeff757..f33cc65 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -83,9 +83,13 @@
args.displayId);
}
- void assertFilterInputEventWasNotCalled() { ASSERT_EQ(nullptr, mFilteredEvent); }
+ void assertFilterInputEventWasNotCalled() {
+ std::scoped_lock lock(mLock);
+ ASSERT_EQ(nullptr, mFilteredEvent);
+ }
void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
+ std::scoped_lock lock(mLock);
ASSERT_TRUE(mConfigurationChangedTime)
<< "Timed out waiting for configuration changed call";
ASSERT_EQ(*mConfigurationChangedTime, when);
@@ -93,6 +97,7 @@
}
void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
+ std::scoped_lock lock(mLock);
ASSERT_TRUE(mLastNotifySwitch);
// We do not check id because it is not exposed to the policy
EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
@@ -103,11 +108,13 @@
}
void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
+ std::scoped_lock lock(mLock);
ASSERT_EQ(touchedToken, mOnPointerDownToken);
mOnPointerDownToken.clear();
}
void assertOnPointerDownWasNotCalled() {
+ std::scoped_lock lock(mLock);
ASSERT_TRUE(mOnPointerDownToken == nullptr)
<< "Expected onPointerDownOutsideFocus to not have been called";
}
@@ -118,12 +125,14 @@
}
private:
- std::unique_ptr<InputEvent> mFilteredEvent;
- std::optional<nsecs_t> mConfigurationChangedTime;
- sp<IBinder> mOnPointerDownToken;
- std::optional<NotifySwitchArgs> mLastNotifySwitch;
+ std::mutex mLock;
+ std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
+ std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
+ sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
+ std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
virtual void notifyConfigurationChanged(nsecs_t when) override {
+ std::scoped_lock lock(mLock);
mConfigurationChangedTime = when;
}
@@ -141,6 +150,7 @@
}
virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
+ std::scoped_lock lock(mLock);
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY: {
const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
@@ -173,6 +183,7 @@
virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
uint32_t policyFlags) override {
+ std::scoped_lock lock(mLock);
/** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
* essentially a passthrough for notifySwitch.
*/
@@ -186,11 +197,13 @@
}
virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
+ std::scoped_lock lock(mLock);
mOnPointerDownToken = newToken;
}
void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
int32_t displayId) {
+ std::scoped_lock lock(mLock);
ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
ASSERT_EQ(mFilteredEvent->getType(), type);
@@ -485,7 +498,7 @@
// --- InputDispatcherTest SetInputWindowTest ---
static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
-static constexpr std::chrono::duration DISPATCHING_TIMEOUT = 5s;
+static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
class FakeApplicationHandle : public InputApplicationHandle {
public:
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 109edfe..c457a15 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1848,6 +1848,28 @@
ASSERT_LE(prevTimestamp, keyArgs.eventTime);
}
+/**
+ * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
+ * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
+ * are passed to the listener.
+ */
+static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
+TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
+ std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+ NotifyKeyArgs keyArgs;
+
+ controller->pressAndReleaseKey(BTN_GEAR_DOWN);
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
+ ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
+
+ controller->pressAndReleaseKey(BTN_GEAR_UP);
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
+ ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
+}
+
// --- TouchProcessTest ---
class TouchIntegrationTest : public InputReaderIntegrationTest {
protected:
diff --git a/services/inputflinger/tests/UinputDevice.cpp b/services/inputflinger/tests/UinputDevice.cpp
index 10e7293..0659511 100644
--- a/services/inputflinger/tests/UinputDevice.cpp
+++ b/services/inputflinger/tests/UinputDevice.cpp
@@ -125,6 +125,9 @@
pressAndReleaseKey(KEY_HOME);
}
+// --- UinputSteamController
+UinputSteamController::UinputSteamController() : UinputKeyboard({BTN_GEAR_DOWN, BTN_GEAR_UP}) {}
+
// --- UinputTouchScreen ---
UinputTouchScreen::UinputTouchScreen(const Rect* size)
: UinputDevice(UinputTouchScreen::DEVICE_NAME), mSize(*size) {}
diff --git a/services/inputflinger/tests/UinputDevice.h b/services/inputflinger/tests/UinputDevice.h
index ec3cd9f..22d1f63 100644
--- a/services/inputflinger/tests/UinputDevice.h
+++ b/services/inputflinger/tests/UinputDevice.h
@@ -108,6 +108,16 @@
UinputHomeKey();
};
+// A joystick device that sends a BTN_GEAR_DOWN / BTN_WHEEL key.
+class UinputSteamController : public UinputKeyboard {
+public:
+ template <class D, class... Ts>
+ friend std::unique_ptr<D> createUinputDevice(Ts... args);
+
+private:
+ UinputSteamController();
+};
+
// --- UinputTouchScreen ---
// A touch screen device with specific size.
class UinputTouchScreen : public UinputDevice {
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 8ecdd95..f0b0200 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -319,7 +319,7 @@
return hasReadyFrame();
}
-bool BufferLayer::onPostComposition(sp<const DisplayDevice> displayDevice,
+bool BufferLayer::onPostComposition(const DisplayDevice* display,
const std::shared_ptr<FenceTime>& glDoneFence,
const std::shared_ptr<FenceTime>& presentFence,
const CompositorTiming& compositorTiming) {
@@ -342,7 +342,7 @@
const int32_t layerId = getSequence();
mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime);
- const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ const auto outputLayer = findOutputLayerForDisplay(display);
if (outputLayer && outputLayer->requiresClientComposition()) {
nsecs_t clientCompositionTimestamp = outputLayer->getState().clientCompositionTimestamp;
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
@@ -359,13 +359,15 @@
mFrameTracker.setFrameReadyTime(desiredPresentTime);
}
- const auto displayId = displayDevice->getId();
if (presentFence->isValid()) {
mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence);
mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
presentFence, FrameTracer::FrameEvent::PRESENT_FENCE);
mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
- } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
+ } else if (!display) {
+ // Do nothing.
+ } else if (const auto displayId = display->getId();
+ displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
@@ -600,14 +602,8 @@
return true;
}
-bool BufferLayer::needsFiltering(const sp<const DisplayDevice>& displayDevice) const {
- // If we are not capturing based on the state of a known display device,
- // just return false.
- if (displayDevice == nullptr) {
- return false;
- }
-
- const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+bool BufferLayer::needsFiltering(const DisplayDevice* display) const {
+ const auto outputLayer = findOutputLayerForDisplay(display);
if (outputLayer == nullptr) {
return false;
}
@@ -621,15 +617,9 @@
sourceCrop.getWidth() != displayFrame.getWidth();
}
-bool BufferLayer::needsFilteringForScreenshots(const sp<const DisplayDevice>& displayDevice,
+bool BufferLayer::needsFilteringForScreenshots(const DisplayDevice* display,
const ui::Transform& inverseParentTransform) const {
- // If we are not capturing based on the state of a known display device,
- // just return false.
- if (displayDevice == nullptr) {
- return false;
- }
-
- const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ const auto outputLayer = findOutputLayerForDisplay(display);
if (outputLayer == nullptr) {
return false;
}
@@ -637,7 +627,7 @@
// We need filtering if the sourceCrop rectangle size does not match the
// viewport rectangle size (not a 1:1 render)
const auto& compositionState = outputLayer->getState();
- const ui::Transform& displayTransform = displayDevice->getTransform();
+ const ui::Transform& displayTransform = display->getTransform();
const ui::Transform inverseTransform = inverseParentTransform * displayTransform.inverse();
// Undo the transformation of the displayFrame so that we're back into
// layer-stack space.
@@ -843,7 +833,7 @@
mDrawingState.inputInfo = tmpInputInfo;
}
-void BufferLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) const {
+void BufferLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) {
mTransformHint = getFixedTransformHint();
if (mTransformHint == ui::Transform::ROT_INVALID) {
mTransformHint = displayTransformHint;
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index cfccc8a..97ffe6f 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -79,10 +79,9 @@
bool isHdrY410() const override;
- bool onPostComposition(sp<const DisplayDevice> displayDevice,
- const std::shared_ptr<FenceTime>& glDoneFence,
+ bool onPostComposition(const DisplayDevice*, const std::shared_ptr<FenceTime>& glDoneFence,
const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) override;
+ const CompositorTiming&) override;
// latchBuffer - called each time the screen is redrawn and returns whether
// the visible regions need to be recomputed (this is a fairly heavy
@@ -119,10 +118,6 @@
ui::Transform::RotationFlags getTransformHint() const override { return mTransformHint; }
- void setTransformHint(ui::Transform::RotationFlags displayTransformHint) const override;
-
- // -----------------------------------------------------------------------
-
// -----------------------------------------------------------------------
// Functions that must be implemented by derived classes
// -----------------------------------------------------------------------
@@ -209,14 +204,16 @@
virtual uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
+ void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
+
// Transform hint provided to the producer. This must be accessed holding
/// the mStateLock.
- mutable ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;
+ ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;
private:
// Returns true if this layer requires filtering
- bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const override;
- bool needsFilteringForScreenshots(const sp<const DisplayDevice>& displayDevice,
+ bool needsFiltering(const DisplayDevice*) const override;
+ bool needsFilteringForScreenshots(const DisplayDevice*,
const ui::Transform& inverseParentTransform) const override;
// BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 5d80768..e5b94e4 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -58,7 +58,7 @@
}
}
-void BufferQueueLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) const {
+void BufferQueueLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) {
BufferLayer::setTransformHint(displayTransformHint);
mConsumer->setTransformHint(mTransformHint);
}
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 9bcb63a..5ebc22d 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -43,8 +43,6 @@
void onLayerDisplayed(const sp<Fence>& releaseFence) override;
- void setTransformHint(ui::Transform::RotationFlags displayTransformHint) const override;
-
std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
// If a buffer was replaced this frame, release the former buffer
@@ -72,6 +70,7 @@
bool getSidebandStreamChanged() const override;
bool latchSidebandStream(bool& recomputeVisibleRegions) override;
+ void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
bool hasFrameUpdate() const override;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 81f2dd1..1faf775 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -149,9 +149,9 @@
// a modification of the axes of rotation. To account for this we
// need to reorient the inverse rotation in terms of the current
// axes of rotation.
- bool is_h_flipped = (invTransform & HAL_TRANSFORM_FLIP_H) != 0;
- bool is_v_flipped = (invTransform & HAL_TRANSFORM_FLIP_V) != 0;
- if (is_h_flipped == is_v_flipped) {
+ bool isHFlipped = (invTransform & HAL_TRANSFORM_FLIP_H) != 0;
+ bool isVFlipped = (invTransform & HAL_TRANSFORM_FLIP_V) != 0;
+ if (isHFlipped == isVFlipped) {
invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
}
std::swap(winWidth, winHeight);
@@ -160,18 +160,18 @@
activeCrop.transform(invTransform, bufferSize.getWidth(), bufferSize.getHeight());
// below, crop is intersected with winCrop expressed in crop's coordinate space
- float xScale = crop.getWidth() / float(winWidth);
- float yScale = crop.getHeight() / float(winHeight);
+ const float xScale = crop.getWidth() / float(winWidth);
+ const float yScale = crop.getHeight() / float(winHeight);
- float insetL = winCrop.left * xScale;
- float insetT = winCrop.top * yScale;
- float insetR = (winWidth - winCrop.right) * xScale;
- float insetB = (winHeight - winCrop.bottom) * yScale;
+ const float insetLeft = winCrop.left * xScale;
+ const float insetTop = winCrop.top * yScale;
+ const float insetRight = (winWidth - winCrop.right) * xScale;
+ const float insetBottom = (winHeight - winCrop.bottom) * yScale;
- crop.left += insetL;
- crop.top += insetT;
- crop.right -= insetR;
- crop.bottom -= insetB;
+ crop.left += insetLeft;
+ crop.top += insetTop;
+ crop.right -= insetRight;
+ crop.bottom -= insetBottom;
return crop;
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 9af9cad..0c8aafc 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -158,19 +158,19 @@
mOrientation = orientation;
const Rect& displayBounds = getCompositionDisplay()->getState().bounds;
- const int w = displayBounds.width();
- const int h = displayBounds.height();
+ const int displayWidth = displayBounds.width();
+ const int displayHeight = displayBounds.height();
- ui::Transform R;
+ ui::Transform rotation;
if (const auto flags = ui::Transform::toRotationFlags(orientation);
flags != ui::Transform::ROT_INVALID) {
- R.set(flags, w, h);
+ rotation.set(flags, displayWidth, displayHeight);
}
if (!frame.isValid()) {
// the destination frame can be invalid if it has never been set,
// in that case we assume the whole display frame.
- frame = Rect(w, h);
+ frame = Rect(displayWidth, displayHeight);
}
if (viewport.isEmpty()) {
@@ -178,45 +178,45 @@
// we assume the whole display size.
// it's also invalid to have an empty viewport, so we handle that
// case in the same way.
- viewport = Rect(w, h);
- if (R.getOrientation() & ui::Transform::ROT_90) {
+ viewport = Rect(displayWidth, displayHeight);
+ if (rotation.getOrientation() & ui::Transform::ROT_90) {
// viewport is always specified in the logical orientation
// of the display (ie: post-rotation).
std::swap(viewport.right, viewport.bottom);
}
}
- ui::Transform TL, TP, S;
- float src_width = viewport.width();
- float src_height = viewport.height();
- float dst_width = frame.width();
- float dst_height = frame.height();
- if (src_width != dst_width || src_height != dst_height) {
- float sx = dst_width / src_width;
- float sy = dst_height / src_height;
- S.set(sx, 0, 0, sy);
+ ui::Transform logicalTranslation, physicalTranslation, scale;
+ const float sourceWidth = viewport.width();
+ const float sourceHeight = viewport.height();
+ const float destWidth = frame.width();
+ const float destHeight = frame.height();
+ if (sourceWidth != destWidth || sourceHeight != destHeight) {
+ const float scaleX = destWidth / sourceWidth;
+ const float scaleY = destHeight / sourceHeight;
+ scale.set(scaleX, 0, 0, scaleY);
}
- float src_x = viewport.left;
- float src_y = viewport.top;
- float dst_x = frame.left;
- float dst_y = frame.top;
- TL.set(-src_x, -src_y);
- TP.set(dst_x, dst_y);
+ const float sourceX = viewport.left;
+ const float sourceY = viewport.top;
+ const float destX = frame.left;
+ const float destY = frame.top;
+ logicalTranslation.set(-sourceX, -sourceY);
+ physicalTranslation.set(destX, destY);
// need to take care of primary display rotation for globalTransform
// for case if the panel is not installed aligned with device orientation
if (isPrimary()) {
if (const auto flags = ui::Transform::toRotationFlags(orientation + mPhysicalOrientation);
flags != ui::Transform::ROT_INVALID) {
- R.set(flags, w, h);
+ rotation.set(flags, displayWidth, displayHeight);
}
}
// The viewport and frame are both in the logical orientation.
// Apply the logical translation, scale to physical size, apply the
// physical translation and finally rotate to the physical orientation.
- ui::Transform globalTransform = R * TP * S * TL;
+ ui::Transform globalTransform = rotation * physicalTranslation * scale * logicalTranslation;
const uint8_t type = globalTransform.getType();
const bool needsFiltering =
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 8c86153..cb467ea 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -93,6 +93,10 @@
static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags();
+ ui::Transform::RotationFlags getTransformHint() const {
+ return static_cast<ui::Transform::RotationFlags>(getTransform().getOrientation());
+ }
+
const ui::Transform& getTransform() const;
const Rect& getViewport() const;
const Rect& getFrame() const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 25929ed1..17458e3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -145,11 +145,10 @@
mFlinger->onLayerDestroyed(this);
}
-LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client> client,
- std::string name, uint32_t w, uint32_t h, uint32_t flags,
- LayerMetadata metadata)
+LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
+ uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata)
: flinger(flinger),
- client(client),
+ client(std::move(client)),
name(std::move(name)),
w(w),
h(h),
@@ -718,9 +717,8 @@
return {*shadowSettings};
}
-Hwc2::IComposerClient::Composition Layer::getCompositionType(
- const sp<const DisplayDevice>& display) const {
- const auto outputLayer = findOutputLayerForDisplay(display);
+Hwc2::IComposerClient::Composition Layer::getCompositionType(const DisplayDevice& display) const {
+ const auto outputLayer = findOutputLayerForDisplay(&display);
if (outputLayer == nullptr) {
return Hwc2::IComposerClient::Composition::INVALID;
}
@@ -731,12 +729,6 @@
}
}
-bool Layer::getClearClientTarget(const sp<const DisplayDevice>& display) const {
- const auto outputLayer = findOutputLayerForDisplay(display);
- LOG_FATAL_IF(!outputLayer);
- return outputLayer->getState().clearClientTarget;
-}
-
bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
if (point->getFrameNumber() <= mCurrentFrameNumber) {
// Don't bother with a SyncPoint, since we've already latched the
@@ -1472,19 +1464,11 @@
return usage;
}
-void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const {
- ui::Transform::RotationFlags transformHint = ui::Transform::ROT_0;
- // Disable setting transform hint if the debug flag is set.
- if (!mFlinger->mDebugDisableTransformHint) {
- // The transform hint is used to improve performance, but we can
- // only have a single transform hint, it cannot
- // apply to all displays.
- const ui::Transform& planeTransform = display->getTransform();
- transformHint = static_cast<ui::Transform::RotationFlags>(planeTransform.getOrientation());
- if (transformHint & ui::Transform::ROT_INVALID) {
- transformHint = ui::Transform::ROT_0;
- }
+void Layer::updateTransformHint(ui::Transform::RotationFlags transformHint) {
+ if (mFlinger->mDebugDisableTransformHint || transformHint & ui::Transform::ROT_INVALID) {
+ transformHint = ui::Transform::ROT_0;
}
+
setTransformHint(transformHint);
}
@@ -1493,7 +1477,7 @@
// ----------------------------------------------------------------------------
// TODO(marissaw): add new layer state info to layer debugging
-LayerDebugInfo Layer::getLayerDebugInfo() const {
+LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const {
using namespace std::string_literals;
LayerDebugInfo info;
@@ -1504,7 +1488,7 @@
info.mType = getType();
info.mTransparentRegion = ds.activeTransparentRegion_legacy;
- info.mVisibleRegion = debugGetVisibleRegionOnDefaultDisplay();
+ info.mVisibleRegion = getVisibleRegion(display);
info.mSurfaceDamageRegion = surfaceDamageRegion;
info.mLayerStack = getLayerStack();
info.mX = ds.active_legacy.transform.tx();
@@ -1574,8 +1558,8 @@
}
}
-void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice) const {
- auto outputLayer = findOutputLayerForDisplay(displayDevice);
+void Layer::miniDump(std::string& result, const DisplayDevice& display) const {
+ const auto outputLayer = findOutputLayerForDisplay(&display);
if (!outputLayer) {
return;
}
@@ -1602,7 +1586,7 @@
StringAppendF(&result, " %10d | ", layerState.z);
}
StringAppendF(&result, " %10d | ", mWindowType);
- StringAppendF(&result, "%10s | ", toString(getCompositionType(displayDevice)).c_str());
+ StringAppendF(&result, "%10s | ", toString(getCompositionType(display)).c_str());
StringAppendF(&result, "%10s | ", toString(outputLayerState.bufferTransform).c_str());
const Rect& frame = outputLayerState.displayFrame;
StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
@@ -2175,27 +2159,28 @@
}
LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags,
- const sp<const DisplayDevice>& device) const {
+ const DisplayDevice* display) const {
LayerProto* layerProto = layersProto.add_layers();
- writeToProtoDrawingState(layerProto, traceFlags);
+ writeToProtoDrawingState(layerProto, traceFlags, display);
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
// Only populate for the primary display.
- if (device) {
- const Hwc2::IComposerClient::Composition compositionType = getCompositionType(device);
+ if (display) {
+ const Hwc2::IComposerClient::Composition compositionType = getCompositionType(*display);
layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
}
}
for (const sp<Layer>& layer : mDrawingChildren) {
- layer->writeToProto(layersProto, traceFlags, device);
+ layer->writeToProto(layersProto, traceFlags, display);
}
return layerProto;
}
-void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) const {
+void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags,
+ const DisplayDevice* display) const {
ui::Transform transform = getTransform();
if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
@@ -2229,7 +2214,7 @@
[&]() { return layerInfo->mutable_position(); });
LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
- LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(),
+ LayerProtoHelper::writeToProto(getVisibleRegion(display),
[&]() { return layerInfo->mutable_visible_region(); });
}
LayerProtoHelper::writeToProto(surfaceDamageRegion,
@@ -2428,22 +2413,14 @@
}
compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
- const sp<const DisplayDevice>& display) const {
+ const DisplayDevice* display) const {
+ if (!display) return nullptr;
return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionEngineLayerFE());
}
-Region Layer::debugGetVisibleRegionOnDefaultDisplay() const {
- sp<DisplayDevice> displayDevice = mFlinger->getDefaultDisplayDeviceLocked();
- if (displayDevice == nullptr) {
- return {};
- }
-
- auto outputLayer = findOutputLayerForDisplay(displayDevice);
- if (outputLayer == nullptr) {
- return {};
- }
-
- return outputLayer->getState().visibleRegion;
+Region Layer::getVisibleRegion(const DisplayDevice* display) const {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ return outputLayer ? outputLayer->getState().visibleRegion : Region();
}
void Layer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 224ea19..3fa935f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_LAYER_H
-#define ANDROID_LAYER_H
+#pragma once
#include <compositionengine/LayerFE.h>
#include <gui/BufferQueue.h>
@@ -77,8 +76,8 @@
// ---------------------------------------------------------------------------
struct LayerCreationArgs {
- LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client> client, std::string name,
- uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata);
+ LayerCreationArgs(SurfaceFlinger*, sp<Client>, std::string name, uint32_t w, uint32_t h,
+ uint32_t flags, LayerMetadata);
SurfaceFlinger* flinger;
const sp<Client> client;
@@ -87,9 +86,9 @@
uint32_t h;
uint32_t flags;
LayerMetadata metadata;
+
pid_t callingPid;
uid_t callingUid;
- sp<const DisplayDevice> displayDevice;
uint32_t textureName;
};
@@ -519,15 +518,14 @@
bool isRemovedFromCurrentState() const;
- LayerProto* writeToProto(LayersProto& layersProto,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL,
- const sp<const DisplayDevice>& device = nullptr) const;
+ LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags,
+ const DisplayDevice*) const;
// Write states that are modified by the main thread. This includes drawing
// state as well as buffer data. This should be called in the main or tracing
// thread.
- void writeToProtoDrawingState(LayerProto* layerInfo,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ void writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags,
+ const DisplayDevice*) const;
// Write drawing or current state. If writing current state, the caller should hold the
// external mStateLock. If writing drawing state, this function should be called on the
// main or tracing thread.
@@ -544,7 +542,7 @@
return s.activeTransparentRegion_legacy;
}
virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
- virtual bool needsFiltering(const sp<const DisplayDevice>&) const { return false; }
+ virtual bool needsFiltering(const DisplayDevice*) const { return false; }
// True if this layer requires filtering
// This method is distinct from needsFiltering() in how the filter
// requirement is computed. needsFiltering() compares displayFrame and crop,
@@ -554,8 +552,7 @@
// different.
// If the parent transform needs to be undone when capturing the layer, then
// the inverse parent transform is also required.
- virtual bool needsFilteringForScreenshots(const sp<const DisplayDevice>&,
- const ui::Transform&) const {
+ virtual bool needsFilteringForScreenshots(const DisplayDevice*, const ui::Transform&) const {
return false;
}
@@ -616,21 +613,16 @@
virtual bool isHdrY410() const { return false; }
- Hwc2::IComposerClient::Composition getCompositionType(
- const sp<const DisplayDevice>& display) const;
- bool getClearClientTarget(const sp<const DisplayDevice>& display) const;
-
virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; }
- virtual void setTransformHint(ui::Transform::RotationFlags /*transformHint*/) const {}
/*
* called after composition.
* returns true if the layer latched a new buffer this frame.
*/
- virtual bool onPostComposition(sp<const DisplayDevice> /*displayDevice*/,
+ virtual bool onPostComposition(const DisplayDevice*,
const std::shared_ptr<FenceTime>& /*glDoneFence*/,
const std::shared_ptr<FenceTime>& /*presentFence*/,
- const CompositorTiming& /*compositorTiming*/) {
+ const CompositorTiming&) {
return false;
}
@@ -682,9 +674,10 @@
*/
void addToCurrentState();
- // Updates the transform hint in our SurfaceFlingerConsumer to match
- // the current orientation of the display device.
- void updateTransformHint(const sp<const DisplayDevice>& display) const;
+ /*
+ * Sets display transform hint on BufferLayerConsumer.
+ */
+ void updateTransformHint(ui::Transform::RotationFlags);
/*
* returns the rectangle that crops the content of the layer and scales it
@@ -713,11 +706,10 @@
inline const State& getCurrentState() const { return mCurrentState; }
inline State& getCurrentState() { return mCurrentState; }
- LayerDebugInfo getLayerDebugInfo() const;
+ LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const;
- /* always call base class first */
static void miniDumpHeader(std::string& result);
- void miniDump(std::string& result, const sp<DisplayDevice>& display) const;
+ void miniDump(std::string& result, const DisplayDevice&) const;
void dumpFrameStats(std::string& result) const;
void dumpFrameEvents(std::string& result);
void dumpCallingUidPid(std::string& result) const;
@@ -822,11 +814,6 @@
return parentBounds;
}
- compositionengine::OutputLayer* findOutputLayerForDisplay(
- const sp<const DisplayDevice>& display) const;
-
- Region debugGetVisibleRegionOnDefaultDisplay() const;
-
/**
* Returns the cropped buffer size or the layer crop if the layer has no buffer. Return
* INVALID_RECT if the layer has no buffer and no crop.
@@ -963,7 +950,8 @@
bool hasInput() const;
protected:
- // -----------------------------------------------------------------------
+ compositionengine::OutputLayer* findOutputLayerForDisplay(const DisplayDevice*) const;
+
bool usingRelativeZ(LayerVector::StateSet stateSet) const;
bool mPremultipliedAlpha{true};
@@ -1035,6 +1023,11 @@
const int mWindowType;
private:
+ virtual void setTransformHint(ui::Transform::RotationFlags) {}
+
+ Hwc2::IComposerClient::Composition getCompositionType(const DisplayDevice&) const;
+ Region getVisibleRegion(const DisplayDevice*) const;
+
/**
* Returns an unsorted vector of all layers that are part of this tree.
* That includes the current layer and all its descendants.
@@ -1098,14 +1091,3 @@
};
} // namespace android
-
-#define RETURN_IF_NO_HWC_LAYER(displayDevice, ...) \
- do { \
- if (!hasHwcLayer(displayDevice)) { \
- ALOGE("[%s] %s failed: no HWC layer found for display %s", mName.string(), \
- __FUNCTION__, displayDevice->getDebugName().c_str()); \
- return __VA_ARGS__; \
- } \
- } while (false)
-
-#endif // ANDROID_LAYER_H
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index b067466..e6c5cc9 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -174,8 +174,10 @@
return LayerVoteType::NoVote;
}
}();
- if (layer->isVisible() && (frameRate.rate > 0 || voteType == LayerVoteType::NoVote)) {
- info->setLayerVote(voteType, frameRate.rate);
+
+ if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) {
+ const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote;
+ info->setLayerVote(type, frameRate.rate);
} else {
info->resetLayerVote();
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
index ce57ea8..b7d0bdd 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
@@ -111,35 +111,47 @@
// Calculate the refresh rate by finding the average delta between frames
nsecs_t totalPresentTimeDeltas = 0;
- int numFrames = 0;
+ nsecs_t totalQueueTimeDeltas = 0;
+ auto missingPresentTime = false;
for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
- // If there are no presentation timestamp provided we can't calculate the refresh rate
+ totalQueueTimeDeltas +=
+ std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);
+
if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
+ missingPresentTime = true;
continue;
}
totalPresentTimeDeltas +=
std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
- numFrames++;
}
- if (numFrames == 0) {
+
+ // If there are no presentation timestamps provided we can't calculate the refresh rate
+ if (missingPresentTime && mLastReportedRefreshRate == 0) {
return std::nullopt;
}
- const float averageFrameTime = static_cast<float>(totalPresentTimeDeltas) / numFrames;
+
+ // Calculate the average frame time based on presentation timestamps. If those
+ // doesn't exist, we look at the time the buffer was queued only. We can do that only if
+ // we calculated a refresh rate based on presentation timestamps in the past. The reason
+ // we look at the queue time is to handle cases where hwui attaches presentation timestamps
+ // when implementing render ahead for specific refresh rates. When hwui no longer provides
+ // presentation timestamps we look at the queue time to see if the current refresh rate still
+ // matches the content.
+ const float averageFrameTime =
+ static_cast<float>(missingPresentTime ? totalQueueTimeDeltas : totalPresentTimeDeltas) /
+ (mFrameTimes.size() - 1);
// Now once we calculated the refresh rate we need to make sure that all the frames we captured
// are evenly distributed and we don't calculate the average across some burst of frames.
for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
- const nsecs_t frameTimeDeltas = [&] {
- nsecs_t delta;
- if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
- delta = (it + 1)->queueTime - it->queueTime;
- } else {
- delta = (it + 1)->presetTime - it->presetTime;
- }
+ const auto presentTimeDeltas = [&] {
+ const auto delta = missingPresentTime ? (it + 1)->queueTime - it->queueTime
+ : (it + 1)->presetTime - it->presetTime;
return std::max(delta, mHighRefreshRatePeriod);
}();
- if (std::abs(frameTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
+
+ if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
return std::nullopt;
}
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h
index ad91f18..e36b7f7 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.h
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h
@@ -88,6 +88,7 @@
// buffer as Max as we don't know anything about this layer or Min as this layer is
// posting infrequent updates.
mFrameTimeValidSince = std::chrono::steady_clock::now();
+ mLastReportedRefreshRate = 0.0f;
}
private:
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index d73fd8b..f87c1f8 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -66,15 +66,15 @@
// TODO (140302863) remove this and use the vsync_reactor system.
if (property_get_bool("debug.sf.vsync_reactor", true)) {
// TODO (144707443) tune Predictor tunables.
- static constexpr int default_rate = 60;
- static constexpr auto initial_period =
- std::chrono::duration<nsecs_t, std::ratio<1, default_rate>>(1);
+ static constexpr int defaultRate = 60;
+ static constexpr auto initialPeriod =
+ std::chrono::duration<nsecs_t, std::ratio<1, defaultRate>>(1);
static constexpr size_t vsyncTimestampHistorySize = 20;
static constexpr size_t minimumSamplesForPrediction = 6;
static constexpr uint32_t discardOutlierPercent = 20;
auto tracker = std::make_unique<
scheduler::VSyncPredictor>(std::chrono::duration_cast<std::chrono::nanoseconds>(
- initial_period)
+ initialPeriod)
.count(),
vsyncTimestampHistorySize, minimumSamplesForPrediction,
discardOutlierPercent);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3b66fa9..e65b80a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -125,6 +125,19 @@
#include "android-base/parseint.h"
#include "android-base/stringprintf.h"
+#define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock)
+
+#define ON_MAIN_THREAD(expr) \
+ [&] { \
+ LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \
+ UnnecessaryLock lock(mStateLock); \
+ return (expr); \
+ }()
+
+#undef NO_THREAD_SAFETY_ANALYSIS
+#define NO_THREAD_SAFETY_ANALYSIS \
+ _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"")
+
namespace android {
using namespace std::string_literals;
@@ -173,12 +186,12 @@
#pragma clang diagnostic pop
template <typename Mutex>
-struct ConditionalLockGuard {
- ConditionalLockGuard(Mutex& mutex, bool lock) : mutex(mutex), lock(lock) {
+struct SCOPED_CAPABILITY ConditionalLockGuard {
+ ConditionalLockGuard(Mutex& mutex, bool lock) ACQUIRE(mutex) : mutex(mutex), lock(lock) {
if (lock) mutex.lock();
}
- ~ConditionalLockGuard() {
+ ~ConditionalLockGuard() RELEASE() {
if (lock) mutex.unlock();
}
@@ -188,6 +201,27 @@
using ConditionalLock = ConditionalLockGuard<Mutex>;
+struct SCOPED_CAPABILITY TimedLock {
+ TimedLock(Mutex& mutex, nsecs_t timeout, const char* whence) ACQUIRE(mutex)
+ : mutex(mutex), status(mutex.timedLock(timeout)) {
+ ALOGE_IF(!locked(), "%s timed out locking: %s (%d)", whence, strerror(-status), status);
+ }
+
+ ~TimedLock() RELEASE() {
+ if (locked()) mutex.unlock();
+ }
+
+ bool locked() const { return status == NO_ERROR; }
+
+ Mutex& mutex;
+ const status_t status;
+};
+
+struct SCOPED_CAPABILITY UnnecessaryLock {
+ explicit UnnecessaryLock(Mutex& mutex) ACQUIRE(mutex) {}
+ ~UnnecessaryLock() RELEASE() {}
+};
+
// TODO(b/141333600): Consolidate with HWC2::Display::Config::Builder::getDefaultDensity.
constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
@@ -991,7 +1025,7 @@
}
auto future = schedule([=]() -> status_t {
- const auto display = getDisplayDeviceLocked(displayToken);
+ const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken));
if (!display) {
ALOGE("Attempt to set allowed display configs for invalid display token %p",
displayToken.get());
@@ -1176,7 +1210,7 @@
}
status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) {
- schedule([=] {
+ schedule([=]() MAIN_THREAD {
Vector<ColorMode> modes;
getDisplayColorModes(displayToken, &modes);
bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes);
@@ -1222,7 +1256,7 @@
}
void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) {
- static_cast<void>(schedule([=] {
+ static_cast<void>(schedule([=]() MAIN_THREAD {
if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
getHwComposer().setAutoLowLatencyMode(*displayId, on);
} else {
@@ -1253,7 +1287,7 @@
}
void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) {
- static_cast<void>(schedule([=] {
+ static_cast<void>(schedule([=]() MAIN_THREAD {
if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
const auto type = on ? hal::ContentType::GAME : hal::ContentType::NONE;
getHwComposer().setContentType(*displayId, type);
@@ -1343,7 +1377,7 @@
status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken,
bool enable, uint8_t componentMask,
uint64_t maxFrames) {
- return schedule([=]() -> status_t {
+ return schedule([=]() MAIN_THREAD -> status_t {
if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
return getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable,
componentMask,
@@ -1412,22 +1446,17 @@
return mScheduler->injectVSync(when, calculateExpectedPresentTime(when)) ? NO_ERROR : BAD_VALUE;
}
-status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const
- NO_THREAD_SAFETY_ANALYSIS {
- // Try to acquire a lock for 1s, fail gracefully
- const status_t err = mStateLock.timedLock(s2ns(1));
- const bool locked = (err == NO_ERROR);
- if (!locked) {
- ALOGE("LayerDebugInfo: SurfaceFlinger unresponsive (%s [%d]) - exit", strerror(-err), err);
+status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const {
+ TimedLock lock(mStateLock, s2ns(1), __FUNCTION__);
+ if (!lock.locked()) {
return TIMED_OUT;
}
+ const auto display = getDefaultDisplayDeviceLocked();
outLayers->clear();
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- outLayers->push_back(layer->getLayerDebugInfo());
- });
+ mCurrentState.traverseInZOrder(
+ [&](Layer* layer) { outLayers->push_back(layer->getLayerDebugInfo(display.get())); });
- mStateLock.unlock();
return NO_ERROR;
}
@@ -1484,7 +1513,7 @@
return BAD_VALUE;
}
- return promise::chain(schedule([=] {
+ return promise::chain(schedule([=]() MAIN_THREAD {
if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
return getHwComposer().setDisplayBrightness(*displayId, brightness);
} else {
@@ -1597,7 +1626,7 @@
}
void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
- hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS {
+ hal::Connection connection) {
ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId,
connection == hal::Connection::CONNECTED ? "connected" : "disconnected");
@@ -1650,8 +1679,7 @@
// Enable / Disable HWVsync from the main thread to avoid race conditions with
// display power state.
- static_cast<void>(
- schedule([=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
+ static_cast<void>(schedule([=]() MAIN_THREAD { setPrimaryVsyncEnabledInternal(enabled); }));
}
void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
@@ -1667,7 +1695,6 @@
}
}
-// Note: it is assumed the caller holds |mStateLock| when this is called
void SurfaceFlinger::resetDisplayState() {
mScheduler->disableHardwareVsync(true);
// Clear the drawing state so that the logic inside of
@@ -1760,7 +1787,7 @@
setTransactionFlags(eDisplayTransactionNeeded);
}
-sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS {
+sp<Fence> SurfaceFlinger::previousFrameFence() {
// We are storing the last 2 present fences. If sf's phase offset is to be
// woken up before the actual vsync but targeting the next vsync, we need to check
// fence N-2
@@ -1768,7 +1795,7 @@
: mPreviousPresentFences[1];
}
-bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS {
+bool SurfaceFlinger::previousFramePending(int graceTimeMs) {
ATRACE_CALL();
const sp<Fence>& fence = previousFrameFence();
@@ -1782,7 +1809,7 @@
return status == -ETIME;
}
-nsecs_t SurfaceFlinger::previousFramePresentTime() NO_THREAD_SAFETY_ANALYSIS {
+nsecs_t SurfaceFlinger::previousFramePresentTime() {
const sp<Fence>& fence = previousFrameFence();
if (fence == Fence::NO_FENCE) {
@@ -1800,8 +1827,7 @@
return mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod;
}
-void SurfaceFlinger::onMessageReceived(int32_t what,
- nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS {
+void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) {
ATRACE_CALL();
switch (what) {
case MessageQueue::INVALIDATE: {
@@ -1815,7 +1841,7 @@
}
}
-void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS {
+void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) {
ATRACE_CALL();
const nsecs_t frameStart = systemTime();
@@ -1888,7 +1914,7 @@
// We received the present fence from the HWC, so we assume it successfully updated
// the config, hence we update SF.
mSetActiveConfigPending = false;
- setActiveConfigInternal();
+ ON_MAIN_THREAD(setActiveConfigInternal());
}
if (framePending && mPropagateBackpressure) {
@@ -1907,12 +1933,12 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
// If we're in a user build then don't push any atoms
if (!mIsUserBuild && mMissedFrameJankCount > 0) {
- const auto displayDevice = getDefaultDisplayDeviceLocked();
+ const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
// Only report jank when the display is on, as displays in DOZE
// power mode may operate at a different frame rate than is
// reported in their config, which causes noticeable (but less
// severe) jank.
- if (displayDevice && displayDevice->getPowerMode() == hal::PowerMode::ON) {
+ if (display && display->getPowerMode() == hal::PowerMode::ON) {
const nsecs_t currentTime = systemTime();
const nsecs_t jankDuration = currentTime - mMissedFrameJankStart;
if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) {
@@ -1969,7 +1995,7 @@
mScheduler->chooseRefreshRateForContent();
}
- performSetActiveConfig();
+ ON_MAIN_THREAD(performSetActiveConfig());
updateCursorAsync();
updateInputFlinger();
@@ -2018,8 +2044,9 @@
mRefreshPending = false;
compositionengine::CompositionRefreshArgs refreshArgs;
- refreshArgs.outputs.reserve(mDisplays.size());
- for (const auto& [_, display] : mDisplays) {
+ const auto& displays = ON_MAIN_THREAD(mDisplays);
+ refreshArgs.outputs.reserve(displays.size());
+ for (const auto& [_, display] : displays) {
refreshArgs.outputs.push_back(display->getCompositionDisplay());
}
mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {
@@ -2074,21 +2101,18 @@
const bool prevFrameHadDeviceComposition = mHadDeviceComposition;
- mHadClientComposition =
- std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
- auto& displayDevice = tokenDisplayPair.second;
- return displayDevice->getCompositionDisplay()->getState().usesClientComposition &&
- !displayDevice->getCompositionDisplay()->getState().reusedClientComposition;
- });
- mHadDeviceComposition =
- std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
- auto& displayDevice = tokenDisplayPair.second;
- return displayDevice->getCompositionDisplay()->getState().usesDeviceComposition;
- });
+ mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
+ const auto& state = pair.second->getCompositionDisplay()->getState();
+ return state.usesClientComposition && !state.reusedClientComposition;
+ });
+ mHadDeviceComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
+ const auto& state = pair.second->getCompositionDisplay()->getState();
+ return state.usesDeviceComposition;
+ });
mReusedClientComposition =
- std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
- auto& displayDevice = tokenDisplayPair.second;
- return displayDevice->getCompositionDisplay()->getState().reusedClientComposition;
+ std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
+ const auto& state = pair.second->getCompositionDisplay()->getState();
+ return state.reusedClientComposition;
});
// Only report a strategy change if we move in and out of composition with hw overlays
@@ -2194,14 +2218,14 @@
for (auto& layer : mLayersWithQueuedFrames) {
layer->releasePendingBuffer(dequeueReadyTime);
}
- // |mStateLock| not needed as we are on the main thread
- const auto displayDevice = getDefaultDisplayDeviceLocked();
+
+ const auto* display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()).get();
getBE().mGlCompositionDoneTimeline.updateSignalTimes();
std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
- if (displayDevice && displayDevice->getCompositionDisplay()->getState().usesClientComposition) {
+ if (display && display->getCompositionDisplay()->getState().usesClientComposition) {
glCompositionDoneFenceTime =
- std::make_shared<FenceTime>(displayDevice->getCompositionDisplay()
+ std::make_shared<FenceTime>(display->getCompositionDisplay()
->getRenderSurface()
->getClientTargetAcquireFence());
getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
@@ -2211,9 +2235,8 @@
getBE().mDisplayTimeline.updateSignalTimes();
mPreviousPresentFences[1] = mPreviousPresentFences[0];
- mPreviousPresentFences[0] = displayDevice
- ? getHwComposer().getPresentFence(*displayDevice->getId())
- : Fence::NO_FENCE;
+ mPreviousPresentFences[0] =
+ display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE;
auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]);
getBE().mDisplayTimeline.push(presentFenceTime);
@@ -2232,8 +2255,8 @@
}
mDrawingState.traverse([&](Layer* layer) {
- bool frameLatched = layer->onPostComposition(displayDevice, glCompositionDoneFenceTime,
- presentFenceTime, compositorTiming);
+ const bool frameLatched = layer->onPostComposition(display, glCompositionDoneFenceTime,
+ presentFenceTime, compositorTiming);
if (frameLatched) {
recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false));
}
@@ -2242,14 +2265,15 @@
mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
mTransactionCompletedThread.sendCallbacks();
- if (displayDevice && displayDevice->isPrimary() &&
- displayDevice->getPowerMode() == hal::PowerMode::ON && presentFenceTime->isValid()) {
+ if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON &&
+ presentFenceTime->isValid()) {
mScheduler->addPresentFence(presentFenceTime);
}
+ const bool isDisplayConnected = display && getHwComposer().isConnected(*display->getId());
+
if (!hasSyncFramework) {
- if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) &&
- displayDevice->isPoweredOn()) {
+ if (isDisplayConnected && display->isPoweredOn()) {
mScheduler->enableHardwareVsync();
}
}
@@ -2260,11 +2284,10 @@
if (presentFenceTime->isValid()) {
mAnimFrameTracker.setActualPresentFence(
std::move(presentFenceTime));
- } else if (displayDevice && getHwComposer().isConnected(*displayDevice->getId())) {
+ } else if (isDisplayConnected) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
- const nsecs_t presentTime =
- getHwComposer().getRefreshTimestamp(*displayDevice->getId());
+ const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId());
mAnimFrameTracker.setActualPresentTime(presentTime);
}
mAnimFrameTracker.advanceFrame();
@@ -2285,8 +2308,7 @@
const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle);
mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections);
- if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) &&
- !displayDevice->isPoweredOn()) {
+ if (isDisplayConnected && !display->isPoweredOn()) {
return;
}
@@ -2342,7 +2364,7 @@
}
void SurfaceFlinger::computeLayerBounds() {
- for (const auto& pair : mDisplays) {
+ for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
const auto& displayDevice = pair.second;
const auto display = displayDevice->getCompositionDisplay();
for (const auto& layer : mDrawingState.layersSortedByZ) {
@@ -2357,10 +2379,8 @@
}
}
-void SurfaceFlinger::postFrame()
-{
- // |mStateLock| not needed as we are on the main thread
- const auto display = getDefaultDisplayDeviceLocked();
+void SurfaceFlinger::postFrame() {
+ const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
if (display && getHwComposer().isConnected(*display->getId())) {
uint32_t flipCount = display->getPageFlipCount();
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
@@ -2788,7 +2808,7 @@
sp<const DisplayDevice> hintDisplay;
uint32_t currentlayerStack = 0;
bool first = true;
- mCurrentState.traverse([&](Layer* layer) {
+ mCurrentState.traverse([&](Layer* layer) REQUIRES(mStateLock) {
// NOTE: we rely on the fact that layers are sorted by
// layerStack first (so we don't have to traverse the list
// of displays for every layer).
@@ -2826,7 +2846,7 @@
// could be null if there is no display available at all to get
// the transform hint from.
if (hintDisplay) {
- layer->updateTransformHint(hintDisplay);
+ layer->updateTransformHint(hintDisplay->getTransformHint());
}
first = false;
@@ -2901,10 +2921,9 @@
mPendingInputWindowCommands.clear();
}
-void SurfaceFlinger::updateCursorAsync()
-{
+void SurfaceFlinger::updateCursorAsync() {
compositionengine::CompositionRefreshArgs refreshArgs;
- for (const auto& [_, display] : mDisplays) {
+ for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
if (display->getId()) {
refreshArgs.outputs.push_back(display->getCompositionDisplay());
}
@@ -2914,7 +2933,7 @@
}
void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate,
- Scheduler::ConfigEvent event) NO_THREAD_SAFETY_ANALYSIS {
+ Scheduler::ConfigEvent event) {
// If this is called from the main thread mStateLock must be locked before
// Currently the only way to call this function from the main thread is from
// Sheduler::chooseRefreshRateForContent
@@ -3040,7 +3059,7 @@
}
void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
- for (const auto& [token, displayDevice] : mDisplays) {
+ for (const auto& [token, displayDevice] : ON_MAIN_THREAD(mDisplays)) {
auto display = displayDevice->getCompositionDisplay();
if (display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
display->editState().dirtyRegion.orSelf(dirty);
@@ -3181,7 +3200,7 @@
}
if (const auto display = getDefaultDisplayDeviceLocked()) {
- lbc->updateTransformHint(display);
+ lbc->updateTransformHint(display->getTransformHint());
}
if (outTransformHint) {
*outTransformHint = lbc->getTransformHint();
@@ -4040,7 +4059,6 @@
LayerMetadata metadata, sp<IBinder>* handle,
sp<Layer>* outLayer) {
LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
- args.displayDevice = getDefaultDisplayDevice();
args.textureName = getNewTexture();
sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(args);
*handle = layer->getHandle();
@@ -4137,7 +4155,7 @@
void SurfaceFlinger::initializeDisplays() {
// Async since we may be called from the main thread.
- static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
+ static_cast<void>(schedule([this]() MAIN_THREAD { onInitializeDisplays(); }));
}
void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, hal::Vsync enabled) {
@@ -4228,7 +4246,7 @@
}
void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
- schedule([=]() NO_THREAD_SAFETY_ANALYSIS {
+ schedule([=]() MAIN_THREAD {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
@@ -4241,8 +4259,7 @@
}).wait();
}
-status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args,
- bool asProto) NO_THREAD_SAFETY_ANALYSIS {
+status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {
std::string result;
IPCThreadState* ipc = IPCThreadState::self();
@@ -4254,18 +4271,6 @@
StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n",
pid, uid);
} else {
- // Try to get the main lock, but give up after one second
- // (this would indicate SF is stuck, but we want to be able to
- // print something in dumpsys).
- status_t err = mStateLock.timedLock(s2ns(1));
- bool locked = (err == NO_ERROR);
- if (!locked) {
- StringAppendF(&result,
- "SurfaceFlinger appears to be unresponsive (%s [%d]), dumping anyways "
- "(no locks held)\n",
- strerror(-err), err);
- }
-
static const std::unordered_map<std::string, Dumper> dumpers = {
{"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
{"--dispsync"s,
@@ -4283,18 +4288,23 @@
const auto flag = args.empty() ? ""s : std::string(String8(args[0]));
- const auto it = dumpers.find(flag);
- if (it != dumpers.end()) {
- (it->second)(args, asProto, result);
- } else if (!asProto) {
- dumpAllLocked(args, result);
+ bool dumpLayers = true;
+ {
+ TimedLock lock(mStateLock, s2ns(1), __FUNCTION__);
+ if (!lock.locked()) {
+ StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n",
+ strerror(-lock.status), lock.status);
+ }
+
+ if (const auto it = dumpers.find(flag); it != dumpers.end()) {
+ (it->second)(args, asProto, result);
+ dumpLayers = false;
+ } else if (!asProto) {
+ dumpAllLocked(args, result);
+ }
}
- if (locked) {
- mStateLock.unlock();
- }
-
- if (it == dumpers.end()) {
+ if (dumpLayers) {
const LayersProto layersProto = dumpProtoFromMainThread();
if (asProto) {
result.append(layersProto.SerializeAsString());
@@ -4568,11 +4578,11 @@
LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
// If context is SurfaceTracing thread, mTracingLock blocks display transactions on main thread.
- const auto display = getDefaultDisplayDeviceLocked();
+ const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
LayersProto layersProto;
for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
- layer->writeToProto(layersProto, traceFlags, display);
+ layer->writeToProto(layersProto, traceFlags, display.get());
}
return layersProto;
@@ -4761,9 +4771,9 @@
StringAppendF(&result, "Display %s HWC layers:\n", to_string(*displayId).c_str());
Layer::miniDumpHeader(result);
- const sp<DisplayDevice> displayDevice = display;
- mCurrentState.traverseInZOrder(
- [&](Layer* layer) { layer->miniDump(result, displayDevice); });
+
+ const DisplayDevice& ref = *display;
+ mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, ref); });
result.append("\n");
}
@@ -5404,7 +5414,7 @@
return NO_ERROR;
}
-const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
+sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack});
if (displayToken) {
return getDisplayDeviceLocked(displayToken);
@@ -5414,7 +5424,7 @@
return getDisplayByLayerStack(displayOrLayerStack);
}
-const sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) {
+sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) {
for (const auto& [token, display] : mDisplays) {
if (display->getLayerStack() == layerStack) {
return display;
@@ -5752,6 +5762,7 @@
fillLayer.alpha = half(alpha);
clientCompositionLayers.push_back(fillLayer);
+ const auto display = renderArea.getDisplayDevice();
std::vector<Layer*> renderedLayers;
Region clearRegion = Region::INVALID_REGION;
traverseLayers([&](Layer* layer) {
@@ -5760,7 +5771,7 @@
compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
clip,
useIdentityTransform,
- layer->needsFilteringForScreenshots(renderArea.getDisplayDevice(), transform) ||
+ layer->needsFilteringForScreenshots(display.get(), transform) ||
renderArea.needsFiltering(),
renderArea.isSecure(),
supportProtectedContent,
@@ -5988,7 +5999,7 @@
}
auto future = schedule([=]() -> status_t {
- const auto display = getDisplayDeviceLocked(displayToken);
+ const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken));
if (!display) {
ALOGE("Attempt to set desired display configs for invalid display token %p",
displayToken.get());
@@ -6143,7 +6154,7 @@
return BAD_VALUE;
}
- static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS {
+ static_cast<void>(schedule([=] {
Mutex::Autolock lock(mStateLock);
if (authenticateSurfaceTextureLocked(surface)) {
sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
@@ -6172,8 +6183,7 @@
sp<IBinder> token;
if (mFrameRateFlexibilityTokenCount == 0) {
- // |mStateLock| not needed as we are on the main thread
- const auto display = getDefaultDisplayDeviceLocked();
+ const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
// This is a little racy, but not in a way that hurts anything. As we grab the
// defaultConfig from the display manager policy, we could be setting a new display
@@ -6223,8 +6233,7 @@
mFrameRateFlexibilityTokenCount--;
ALOGD("Frame rate flexibility token released. count=%d", mFrameRateFlexibilityTokenCount);
if (mFrameRateFlexibilityTokenCount == 0) {
- // |mStateLock| not needed as we are on the main thread
- const auto display = getDefaultDisplayDeviceLocked();
+ const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
constexpr bool kOverridePolicy = true;
status_t result = setDesiredDisplayConfigSpecsInternal(display, {}, kOverridePolicy);
LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token");
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 509de0f..4cfbddd 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -289,12 +289,6 @@
// The CompositionEngine encapsulates all composition related interfaces and actions.
compositionengine::CompositionEngine& getCompositionEngine() const;
- // returns the default Display
- sp<const DisplayDevice> getDefaultDisplayDevice() {
- Mutex::Autolock _l(mStateLock);
- return getDefaultDisplayDeviceLocked();
- }
-
// Obtains a name from the texture pool, or, if the pool is empty, posts a
// synchronous message to the main thread to obtain one on the fly
uint32_t getNewTexture();
@@ -307,7 +301,7 @@
void setPrimaryVsyncEnabled(bool enabled);
// main thread function to enable/disable h/w composer event
- void setPrimaryVsyncEnabledInternal(bool enabled);
+ void setPrimaryVsyncEnabledInternal(bool enabled) REQUIRES(mStateLock);
void setVsyncEnabledInHWC(DisplayId displayId, hal::Vsync enabled);
// called on the main thread by MessageQueue when an internal message
@@ -722,8 +716,8 @@
status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
bool regionSampling, bool& outCapturedSecureLayers);
- const sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack);
- const sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack);
+ sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
+ sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock);
status_t captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer, bool useIdentityTransform,
@@ -751,28 +745,32 @@
// called when starting, or restarting after system_server death
void initializeDisplays();
- // NOTE: can only be called from the main thread or with mStateLock held
- sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) const {
+ sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) const
+ REQUIRES(mStateLock) {
return const_cast<SurfaceFlinger*>(this)->getDisplayDeviceLocked(displayToken);
}
- // NOTE: can only be called from the main thread or with mStateLock held
- sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) {
+ sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) REQUIRES(mStateLock) {
const auto it = mDisplays.find(displayToken);
return it == mDisplays.end() ? nullptr : it->second;
}
- sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const {
+ sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const REQUIRES(mStateLock) {
return const_cast<SurfaceFlinger*>(this)->getDefaultDisplayDeviceLocked();
}
- sp<DisplayDevice> getDefaultDisplayDeviceLocked() {
+ sp<DisplayDevice> getDefaultDisplayDeviceLocked() REQUIRES(mStateLock) {
if (const auto token = getInternalDisplayTokenLocked()) {
return getDisplayDeviceLocked(token);
}
return nullptr;
}
+ sp<const DisplayDevice> getDefaultDisplayDevice() EXCLUDES(mStateLock) {
+ Mutex::Autolock lock(mStateLock);
+ return getDefaultDisplayDeviceLocked();
+ }
+
std::optional<DeviceProductInfo> getDeviceProductInfoLocked(const DisplayDevice&) const;
// mark a region of a layer stack dirty. this updates the dirty
@@ -827,10 +825,11 @@
std::shared_ptr<compositionengine::Display> compositionDisplay,
const DisplayDeviceState& state,
const sp<compositionengine::DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer);
+ const sp<IGraphicBufferProducer>& producer) REQUIRES(mStateLock);
void processDisplayChangesLocked() REQUIRES(mStateLock);
- void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state);
- void processDisplayRemoved(const wp<IBinder>& displayToken);
+ void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&)
+ REQUIRES(mStateLock);
+ void processDisplayRemoved(const wp<IBinder>& displayToken) REQUIRES(mStateLock);
void processDisplayChanged(const wp<IBinder>& displayToken,
const DisplayDeviceState& currentState,
const DisplayDeviceState& drawingState) REQUIRES(mStateLock);
@@ -873,12 +872,13 @@
/*
* Display identification
*/
- sp<IBinder> getPhysicalDisplayTokenLocked(DisplayId displayId) const {
+ sp<IBinder> getPhysicalDisplayTokenLocked(DisplayId displayId) const REQUIRES(mStateLock) {
const auto it = mPhysicalDisplayTokens.find(displayId);
return it != mPhysicalDisplayTokens.end() ? it->second : nullptr;
}
- std::optional<DisplayId> getPhysicalDisplayIdLocked(const sp<IBinder>& displayToken) const {
+ std::optional<DisplayId> getPhysicalDisplayIdLocked(const sp<IBinder>& displayToken) const
+ REQUIRES(mStateLock) {
for (const auto& [id, token] : mPhysicalDisplayTokens) {
if (token == displayToken) {
return id;
@@ -888,12 +888,12 @@
}
// TODO(b/74619554): Remove special cases for primary display.
- sp<IBinder> getInternalDisplayTokenLocked() const {
+ sp<IBinder> getInternalDisplayTokenLocked() const REQUIRES(mStateLock) {
const auto displayId = getInternalDisplayIdLocked();
return displayId ? getPhysicalDisplayTokenLocked(*displayId) : nullptr;
}
- std::optional<DisplayId> getInternalDisplayIdLocked() const {
+ std::optional<DisplayId> getInternalDisplayIdLocked() const REQUIRES(mStateLock) {
const auto hwcDisplayId = getHwComposer().getInternalHwcDisplayId();
return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
}
@@ -945,9 +945,9 @@
void recordBufferingStats(const std::string& layerName,
std::vector<OccupancyTracker::Segment>&& history);
void dumpBufferingStats(std::string& result) const;
- void dumpDisplayIdentificationData(std::string& result) const;
+ void dumpDisplayIdentificationData(std::string& result) const REQUIRES(mStateLock);
void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
- void dumpWideColorInfo(std::string& result) const;
+ void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock);
LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
void dumpOffscreenLayersProto(LayersProto& layersProto,
uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
@@ -974,7 +974,7 @@
/* ------------------------------------------------------------------------
* VrFlinger
*/
- void resetDisplayState();
+ void resetDisplayState() REQUIRES(mStateLock);
// Check to see if we should handoff to vr flinger.
void updateVrFlinger();
@@ -1053,16 +1053,14 @@
hal::HWDisplayId hwcDisplayId;
hal::Connection connection = hal::Connection::INVALID;
};
- // protected by mStateLock
- std::vector<HotplugEvent> mPendingHotplugEvents;
+ std::vector<HotplugEvent> mPendingHotplugEvents GUARDED_BY(mStateLock);
// this may only be written from the main thread with mStateLock held
// it may be read from other threads with mStateLock held
- std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays;
- std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
+ std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays GUARDED_BY(mStateLock);
+ std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens GUARDED_BY(mStateLock);
- // protected by mStateLock
- std::unordered_map<BBinder*, wp<Layer>> mLayersByLocalBinderToken;
+ std::unordered_map<BBinder*, wp<Layer>> mLayersByLocalBinderToken GUARDED_BY(mStateLock);
// don't use a lock for these, we don't care
int mDebugRegion = 0;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 8713b2b..32d722e 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -1073,7 +1073,8 @@
struct ForcedClientCompositionResultVariant : public CompositionResultBaseVariant {
static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
- const auto outputLayer = layer->findOutputLayerForDisplay(test->mDisplay);
+ const auto outputLayer =
+ TestableSurfaceFlinger::findOutputLayerForDisplay(layer, test->mDisplay);
LOG_FATAL_IF(!outputLayer);
outputLayer->editState().forceClientComposition = true;
}
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 15207c9..431cf0f 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -512,45 +512,33 @@
EXPECT_EQ(1, frequentLayerCount(time));
}
-TEST_F(LayerHistoryTestV2, calculateRefreshRate30Hz) {
- const auto layer = createLayer();
- EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
- EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) {
+ auto explicitVisiblelayer = createLayer();
+ auto explicitInvisiblelayer = createLayer();
- EXPECT_EQ(1, layerCount());
- EXPECT_EQ(0, activeLayerCount());
+ EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree())
+ .WillRepeatedly(Return(
+ Layer::FrameRate(60.0f, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+ EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree())
+ .WillRepeatedly(Return(
+ Layer::FrameRate(90.0f, Layer::FrameRateCompatibility::ExactOrMultiple)));
nsecs_t time = systemTime();
- const nsecs_t frameTime = 33'333'333;
- for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
- time += frameTime;
- history().record(layer.get(), time, time);
- }
+ // Post a buffer to the layers to make them active
+ history().record(explicitVisiblelayer.get(), time, time);
+ history().record(explicitInvisiblelayer.get(), time, time);
+
+ EXPECT_EQ(2, layerCount());
ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_FLOAT_EQ(30.f, history().summarize(time)[0].desiredRefreshRate);
-}
-
-TEST_F(LayerHistoryTestV2, calculateRefreshRate30HzSkipTimestamp) {
- const auto layer = createLayer();
- EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
- EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
-
- EXPECT_EQ(1, layerCount());
- EXPECT_EQ(0, activeLayerCount());
-
- nsecs_t time = systemTime();
- const nsecs_t frameTime = 33'333'333;
-
- for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
- time += frameTime;
- const auto timestamp = (i == PRESENT_TIME_HISTORY_SIZE / 2) ? 0 : time;
- history().record(layer.get(), timestamp, time);
- }
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_FLOAT_EQ(30.f, history().summarize(time)[0].desiredRefreshRate);
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+ history().summarize(time)[0].vote);
+ EXPECT_FLOAT_EQ(60.0f, history().summarize(time)[0].desiredRefreshRate);
+ EXPECT_EQ(2, activeLayerCount());
+ EXPECT_EQ(2, frequentLayerCount(time));
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index add3327..38bc8a1 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -177,6 +177,8 @@
class TestableSurfaceFlinger {
public:
+ using HotplugEvent = SurfaceFlinger::HotplugEvent;
+
SurfaceFlinger* flinger() { return mFlinger.get(); }
TestableScheduler* scheduler() { return mScheduler; }
@@ -246,28 +248,32 @@
memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries));
}
- using HotplugEvent = SurfaceFlinger::HotplugEvent;
-
- auto& mutableLayerCurrentState(sp<Layer> layer) { return layer->mCurrentState; }
- auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mDrawingState; }
+ static auto& mutableLayerCurrentState(const sp<Layer>& layer) { return layer->mCurrentState; }
+ static auto& mutableLayerDrawingState(const sp<Layer>& layer) { return layer->mDrawingState; }
auto& mutableStateLock() { return mFlinger->mStateLock; }
- void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) {
+ static auto findOutputLayerForDisplay(const sp<Layer>& layer,
+ const sp<const DisplayDevice>& display) {
+ return layer->findOutputLayerForDisplay(display.get());
+ }
+
+ static void setLayerSidebandStream(const sp<Layer>& layer,
+ const sp<NativeHandle>& sidebandStream) {
layer->mDrawingState.sidebandStream = sidebandStream;
layer->mSidebandStream = sidebandStream;
layer->editCompositionState()->sidebandStream = sidebandStream;
}
- void setLayerCompositionType(sp<Layer> layer, hal::Composition type) {
- auto outputLayer = layer->findOutputLayerForDisplay(mFlinger->getDefaultDisplayDevice());
+ void setLayerCompositionType(const sp<Layer>& layer, hal::Composition type) {
+ auto outputLayer = findOutputLayerForDisplay(layer, mFlinger->getDefaultDisplayDevice());
LOG_ALWAYS_FATAL_IF(!outputLayer);
auto& state = outputLayer->editState();
LOG_ALWAYS_FATAL_IF(!outputLayer->getState().hwc);
(*state.hwc).hwcCompositionType = type;
- };
+ }
- void setLayerPotentialCursor(sp<Layer> layer, bool potentialCursor) {
+ static void setLayerPotentialCursor(const sp<Layer>& layer, bool potentialCursor) {
layer->mPotentialCursor = potentialCursor;
}
@@ -283,14 +289,14 @@
return mFlinger->destroyDisplay(displayToken);
}
- auto resetDisplayState() { return mFlinger->resetDisplayState(); }
+ auto resetDisplayState() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->resetDisplayState(); }
auto setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
const DisplayDeviceState& state,
const sp<compositionengine::DisplaySurface>& dispSurface,
- const sp<IGraphicBufferProducer>& producer) {
+ const sp<IGraphicBufferProducer>& producer) NO_THREAD_SAFETY_ANALYSIS {
return mFlinger->setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
dispSurface, producer);
}