diff options
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 |