summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/atrace/atrace.cpp1
-rw-r--r--libs/binder/Parcel.cpp18
-rw-r--r--libs/binder/Status.cpp31
-rw-r--r--libs/graphicsenv/GraphicsEnv.cpp111
-rw-r--r--libs/graphicsenv/include/graphicsenv/GraphicsEnv.h1
-rw-r--r--opengl/libs/Android.bp4
-rw-r--r--opengl/libs/EGL/Loader.cpp88
-rw-r--r--opengl/libs/EGL/Loader.h1
-rw-r--r--opengl/libs/EGL/egl.cpp10
-rw-r--r--opengl/libs/EGL/egl_display.cpp2
-rw-r--r--opengl/libs/EGL/egldefs.h7
-rw-r--r--services/inputflinger/InputClassifier.cpp2
-rw-r--r--services/inputflinger/InputDispatcher.cpp3
-rw-r--r--services/sensorservice/SensorDevice.cpp61
-rw-r--r--services/sensorservice/SensorDevice.h6
-rw-r--r--services/surfaceflinger/BufferLayer.cpp6
-rw-r--r--services/surfaceflinger/BufferQueueLayer.cpp2
-rw-r--r--services/surfaceflinger/BufferStateLayer.cpp2
-rw-r--r--services/surfaceflinger/Layer.cpp59
-rw-r--r--services/surfaceflinger/Layer.h23
-rw-r--r--services/surfaceflinger/RegionSamplingThread.cpp65
-rw-r--r--services/surfaceflinger/RegionSamplingThread.h5
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp41
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h11
-rw-r--r--services/surfaceflinger/tests/SurfaceFlinger_test.filter2
-rw-r--r--services/surfaceflinger/tests/Transaction_test.cpp176
-rw-r--r--services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp72
28 files changed, 667 insertions, 145 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 7ac0eb7d69..a4b00f8e0c 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -890,6 +890,7 @@ static void cleanUpUserspaceTracing()
setTagsProperty(0);
clearAppProperties();
pokeBinderServices();
+ pokeHalServices();
if (g_tracePdx) {
ServiceUtility::PokeServices();
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 5427ff8e4c..afa3d33349 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2086,8 +2086,8 @@ status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const {
const char* Parcel::readCString() const
{
- const size_t avail = mDataSize-mDataPos;
- if (avail > 0) {
+ if (mDataPos < mDataSize) {
+ const size_t avail = mDataSize-mDataPos;
const char* str = reinterpret_cast<const char*>(mData+mDataPos);
// is the string's trailing NUL within the parcel's valid bounds?
const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
@@ -2835,10 +2835,16 @@ status_t Parcel::continueWrite(size_t desired)
}
release_object(proc, *flat, this, &mOpenAshmemSize);
}
- binder_size_t* objects =
- (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
- if (objects) {
- mObjects = objects;
+
+ if (objectsSize == 0) {
+ free(mObjects);
+ mObjects = nullptr;
+ } else {
+ binder_size_t* objects =
+ (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
+ if (objects) {
+ mObjects = objects;
+ }
}
mObjectsSize = objectsSize;
mNextObjectHint = 0;
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 8b33a56484..0ad99cee3f 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -102,13 +102,23 @@ status_t Status::readFromParcel(const Parcel& parcel) {
// Skip over fat response headers. Not used (or propagated) in native code.
if (mException == EX_HAS_REPLY_HEADER) {
// Note that the header size includes the 4 byte size field.
- const int32_t header_start = parcel.dataPosition();
+ const size_t header_start = parcel.dataPosition();
+ // Get available size before reading more
+ const size_t header_avail = parcel.dataAvail();
+
int32_t header_size;
status = parcel.readInt32(&header_size);
if (status != OK) {
setFromStatusT(status);
return status;
}
+
+ if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
+
parcel.setDataPosition(header_start + header_size);
// And fat response headers are currently only used when there are no
// exceptions, so act like there was no error.
@@ -135,19 +145,36 @@ status_t Status::readFromParcel(const Parcel& parcel) {
setFromStatusT(status);
return status;
}
+ if (remote_stack_trace_header_size < 0 ||
+ static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) {
+
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel.readInt32(&mErrorCode);
} else if (mException == EX_PARCELABLE) {
// Skip over the blob of Parcelable data
- const int32_t header_start = parcel.dataPosition();
+ const size_t header_start = parcel.dataPosition();
+ // Get available size before reading more
+ const size_t header_avail = parcel.dataAvail();
+
int32_t header_size;
status = parcel.readInt32(&header_size);
if (status != OK) {
setFromStatusT(status);
return status;
}
+
+ if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
+
parcel.setDataPosition(header_start + header_size);
}
if (status != OK) {
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 407f77d88b..1c5fa52855 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -534,60 +534,73 @@ void GraphicsEnv::setDebugLayersGLES(const std::string layers) {
mDebugLayersGLES = layers;
}
+// Return true if all the required libraries from vndk and sphal namespace are
+// linked to the Game Driver namespace correctly.
+bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
+ const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
+ if (llndkLibraries.empty()) {
+ return false;
+ }
+ if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
+ ALOGE("Failed to link default namespace[%s]", dlerror());
+ return false;
+ }
+
+ const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
+ if (vndkspLibraries.empty()) {
+ return false;
+ }
+ if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+ ALOGE("Failed to link vndk namespace[%s]", dlerror());
+ return false;
+ }
+
+ if (mSphalLibraries.empty()) {
+ return true;
+ }
+
+ // Make additional libraries in sphal to be accessible
+ auto sphalNamespace = android_get_exported_namespace("sphal");
+ if (!sphalNamespace) {
+ ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
+ mSphalLibraries.c_str());
+ return false;
+ }
+
+ if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
+ ALOGE("Failed to link sphal namespace[%s]", dlerror());
+ return false;
+ }
+
+ return true;
+}
+
android_namespace_t* GraphicsEnv::getDriverNamespace() {
- static std::once_flag once;
- std::call_once(once, [this]() {
- if (mDriverPath.empty()) return;
-
- auto vndkNamespace = android_get_exported_namespace("vndk");
- if (!vndkNamespace) return;
-
- mDriverNamespace = android_create_namespace("gfx driver",
- mDriverPath.c_str(), // ld_library_path
- mDriverPath.c_str(), // default_library_path
- ANDROID_NAMESPACE_TYPE_ISOLATED,
- nullptr, // permitted_when_isolated_path
- nullptr);
-
- const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
- if (llndkLibraries.empty()) {
- mDriverNamespace = nullptr;
- return;
- }
- if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
- ALOGE("Failed to link default namespace[%s]", dlerror());
- mDriverNamespace = nullptr;
- return;
- }
+ std::lock_guard<std::mutex> lock(mNamespaceMutex);
- const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
- if (vndkspLibraries.empty()) {
- mDriverNamespace = nullptr;
- return;
- }
- if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
- ALOGE("Failed to link vndk namespace[%s]", dlerror());
- mDriverNamespace = nullptr;
- return;
- }
+ if (mDriverNamespace) {
+ return mDriverNamespace;
+ }
- if (mSphalLibraries.empty()) return;
+ if (mDriverPath.empty()) {
+ return nullptr;
+ }
- // Make additional libraries in sphal to be accessible
- auto sphalNamespace = android_get_exported_namespace("sphal");
- if (!sphalNamespace) {
- ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
- mSphalLibraries.c_str());
- mDriverNamespace = nullptr;
- return;
- }
+ auto vndkNamespace = android_get_exported_namespace("vndk");
+ if (!vndkNamespace) {
+ return nullptr;
+ }
- if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
- ALOGE("Failed to link sphal namespace[%s]", dlerror());
- mDriverNamespace = nullptr;
- return;
- }
- });
+ mDriverNamespace = android_create_namespace("gfx driver",
+ mDriverPath.c_str(), // ld_library_path
+ mDriverPath.c_str(), // default_library_path
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr, // permitted_when_isolated_path
+ nullptr);
+
+ if (!linkDriverNamespaceLocked(vndkNamespace)) {
+ mDriverNamespace = nullptr;
+ }
return mDriverNamespace;
}
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 7d627500fd..f5d19db493 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -129,6 +129,7 @@ private:
void* loadLibrary(std::string name);
bool checkAngleRules(void* so);
void updateUseAngle();
+ bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace);
GraphicsEnv() = default;
std::string mDriverPath;
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index c0bace8486..abc7a72716 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -208,6 +208,10 @@ cc_library_shared {
defaults: ["gles_libs_defaults"],
srcs: ["GLES2/gl2.cpp"],
cflags: ["-DLOG_TAG=\"libGLESv2\""],
+
+ // Bug: http://b/133874658 Disable native_coverage as we investigate a
+ // crash in surfaceflinger on coverage-enabled cuttlefish builds.
+ native_coverage: false,
}
//##############################################################################
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index d5c46c6683..038a432337 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -84,6 +84,11 @@ static void* do_android_load_sphal_library(const char* path, int mode) {
return android_load_sphal_library(path, mode);
}
+static int do_android_unload_sphal_library(void* dso) {
+ ATRACE_CALL();
+ return android_unload_sphal_library(dso);
+}
+
Loader::driver_t::driver_t(void* gles)
{
dso[0] = gles;
@@ -180,11 +185,81 @@ static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
"ro.board.platform",
};
+static bool should_unload_system_driver(egl_connection_t* cnx) {
+ // Return false if the system driver has been unloaded once.
+ if (cnx->systemDriverUnloaded) {
+ return false;
+ }
+
+ // Return true if Angle namespace is set.
+ android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
+ if (ns) {
+ return true;
+ }
+
+#ifndef __ANDROID_VNDK__
+ // Return true if updated driver namespace is set.
+ ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+ if (ns) {
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+static void uninit_api(char const* const* api, __eglMustCastToProperFunctionPointerType* curr) {
+ while (*api) {
+ *curr++ = nullptr;
+ api++;
+ }
+}
+
+void Loader::unload_system_driver(egl_connection_t* cnx) {
+ ATRACE_CALL();
+
+ uninit_api(gl_names,
+ (__eglMustCastToProperFunctionPointerType*)&cnx
+ ->hooks[egl_connection_t::GLESv2_INDEX]
+ ->gl);
+ uninit_api(gl_names,
+ (__eglMustCastToProperFunctionPointerType*)&cnx
+ ->hooks[egl_connection_t::GLESv1_INDEX]
+ ->gl);
+ uninit_api(egl_names, (__eglMustCastToProperFunctionPointerType*)&cnx->egl);
+
+ if (cnx->dso) {
+ ALOGD("Unload system gl driver.");
+ driver_t* hnd = (driver_t*)cnx->dso;
+ if (hnd->dso[2]) {
+ do_android_unload_sphal_library(hnd->dso[2]);
+ }
+ if (hnd->dso[1]) {
+ do_android_unload_sphal_library(hnd->dso[1]);
+ }
+ if (hnd->dso[0]) {
+ do_android_unload_sphal_library(hnd->dso[0]);
+ }
+ cnx->dso = nullptr;
+ }
+
+ cnx->systemDriverUnloaded = true;
+}
+
void* Loader::open(egl_connection_t* cnx)
{
ATRACE_CALL();
const nsecs_t openTime = systemTime();
+ if (should_unload_system_driver(cnx)) {
+ unload_system_driver(cnx);
+ }
+
+ // If a driver has been loaded, return the driver directly.
+ if (cnx->dso) {
+ return cnx->dso;
+ }
+
setEmulatorGlesValue();
// Check if we should use ANGLE early, so loading each driver doesn't require repeated queries.
@@ -244,9 +319,15 @@ void* Loader::open(egl_connection_t* cnx)
"couldn't find an OpenGL ES implementation, make sure you set %s or %s",
HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]);
- cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
- cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
- cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+ if (!cnx->libEgl) {
+ cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
+ }
+ if (!cnx->libGles1) {
+ cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+ }
+ if (!cnx->libGles2) {
+ cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
+ }
if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
@@ -584,6 +665,7 @@ Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx)
return nullptr;
}
+ ALOGD("Load updated gl driver.");
android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL_UPDATED);
driver_t* hnd = nullptr;
void* dso = load_updated_driver("GLES", ns);
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 0292d02e1d..6f31ab4741 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -58,6 +58,7 @@ private:
driver_t* attempt_to_load_angle(egl_connection_t* cnx);
driver_t* attempt_to_load_updated_driver(egl_connection_t* cnx);
driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
+ void unload_system_driver(egl_connection_t* cnx);
void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
static __attribute__((noinline))
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 8870d5f571..25b1009ba2 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -187,13 +187,9 @@ static EGLBoolean egl_init_drivers_locked() {
// dynamically load our EGL implementation
egl_connection_t* cnx = &gEGLImpl;
- if (cnx->dso == nullptr) {
- cnx->hooks[egl_connection_t::GLESv1_INDEX] =
- &gHooks[egl_connection_t::GLESv1_INDEX];
- cnx->hooks[egl_connection_t::GLESv2_INDEX] =
- &gHooks[egl_connection_t::GLESv2_INDEX];
- cnx->dso = loader.open(cnx);
- }
+ cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX];
+ cnx->hooks[egl_connection_t::GLESv2_INDEX] = &gHooks[egl_connection_t::GLESv2_INDEX];
+ cnx->dso = loader.open(cnx);
// Check to see if any layers are enabled and route functions through them
if (cnx->dso) {
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 8841a3b02c..67d69b4d06 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -217,7 +217,7 @@ EGLDisplay egl_display_t::getPlatformDisplay(EGLNativeDisplayType display,
Loader& loader(Loader::getInstance());
egl_connection_t* const cnx = &gEGLImpl;
- if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
+ if (cnx->dso) {
EGLDisplay dpy = EGL_NO_DISPLAY;
if (cnx->useAngle) {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 9e112cc034..7bb9b59ea4 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -44,7 +44,11 @@ struct egl_connection_t {
GLESv2_INDEX = 1
};
- inline egl_connection_t() : dso(nullptr) {
+ inline egl_connection_t() : dso(nullptr),
+ libEgl(nullptr),
+ libGles1(nullptr),
+ libGles2(nullptr),
+ systemDriverUnloaded(false) {
char const* const* entries = platform_names;
EGLFuncPointer* curr = reinterpret_cast<EGLFuncPointer*>(&platform);
@@ -76,6 +80,7 @@ struct egl_connection_t {
void* libGles1;
void* libGles2;
+ bool systemDriverUnloaded;
bool shouldUseAngle; // Should we attempt to load ANGLE
bool angleDecided; // Have we tried to load ANGLE
bool useAngle; // Was ANGLE successfully loaded
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index ef1a2247e9..6a7f2797f4 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -82,7 +82,7 @@ static bool isTouchEvent(const NotifyMotionArgs& args) {
// Check if the "deep touch" feature is on.
static bool deepPressEnabled() {
std::string flag_value = server_configurable_flags::GetServerConfigurableFlag(
- INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "true");
+ INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "false");
std::transform(flag_value.begin(), flag_value.end(), flag_value.begin(), ::tolower);
if (flag_value == "1" || flag_value == "true") {
ALOGI("Deep press feature enabled.");
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 31a2dab6c5..c2ff4c9629 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -2172,9 +2172,8 @@ void InputDispatcher::dispatchPointerDownOutsideFocus(uint32_t source, int32_t a
return;
}
- int32_t displayId = inputWindowHandle->getInfo()->displayId;
sp<InputWindowHandle> focusedWindowHandle =
- getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+ getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
bool hasFocusChanged = !focusedWindowHandle || focusedWindowHandle->getToken() != newToken;
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index fcd4f29adf..717f31769b 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -45,7 +45,9 @@ namespace android {
ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
-static status_t StatusFromResult(Result result) {
+namespace {
+
+status_t statusFromResult(Result result) {
switch (result) {
case Result::OK:
return OK;
@@ -71,6 +73,8 @@ enum EventQueueFlagBitsInternal : uint32_t {
INTERNAL_WAKE = 1 << 16,
};
+} // anonymous namespace
+
void SensorsHalDeathReceivier::serviceDied(
uint64_t /* cookie */,
const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
@@ -105,7 +109,7 @@ SensorDevice::SensorDevice()
initializeSensorList();
mIsDirectReportSupported =
- (checkReturn(mSensors->unregisterDirectChannel(-1)) != Result::INVALID_OPERATION);
+ (checkReturnAndGetStatus(mSensors->unregisterDirectChannel(-1)) != INVALID_OPERATION);
}
void SensorDevice::initializeSensorList() {
@@ -122,7 +126,7 @@ void SensorDevice::initializeSensorList() {
convertToSensor(list[i], &sensor);
// Sanity check and clamp power if it is 0 (or close)
if (sensor.power < minPowerMa) {
- ALOGE("Reported power %f not deemed sane, clamping to %f",
+ ALOGI("Reported power %f not deemed sane, clamping to %f",
sensor.power, minPowerMa);
sensor.power = minPowerMa;
}
@@ -217,10 +221,10 @@ SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV2_0() {
mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
mWakeLockQueueFlag != nullptr);
- status_t status = StatusFromResult(checkReturn(mSensors->initialize(
+ status_t status = checkReturnAndGetStatus(mSensors->initialize(
*mEventQueue->getDesc(),
*mWakeLockQueue->getDesc(),
- new SensorsCallback())));
+ new SensorsCallback()));
if (status != NO_ERROR) {
connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
@@ -270,6 +274,8 @@ bool SensorDevice::sensorHandlesChanged(const Vector<sensor_t>& oldSensorList,
bool didChange = false;
if (oldSensorList.size() != newSensorList.size()) {
+ ALOGI("Sensor list size changed from %zu to %zu", oldSensorList.size(),
+ newSensorList.size());
didChange = true;
}
@@ -281,6 +287,7 @@ bool SensorDevice::sensorHandlesChanged(const Vector<sensor_t>& oldSensorList,
if (prevSensor.handle == newSensor.handle) {
found = true;
if (!sensorIsEquivalent(prevSensor, newSensor)) {
+ ALOGI("Sensor %s not equivalent to previous version", newSensor.name);
didChange = true;
}
}
@@ -289,6 +296,7 @@ bool SensorDevice::sensorHandlesChanged(const Vector<sensor_t>& oldSensorList,
if (!found) {
// Could not find the new sensor in the old list of sensors, the lists must
// have changed.
+ ALOGI("Sensor %s (handle %d) did not exist before", newSensor.name, newSensor.handle);
didChange = true;
}
}
@@ -423,7 +431,7 @@ ssize_t SensorDevice::pollHal(sensors_event_t* buffer, size_t count) {
convertToSensorEvents(events, dynamicSensorsAdded, buffer);
err = (ssize_t)events.size();
} else {
- err = StatusFromResult(result);
+ err = statusFromResult(result);
}
});
@@ -621,7 +629,7 @@ status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {
if (actuateHardware) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
enabled);
- err = StatusFromResult(checkReturn(mSensors->activate(handle, enabled)));
+ err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
strerror(-err));
@@ -694,9 +702,8 @@ status_t SensorDevice::batchLocked(void* ident, int handle, int flags, int64_t s
if (prevBestBatchParams != info.bestBatchParams) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
- err = StatusFromResult(
- checkReturn(mSensors->batch(
- handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch)));
+ err = checkReturnAndGetStatus(mSensors->batch(
+ handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
if (err != NO_ERROR) {
ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
mSensors.get(), handle, info.bestBatchParams.mTSample,
@@ -720,7 +727,7 @@ status_t SensorDevice::flush(void* ident, int handle) {
if (mSensors == nullptr) return NO_INIT;
if (isClientDisabled(ident)) return INVALID_OPERATION;
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
- return StatusFromResult(checkReturn(mSensors->flush(handle)));
+ return checkReturnAndGetStatus(mSensors->flush(handle));
}
bool SensorDevice::isClientDisabled(void* ident) {
@@ -753,16 +760,14 @@ void SensorDevice::enableAllSensors() {
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
sensor_handle);
- status_t err = StatusFromResult(
- checkReturn(mSensors->batch(
- sensor_handle,
- info.bestBatchParams.mTSample,
- info.bestBatchParams.mTBatch)));
+ status_t err = checkReturnAndGetStatus(mSensors->batch(
+ sensor_handle,
+ info.bestBatchParams.mTSample,
+ info.bestBatchParams.mTBatch));
ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
if (err == NO_ERROR) {
- err = StatusFromResult(
- checkReturn(mSensors->activate(sensor_handle, 1 /* enabled */)));
+ err = checkReturnAndGetStatus(mSensors->activate(sensor_handle, 1 /* enabled */));
ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
}
@@ -810,14 +815,13 @@ status_t SensorDevice::injectSensorData(
Event ev;
convertFromSensorEvent(*injected_sensor_event, &ev);
- return StatusFromResult(checkReturn(mSensors->injectSensorData(ev)));
+ return checkReturnAndGetStatus(mSensors->injectSensorData(ev));
}
status_t SensorDevice::setMode(uint32_t mode) {
if (mSensors == nullptr) return NO_INIT;
- return StatusFromResult(
- checkReturn(mSensors->setOperationMode(
- static_cast<hardware::sensors::V1_0::OperationMode>(mode))));
+ return checkReturnAndGetStatus(mSensors->setOperationMode(
+ static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
}
int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
@@ -855,7 +859,7 @@ int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory)
if (result == Result::OK) {
ret = channelHandle;
} else {
- ret = StatusFromResult(result);
+ ret = statusFromResult(result);
}
}));
return ret;
@@ -894,12 +898,12 @@ int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
[&ret, rate] (auto result, auto token) {
if (rate == RateLevel::STOP) {
- ret = StatusFromResult(result);
+ ret = statusFromResult(result);
} else {
if (result == Result::OK) {
ret = token;
} else {
- ret = StatusFromResult(result);
+ ret = statusFromResult(result);
}
}
}));
@@ -1008,7 +1012,7 @@ void SensorDevice::convertToSensorEvents(
}
void SensorDevice::handleHidlDeath(const std::string & detail) {
- if (!SensorDevice::getInstance().mSensors->supportsMessageQueues()) {
+ if (!mSensors->supportsMessageQueues()) {
// restart is the only option at present.
LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
} else {
@@ -1016,5 +1020,10 @@ void SensorDevice::handleHidlDeath(const std::string & detail) {
}
}
+status_t SensorDevice::checkReturnAndGetStatus(const Return<Result>& ret) {
+ checkReturn(ret);
+ return (!ret.isOk()) ? DEAD_OBJECT : statusFromResult(ret);
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index e8685c292c..d2c6994023 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -211,14 +211,14 @@ private:
status_t batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
int64_t maxBatchReportLatencyNs);
- static void handleHidlDeath(const std::string &detail);
+ void handleHidlDeath(const std::string &detail);
template<typename T>
- static Return<T> checkReturn(Return<T> &&ret) {
+ void checkReturn(const Return<T>& ret) {
if (!ret.isOk()) {
handleHidlDeath(ret.description());
}
- return std::move(ret);
}
+ status_t checkReturnAndGetStatus(const Return<Result>& ret);
//TODO(b/67425500): remove waiter after bug is resolved.
sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index a2b6ab6b4d..9d723998c4 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -545,6 +545,12 @@ void BufferLayer::notifyAvailableFrames() {
if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled &&
presentTimeIsCurrent) {
point->setFrameAvailable();
+ sp<Layer> requestedSyncLayer = point->getRequestedSyncLayer();
+ if (requestedSyncLayer) {
+ // Need to update the transaction flag to ensure the layer's pending transaction
+ // gets applied.
+ requestedSyncLayer->setTransactionFlags(eTransactionNeeded);
+ }
}
}
}
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index bd0b55f688..57f1008e85 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -143,7 +143,7 @@ bool BufferQueueLayer::framePresentTimeIsCurrent() const {
}
Mutex::Autolock lock(mQueueItemLock);
- return mQueueItems[0].mTimestamp <= mFlinger->mScheduler->expectedPresentTime();
+ return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime();
}
nsecs_t BufferQueueLayer::getDesiredPresentTime() {
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index bcc9915099..2abc1a75a9 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -374,7 +374,7 @@ bool BufferStateLayer::framePresentTimeIsCurrent() const {
return true;
}
- return mDesiredPresentTime <= mFlinger->mScheduler->expectedPresentTime();
+ return mDesiredPresentTime <= mFlinger->getExpectedPresentTime();
}
nsecs_t BufferStateLayer::getDesiredPresentTime() {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 379b004f9e..898f3bc992 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -144,28 +144,47 @@ Layer::~Layer() {
*/
void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
-void Layer::onRemovedFromCurrentState() {
- mRemovedFromCurrentState = true;
+void Layer::removeRemoteSyncPoints() {
+ for (auto& point : mRemoteSyncPoints) {
+ point->setTransactionApplied();
+ }
+ mRemoteSyncPoints.clear();
- // the layer is removed from SF mCurrentState to mLayersPendingRemoval
- if (mCurrentState.zOrderRelativeOf != nullptr) {
- sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
- if (strongRelative != nullptr) {
- strongRelative->removeZOrderRelative(this);
- mFlinger->setTransactionFlags(eTraversalNeeded);
+ {
+ Mutex::Autolock pendingStateLock(mPendingStateMutex);
+ for (State pendingState : mPendingStates) {
+ pendingState.barrierLayer_legacy = nullptr;
}
+ }
+}
+
+void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) {
+ if (mCurrentState.zOrderRelativeOf == nullptr) {
+ return;
+ }
+
+ sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+ if (strongRelative == nullptr) {
setZOrderRelativeOf(nullptr);
+ return;
}
+ if (!std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) {
+ strongRelative->removeZOrderRelative(this);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
+ setZOrderRelativeOf(nullptr);
+ }
+}
+
+void Layer::removeFromCurrentState() {
+ mRemovedFromCurrentState = true;
+
// Since we are no longer reachable from CurrentState SurfaceFlinger
// will no longer invoke doTransaction for us, and so we will
// never finish applying transactions. We signal the sync point
// now so that another layer will not become indefinitely
// blocked.
- for (auto& point: mRemoteSyncPoints) {
- point->setTransactionApplied();
- }
- mRemoteSyncPoints.clear();
+ removeRemoteSyncPoints();
{
Mutex::Autolock syncLock(mLocalSyncPointMutex);
@@ -175,13 +194,18 @@ void Layer::onRemovedFromCurrentState() {
mLocalSyncPoints.clear();
}
- for (const auto& child : mCurrentChildren) {
- child->onRemovedFromCurrentState();
- }
-
mFlinger->markLayerPendingRemovalLocked(this);
}
+void Layer::onRemovedFromCurrentState() {
+ auto layersInTree = getLayersInTree(LayerVector::StateSet::Current);
+ std::sort(layersInTree.begin(), layersInTree.end());
+ for (const auto& layer : layersInTree) {
+ layer->removeFromCurrentState();
+ layer->removeRelativeZ(layersInTree);
+ }
+}
+
void Layer::addToCurrentState() {
mRemovedFromCurrentState = false;
@@ -667,7 +691,7 @@ void Layer::pushPendingState() {
// to be applied as per normal (no synchronization).
mCurrentState.barrierLayer_legacy = nullptr;
} else {
- auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy);
+ auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy, this);
if (barrierLayer->addSyncPoint(syncPoint)) {
mRemoteSyncPoints.push_back(std::move(syncPoint));
} else {
@@ -1510,6 +1534,7 @@ bool Layer::detachChildren() {
if (client != nullptr && parentClient != client) {
child->mLayerDetached = true;
child->detachChildren();
+ child->removeRemoteSyncPoints();
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 7aecc90ea3..6db6beb4f6 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -570,6 +570,17 @@ public:
virtual bool isBufferLatched() const { return false; }
/*
+ * Remove relative z for the layer if its relative parent is not part of the
+ * provided layer tree.
+ */
+ void removeRelativeZ(const std::vector<Layer*>& layersInTree);
+
+ /*
+ * Remove from current state and mark for removal.
+ */
+ void removeFromCurrentState();
+
+ /*
* called with the state lock from a binder thread when the layer is
* removed from the current list to the pending removal list
*/
@@ -735,8 +746,11 @@ protected:
class SyncPoint {
public:
- explicit SyncPoint(uint64_t frameNumber)
- : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+ explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer)
+ : mFrameNumber(frameNumber),
+ mFrameIsAvailable(false),
+ mTransactionIsApplied(false),
+ mRequestedSyncLayer(requestedSyncLayer) {}
uint64_t getFrameNumber() const { return mFrameNumber; }
@@ -748,10 +762,13 @@ protected:
void setTransactionApplied() { mTransactionIsApplied = true; }
+ sp<Layer> getRequestedSyncLayer() { return mRequestedSyncLayer.promote(); }
+
private:
const uint64_t mFrameNumber;
std::atomic<bool> mFrameIsAvailable;
std::atomic<bool> mTransactionIsApplied;
+ wp<Layer> mRequestedSyncLayer;
};
// SyncPoints which will be signaled when the correct frame is at the head
@@ -930,6 +947,8 @@ private:
void setZOrderRelativeOf(const wp<Layer>& relativeOf);
bool mGetHandleCalled = false;
+
+ void removeRemoteSyncPoints();
};
} // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 368426018b..66906e950c 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -26,6 +26,8 @@
#include <utils/Trace.h>
#include <string>
+#include <compositionengine/Display.h>
+#include <compositionengine/impl/OutputCompositionState.h>
#include "DisplayDevice.h"
#include "Layer.h"
#include "SurfaceFlinger.h"
@@ -264,7 +266,26 @@ float getLuma(float r, float g, float b) {
}
} // anonymous namespace
-float sampleArea(const uint32_t* data, int32_t stride, const Rect& area) {
+float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride,
+ uint32_t orientation, const Rect& sample_area) {
+ if (!sample_area.isValid() || (sample_area.getWidth() > width) ||
+ (sample_area.getHeight() > height)) {
+ ALOGE("invalid sampling region requested");
+ return 0.0f;
+ }
+
+ // (b/133849373) ROT_90 screencap images produced upside down
+ auto area = sample_area;
+ if (orientation & ui::Transform::ROT_90) {
+ area.top = height - area.top;
+ area.bottom = height - area.bottom;
+ std::swap(area.top, area.bottom);
+
+ area.left = width - area.left;
+ area.right = width - area.right;
+ std::swap(area.left, area.right);
+ }
+
std::array<int32_t, 256> brightnessBuckets = {};
const int32_t majoritySampleNum = area.getWidth() * area.getHeight() / 2;
@@ -293,18 +314,21 @@ float sampleArea(const uint32_t* data, int32_t stride, const Rect& area) {
std::vector<float> RegionSamplingThread::sampleBuffer(
const sp<GraphicBuffer>& buffer, const Point& leftTop,
- const std::vector<RegionSamplingThread::Descriptor>& descriptors) {
+ const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation) {
void* data_raw = nullptr;
buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, &data_raw);
std::shared_ptr<uint32_t> data(reinterpret_cast<uint32_t*>(data_raw),
[&buffer](auto) { buffer->unlock(); });
if (!data) return {};
+ const int32_t width = buffer->getWidth();
+ const int32_t height = buffer->getHeight();
const int32_t stride = buffer->getStride();
std::vector<float> lumas(descriptors.size());
std::transform(descriptors.begin(), descriptors.end(), lumas.begin(),
[&](auto const& descriptor) {
- return sampleArea(data.get(), stride, descriptor.area - leftTop);
+ return sampleArea(data.get(), width, height, stride, orientation,
+ descriptor.area - leftTop);
});
return lumas;
}
@@ -317,6 +341,11 @@ void RegionSamplingThread::captureSample() {
return;
}
+ const auto device = mFlinger.getDefaultDisplayDevice();
+ const auto display = device->getCompositionDisplay();
+ const auto state = display->getState();
+ const auto orientation = static_cast<ui::Transform::orientation_flags>(state.orientation);
+
std::vector<RegionSamplingThread::Descriptor> descriptors;
Region sampleRegion;
for (const auto& [listener, descriptor] : mDescriptors) {
@@ -326,10 +355,28 @@ void RegionSamplingThread::captureSample() {
const Rect sampledArea = sampleRegion.bounds();
- sp<const DisplayDevice> device = mFlinger.getDefaultDisplayDevice();
- DisplayRenderArea renderArea(device, sampledArea, sampledArea.getWidth(),
- sampledArea.getHeight(), ui::Dataspace::V0_SRGB,
- ui::Transform::ROT_0);
+ auto dx = 0;
+ auto dy = 0;
+ switch (orientation) {
+ case ui::Transform::ROT_90:
+ dx = device->getWidth();
+ break;
+ case ui::Transform::ROT_180:
+ dx = device->getWidth();
+ dy = device->getHeight();
+ break;
+ case ui::Transform::ROT_270:
+ dy = device->getHeight();
+ break;
+ default:
+ break;
+ }
+
+ ui::Transform t(orientation);
+ auto screencapRegion = t.transform(sampleRegion);
+ screencapRegion = screencapRegion.translate(dx, dy);
+ DisplayRenderArea renderArea(device, screencapRegion.bounds(), sampledArea.getWidth(),
+ sampledArea.getHeight(), ui::Dataspace::V0_SRGB, orientation);
std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
@@ -395,8 +442,8 @@ void RegionSamplingThread::captureSample() {
}
ALOGV("Sampling %zu descriptors", activeDescriptors.size());
- std::vector<float> lumas = sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors);
-
+ std::vector<float> lumas =
+ sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors, orientation);
if (lumas.size() != activeDescriptors.size()) {
ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(),
activeDescriptors.size());
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index 08134e6acd..3c6fcf3872 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -37,7 +37,8 @@ class Scheduler;
class SurfaceFlinger;
struct SamplingOffsetCallback;
-float sampleArea(const uint32_t* data, int32_t stride, const Rect& area);
+float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride,
+ uint32_t orientation, const Rect& area);
class RegionSamplingThread : public IBinder::DeathRecipient {
public:
@@ -94,7 +95,7 @@ private:
};
std::vector<float> sampleBuffer(
const sp<GraphicBuffer>& buffer, const Point& leftTop,
- const std::vector<RegionSamplingThread::Descriptor>& descriptors);
+ const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation);
void doSample();
void binderDied(const wp<IBinder>& who) override;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index f6cc87bb89..d311f62fdb 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -297,7 +297,7 @@ private:
const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
// Global config to force HDR content to work on DEFAULT refreshRate
- static constexpr bool mForceHDRContentToDefaultRefreshRate = true;
+ static constexpr bool mForceHDRContentToDefaultRefreshRate = false;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 278191079f..982a33e48a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1530,10 +1530,25 @@ void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDispl
void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {
ATRACE_CALL();
- Mutex::Autolock lock(mStateLock);
+
+ // Enable / Disable HWVsync from the main thread to avoid race conditions with
+ // display power state.
+ postMessageAsync(new LambdaMessage(
+ [=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
+}
+
+void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
+ ATRACE_CALL();
+
if (const auto displayId = getInternalDisplayIdLocked()) {
- getHwComposer().setVsyncEnabled(*displayId,
- enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
+ sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
+ if (display && display->isPoweredOn()) {
+ getHwComposer().setVsyncEnabled(*displayId,
+ enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
+ } else {
+ // Cache the latest vsync state and apply it when screen is on again
+ mEnableHWVsyncScreenOn = enabled;
+ }
}
}
@@ -1643,6 +1658,18 @@ bool SurfaceFlinger::previousFrameMissed() NO_THREAD_SAFETY_ANALYSIS {
return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
}
+nsecs_t SurfaceFlinger::getExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
+ DisplayStatInfo stats;
+ mScheduler->getDisplayStatInfo(&stats);
+ const nsecs_t presentTime = mScheduler->expectedPresentTime();
+ // Inflate the expected present time if we're targetting the next vsync.
+ const nsecs_t correctedTime =
+ mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
+ ? presentTime
+ : presentTime + stats.vsyncPeriod;
+ return correctedTime;
+}
+
void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
switch (what) {
@@ -3244,8 +3271,7 @@ bool SurfaceFlinger::handlePageFlip()
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (layer->hasReadyFrame()) {
frameQueued = true;
- nsecs_t expectedPresentTime;
- expectedPresentTime = mScheduler->expectedPresentTime();
+ const nsecs_t expectedPresentTime = getExpectedPresentTime();
if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.push_back(layer);
} else {
@@ -4434,6 +4460,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int
// Turn on the display
getHwComposer().setPowerMode(*displayId, mode);
if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
+ if (mEnableHWVsyncScreenOn) {
+ setPrimaryVsyncEnabledInternal(mEnableHWVsyncScreenOn);
+ mEnableHWVsyncScreenOn = false;
+ }
+
mScheduler->onScreenAcquired(mAppConnectionHandle);
mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 74fefa7a3f..df6cdf2993 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -293,11 +293,19 @@ public:
// TODO: this should be made accessible only to EventThread
void setPrimaryVsyncEnabled(bool enabled);
+ // main thread function to enable/disable h/w composer event
+ void setPrimaryVsyncEnabledInternal(bool enabled);
+
// called on the main thread by MessageQueue when an internal message
// is received
// TODO: this should be made accessible only to MessageQueue
void onMessageReceived(int32_t what);
+ // Returns the expected present time for this frame.
+ // When we are in negative offsets, we perform a correction so that the
+ // predicted vsync for the *next* frame is used instead.
+ nsecs_t getExpectedPresentTime();
+
// for debugging only
// TODO: this should be made accessible only to HWComposer
const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId);
@@ -1168,6 +1176,9 @@ private:
// The Layer pointer is removed from the set when the destructor is called so there shouldn't
// be any issues with a raw pointer referencing an invalid object.
std::unordered_set<Layer*> mOffscreenLayers;
+
+ // Flag to indicate whether to re-enable HWVsync when screen is on
+ bool mEnableHWVsyncScreenOn = false;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 5ebae1e522..6b4634ae76 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*"
+ "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*:RelativeZTest.*"
}
}
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index ec1ac4b229..f83b3eafe6 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -385,6 +385,18 @@ protected:
return createLayer(mClient, name, width, height, flags, parent);
}
+ sp<SurfaceControl> createColorLayer(const char* name, const Color& color,
+ SurfaceControl* parent = nullptr) {
+ auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */,
+ PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, parent);
+ asTransaction([&](Transaction& t) {
+ t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f});
+ t.setAlpha(colorLayer, color.a / 255.0f);
+ });
+ return colorLayer;
+ }
+
ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
// wait for previous transactions (such as setSize) to complete
Transaction().apply(true);
@@ -4725,6 +4737,48 @@ TEST_F(ChildLayerTest, DetachChildrenThenAttach) {
mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED);
}
}
+TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) {
+ sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> childNewClient =
+ newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+ ASSERT_TRUE(childNewClient != nullptr);
+ ASSERT_TRUE(childNewClient->isValid());
+
+ fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+
+ Transaction()
+ .hide(mChild)
+ .show(childNewClient)
+ .setPosition(childNewClient, 10, 10)
+ .setPosition(mFGSurfaceControl, 64, 64)
+ .apply();
+
+ {
+ mCapture = screenshot();
+ Rect rect = Rect(74, 74, 84, 84);
+ mCapture->expectBorder(rect, Color{195, 63, 63, 255});
+ mCapture->expectColor(rect, Color{200, 200, 200, 255});
+ }
+
+ Transaction()
+ .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(),
+ mFGSurfaceControl->getSurface()->getNextFrameNumber())
+ .apply();
+ Transaction().detachChildren(mFGSurfaceControl).apply();
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32));
+
+ // BufferLayer can still dequeue buffers even though there's a detached layer with a
+ // deferred transaction.
+ {
+ SCOPED_TRACE("new buffer");
+ mCapture = screenshot();
+ Rect rect = Rect(74, 74, 84, 84);
+ mCapture->expectBorder(rect, Color::RED);
+ mCapture->expectColor(rect, Color{200, 200, 200, 255});
+ }
+}
TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
asTransaction([&](Transaction& t) {
@@ -5833,4 +5887,126 @@ TEST_F(DisplayActiveConfigTest, changeAllowedConfig) {
allowedConfigs.end());
}
+class RelativeZTest : public LayerTransactionTest {
+protected:
+ virtual void SetUp() {
+ LayerTransactionTest::SetUp();
+ ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+ const auto display = SurfaceComposerClient::getInternalDisplayToken();
+ ASSERT_FALSE(display == nullptr);
+
+ // Back layer
+ mBackgroundLayer = createColorLayer("Background layer", Color::RED);
+
+ // Front layer
+ mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN);
+
+ asTransaction([&](Transaction& t) {
+ t.setDisplayLayerStack(display, 0);
+ t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer);
+ t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer);
+ });
+ }
+
+ virtual void TearDown() {
+ LayerTransactionTest::TearDown();
+ mBackgroundLayer = 0;
+ mForegroundLayer = 0;
+ }
+
+ sp<SurfaceControl> mBackgroundLayer;
+ sp<SurfaceControl> mForegroundLayer;
+};
+
+// When a layer is reparented offscreen, remove relative z order if the relative parent
+// is still onscreen so that the layer is not drawn.
+TEST_F(RelativeZTest, LayerRemoved) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ // Background layer (RED)
+ // Child layer (WHITE) (relative to foregroud layer)
+ // Foregroud layer (GREEN)
+ sp<SurfaceControl> childLayer =
+ createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get());
+
+ Transaction{}
+ .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1)
+ .show(childLayer)
+ .apply();
+
+ {
+ // The childLayer should be in front of the FG control.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+ }
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLayer, nullptr).apply();
+
+ // Background layer (RED)
+ // Child layer (WHITE)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply();
+
+ {
+ // The relative z info for child layer should be reset, leaving FG control on top.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+}
+
+// When a layer is reparented offscreen, preseve relative z order if the relative parent
+// is also offscreen. Regression test b/132613412
+TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // child level 1 (WHITE)
+ // child level 2a (BLUE)
+ // child level 3 (GREEN) (relative to child level 2b)
+ // child level 2b (BLACK)
+ sp<SurfaceControl> childLevel1 =
+ createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get());
+ sp<SurfaceControl> childLevel2a =
+ createColorLayer("child level 2a", Color::BLUE, childLevel1.get());
+ sp<SurfaceControl> childLevel2b =
+ createColorLayer("child level 2b", Color::BLACK, childLevel1.get());
+ sp<SurfaceControl> childLevel3 =
+ createColorLayer("child level 3", Color::GREEN, childLevel2a.get());
+
+ Transaction{}
+ .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1)
+ .show(childLevel2a)
+ .show(childLevel2b)
+ .show(childLevel3)
+ .apply();
+
+ {
+ // The childLevel3 should be in front of childLevel2b.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLevel1, nullptr).apply();
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // child level 1 (WHITE)
+ // child level 2 back (BLUE)
+ // child level 3 (GREEN) (relative to child level 2b)
+ // child level 2 front (BLACK)
+ Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply();
+
+ {
+ // Nothing should change at this point since relative z info was preserved.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+}
+
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
index 51d6d7e1df..160f0412d9 100644
--- a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
@@ -17,6 +17,8 @@
#undef LOG_TAG
#define LOG_TAG "RegionSamplingTest"
+#include <ui/Transform.h>
+
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <array>
@@ -33,18 +35,21 @@ public:
static int constexpr kWidth = 98;
static int constexpr kStride = 100;
static int constexpr kHeight = 29;
+ static int constexpr kOrientation = ui::Transform::ROT_0;
std::array<uint32_t, kHeight * kStride> buffer;
Rect const whole_area{0, 0, kWidth, kHeight};
};
TEST_F(RegionSamplingTest, calculate_mean_white) {
std::fill(buffer.begin(), buffer.end(), kWhite);
- EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatEq(1.0f));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+ testing::FloatEq(1.0f));
}
TEST_F(RegionSamplingTest, calculate_mean_black) {
std::fill(buffer.begin(), buffer.end(), kBlack);
- EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatEq(0.0f));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+ testing::FloatEq(0.0f));
}
TEST_F(RegionSamplingTest, calculate_mean_partial_region) {
@@ -54,7 +59,8 @@ TEST_F(RegionSamplingTest, calculate_mean_partial_region) {
whole_area.top + halfway_down};
std::fill(buffer.begin(), buffer.begin() + half, 0);
std::fill(buffer.begin() + half, buffer.end(), kWhite);
- EXPECT_THAT(sampleArea(buffer.data(), kStride, partial_region), testing::FloatEq(0.0f));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, partial_region),
+ testing::FloatEq(0.0f));
}
TEST_F(RegionSamplingTest, calculate_mean_mixed_values) {
@@ -63,15 +69,71 @@ TEST_F(RegionSamplingTest, calculate_mean_mixed_values) {
n++;
return pixel;
});
- EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatNear(0.083f, 0.01f));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+ testing::FloatNear(0.083f, 0.01f));
}
TEST_F(RegionSamplingTest, bimodal_tiebreaker) {
std::generate(buffer.begin(), buffer.end(),
[n = 0]() mutable { return (n++ % 2) ? kBlack : kWhite; });
// presently there's no tiebreaking strategy in place, accept either of the means
- EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area),
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
testing::AnyOf(testing::FloatEq(1.0), testing::FloatEq(0.0f)));
}
+TEST_F(RegionSamplingTest, bounds_checking) {
+ std::generate(buffer.begin(), buffer.end(),
+ [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
+
+ Rect invalid_region{0, 0, 4, kHeight + 1};
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+ testing::Eq(0.0));
+
+ invalid_region = Rect{0, 0, -4, kHeight};
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+ testing::Eq(0.0));
+
+ invalid_region = Rect{3, 0, 2, 0};
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+ testing::Eq(0.0));
+
+ invalid_region = Rect{0, 3, 0, 2};
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+ testing::Eq(0.0));
+}
+
+// workaround for b/133849373
+TEST_F(RegionSamplingTest, orientation_90) {
+ std::generate(buffer.begin(), buffer.end(),
+ [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
+
+ Rect tl_region{0, 0, 4, 4};
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
+ tl_region),
+ testing::Eq(1.0));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
+ tl_region),
+ testing::Eq(1.0));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
+ tl_region),
+ testing::Eq(0.0));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
+ tl_region),
+ testing::Eq(0.0));
+
+ Rect br_region{kWidth - 4, kHeight - 4, kWidth, kHeight};
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
+ br_region),
+ testing::Eq(0.0));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
+ br_region),
+ testing::Eq(0.0));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
+ br_region),
+ testing::Eq(1.0));
+ EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
+ br_region),
+ testing::Eq(1.0));
+}
+
} // namespace android