diff options
23 files changed, 534 insertions, 84 deletions
diff --git a/include/android/native_window.h b/include/android/native_window.h index cf07f1a..d44ac05 100644 --- a/include/android/native_window.h +++ b/include/android/native_window.h @@ -27,6 +27,7 @@ #define ANDROID_NATIVE_WINDOW_H #include <android/rect.h> +#include <system/window.h> #ifdef __cplusplus extern "C" { @@ -44,19 +45,6 @@ enum { WINDOW_FORMAT_RGB_565 = 4, }; -struct ANativeWindow; -/** - * {@link ANativeWindow} is opaque type that provides access to a native window. - * - * A pointer can be obtained using ANativeWindow_fromSurface(). - */ -typedef struct ANativeWindow ANativeWindow; - -/** - * {@link ANativeWindow} is a struct that represents a windows buffer. - * - * A pointer can be obtained using ANativeWindow_lock(). - */ typedef struct ANativeWindow_Buffer { // The number of pixels that are show horizontally. int32_t width; diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 345ba20..a338276 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -159,14 +159,20 @@ status_t BpBinder::dump(int fd, const Vector<String16>& args) status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { - // Once a binder has died, it will never come back to life. + // Once a binder has died, it will never come back to life. But + // note that the special case of the global service manager cannot + // die; there is no guarantee in the framework that it will be + // alive before a binder service object is instantiated, so we + // ignore errors for that special object so that + // IServiceManager::addService() calls can be retried. if (mAlive) { status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); - if (status == DEAD_OBJECT) mAlive = 0; + if (status == DEAD_OBJECT) + if (this != ProcessState::self()->getContextObject(NULL).get()) + mAlive = 0; return status; } - return DEAD_OBJECT; } diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 3c716df..e4df78a 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -28,6 +28,8 @@ #include <unistd.h> +#define ADD_SERVICE_RETRY_SECS 10 + namespace android { sp<IServiceManager> defaultServiceManager() @@ -155,13 +157,26 @@ public: virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated) { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeString16(name); - data.writeStrongBinder(service); - data.writeInt32(allowIsolated ? 1 : 0); - status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); - return err == NO_ERROR ? reply.readExceptionCode() : err; + status_t err; + for (int i=0; i<ADD_SERVICE_RETRY_SECS; i++) { + Parcel data, reply; + data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); + data.writeString16(name); + data.writeStrongBinder(service); + data.writeInt32(allowIsolated ? 1 : 0); + err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); + if (err == NO_ERROR) + return reply.readExceptionCode(); + if (i != ADD_SERVICE_RETRY_SECS) { + ALOGI("addService() %s failed (err %d - no service manager yet?). Retrying...\n", + String8(name).string(), err); + sleep(1); + } else { + ALOGE("addService() %s failed (err %d). Giving up.\n", + String8(name).string(), err); + } + } + return err; } virtual Vector<String16> listServices() diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index c3c6235..da02c68 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -185,7 +185,12 @@ public: if (result != NO_ERROR) { return result; } - memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output)); + const void *out_data =reply.readInplace(sizeof(*output)); + if(out_data != NULL) { + memcpy(output, out_data, sizeof(*output)); + } else { + return BAD_VALUE; + } result = reply.readInt32(); return result; } @@ -227,7 +232,12 @@ public: if (result != NO_ERROR) { return result; } - memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output)); + const void *out_data =reply.readInplace(sizeof(*output)); + if(out_data != NULL) { + memcpy(output, out_data, sizeof(*output)); + } else { + return BAD_VALUE; + } result = reply.readInt32(); return result; } diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index 235cbbd..f0c52a0 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -376,10 +376,10 @@ size_t Sensor::getFlattenedSize() const sizeof(bool); size_t variableSize = - sizeof(uint32_t) + FlattenableUtils::align<4>(mName.length()) + - sizeof(uint32_t) + FlattenableUtils::align<4>(mVendor.length()) + - sizeof(uint32_t) + FlattenableUtils::align<4>(mStringType.length()) + - sizeof(uint32_t) + FlattenableUtils::align<4>(mRequiredPermission.length()); + sizeof(size_t) + FlattenableUtils::align<sizeof(size_t)>(mName.length()) + + sizeof(size_t) + FlattenableUtils::align<sizeof(size_t)>(mVendor.length()) + + sizeof(size_t) + FlattenableUtils::align<sizeof(size_t)>(mStringType.length()) + + sizeof(size_t) + FlattenableUtils::align<sizeof(size_t)>(mRequiredPermission.length()); return fixedSize + variableSize; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 4b76f98..4f8a9a1 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -141,9 +141,12 @@ int Surface::hook_queueBuffer(ANativeWindow* window, int Surface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer) { Surface* c = getSelf(window); - ANativeWindowBuffer* buf; + ANativeWindowBuffer* buf = NULL; int fenceFd = -1; int result = c->dequeueBuffer(&buf, &fenceFd); + + if (result != NO_ERROR) return result; + sp<Fence> fence(new Fence(fenceFd)); int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED"); if (waitResult != OK) { @@ -254,10 +257,13 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result); mGraphicBufferProducer->cancelBuffer(buf, fence); return result; + } else if (gbuf == 0) { + ALOGE("dequeueBuffer: Buffer is null return"); + return INVALID_OPERATION; } } - if (fence->isValid()) { + if ((fence != NULL) && fence->isValid()) { *fenceFd = fence->dup(); if (*fenceFd == -1) { ALOGE("dequeueBuffer: error duping fence: %d", errno); diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 593d0c2..58aeabb 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -1468,6 +1468,9 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy, if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (ggl_unlikely(num_config==0)) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + GLint numConfigs = NELEM(gConfigs); if (!configs) { *num_config = numConfigs; diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp index 1fcc048..6bd2f6d 100644 --- a/opengl/libs/EGL/Loader.cpp +++ b/opengl/libs/EGL/Loader.cpp @@ -86,6 +86,13 @@ checkGlesEmulationStatus(void) char prop[PROPERTY_VALUE_MAX]; int result = -1; + /* Check if hardware acceleration disabled explicitly */ + property_get("debug.egl.hw", prop, "1"); + if (!atoi(prop)) { + ALOGD("3D hardware acceleration is disabled"); + return 0; + } + /* First, check for qemu=1 */ property_get("ro.kernel.qemu",prop,"0"); if (atoi(prop) != 1) diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index cdec565..a86c54c 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -23,6 +23,7 @@ #include <hardware/gralloc.h> #include <system/window.h> +#include <sys/mman.h> #include <EGL/egl.h> #include <EGL/eglext.h> @@ -414,6 +415,35 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, } // ---------------------------------------------------------------------------- +// Utility procedure to test a NativeWindowType for validity before referencing +// through the pointer. It's not feasible to test for deliberate forgeries, +// but this heuristic is good enough to test for basic accidental cases, using +// the special "magic" value placed in a native-window structure. +// ---------------------------------------------------------------------------- +EGLBoolean isValidNativeWindow(NativeWindowType window) +{ + ANativeWindow *nwindow = static_cast<ANativeWindow*>(window); + // the msync system call returns with ENOMEM error for unmapped memory + // pages. This is used here as a way to test whether we can read through a + // pointer without getting a segfault. + uintptr_t pagesize = (uintptr_t) sysconf(_SC_PAGESIZE); + uintptr_t addr = ((uintptr_t)(&nwindow->common.magic)) & (~(pagesize - 1)); + int rc = msync((void *)addr, pagesize, MS_ASYNC); + if (0 == rc) { + if (nwindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC) + return EGL_TRUE; + else + return EGL_FALSE; + } + if (ENOMEM == errno) + return EGL_FALSE; + ALOGE("error unexpected msync error: %s (%d)", + strerror(-errno), errno); + return EGL_FALSE; +} + + +// ---------------------------------------------------------------------------- // surfaces // ---------------------------------------------------------------------------- @@ -448,6 +478,10 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, if (dp) { EGLDisplay iDpy = dp->disp.dpy; + if (!isValidNativeWindow(window)) { + ALOGE("EGLNativeWindow %p invalid", window); + return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); if (result != OK) { ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " @@ -462,15 +496,19 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, // modify the EGLconfig's format before setting the native window's // format. - // by default, just pick RGBA_8888 - EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; + EGLint format; android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; EGLint a = 0; cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); if (a > 0) { // alpha-channel requested, there's really only one suitable format - format = HAL_PIXEL_FORMAT_RGBA_8888; + if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID, + &format)) { + ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x", + eglGetError()); + format = HAL_PIXEL_FORMAT_RGBA_8888; + } } else { EGLint r, g, b; r = g = b = 0; diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp index 918faa8..dee64db 100644 --- a/opengl/libs/EGL/egl_object.cpp +++ b/opengl/libs/EGL/egl_object.cpp @@ -111,11 +111,6 @@ void egl_context_t::onMakeCurrent(EGLSurface draw, EGLSurface read) { // call the implementation's glGetString(GL_EXTENSIONS) const char* exts = (const char *)gEGLImpl.hooks[version]->gl.glGetString(GL_EXTENSIONS); gl_extensions.setTo(exts); - if (gl_extensions.find("GL_EXT_debug_marker") < 0) { - String8 temp("GL_EXT_debug_marker "); - temp.append(gl_extensions); - gl_extensions.setTo(temp); - } // tokenize the supported extensions for the glGetStringi() wrapper std::stringstream ss; diff --git a/services/inputflinger/Android.mk b/services/inputflinger/Android.mk index ed867d8..773064f 100644 --- a/services/inputflinger/Android.mk +++ b/services/inputflinger/Android.mk @@ -39,6 +39,9 @@ LOCAL_SHARED_LIBRARIES := \ #LOCAL_CFLAGS += -fvisibility=hidden LOCAL_CFLAGS += -Wno-unused-parameter +ifneq ($(TARGET_BUILD_VARIANT),user) + LOCAL_CFLAGS += -DCONSOLE_MANAGER -DANDROID_VT=7 +endif LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp index 5859606..61817f3 100644 --- a/services/inputflinger/EventHub.cpp +++ b/services/inputflinger/EventHub.cpp @@ -50,6 +50,8 @@ #include <input/KeyCharacterMap.h> #include <input/VirtualKeyMap.h> +#include <linux/vt.h> + /* this macro is used to tell if "bit" is set in "array" * it selects a byte from the array, and does a boolean AND * operation with a byte that only has the relevant bit set. @@ -790,6 +792,14 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz } } +#ifdef CONSOLE_MANAGER + struct vt_stat vs; + int fd_vt = open("/dev/tty0", O_RDWR | O_SYNC); + if (fd_vt >= 0) { + ioctl(fd_vt, VT_GETSTATE, &vs); + close(fd_vt); + } +#endif // Grab the next input event. bool deviceChanged = false; while (mPendingEventIndex < mPendingEventCount) { @@ -844,6 +854,12 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz } else if ((readSize % sizeof(struct input_event)) != 0) { ALOGE("could not get event (wrong size: %d)", readSize); } else { +#ifdef CONSOLE_MANAGER + if (vs.v_active != ANDROID_VT) { + ALOGV("Skip a non Android VT event"); + continue; + } +#endif int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; size_t count = size_t(readSize) / sizeof(struct input_event); @@ -1066,8 +1082,17 @@ static const int32_t GAMEPAD_KEYCODES[] = { }; status_t EventHub::openDeviceLocked(const char *devicePath) { + return openDeviceLocked(devicePath, false); +} + +status_t EventHub::openDeviceLocked(const char *devicePath, bool ignoreAlreadyOpened) { char buffer[80]; + if (ignoreAlreadyOpened && (getDeviceByPathLocked(devicePath) != 0)) { + ALOGV("Ignoring device '%s' that has already been opened.", devicePath); + return 0; + } + ALOGV("Opening device: %s", devicePath); int fd = open(devicePath, O_RDWR | O_CLOEXEC); @@ -1202,7 +1227,7 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT; } // Is this an old style single-touch driver? - } else if (test_bit(BTN_TOUCH, device->keyBitmask) + } else if ((test_bit(BTN_TOUCH, device->keyBitmask) || test_bit(BTN_LEFT, device->keyBitmask)) && test_bit(ABS_X, device->absBitmask) && test_bit(ABS_Y, device->absBitmask)) { device->classes |= INPUT_DEVICE_CLASS_TOUCH; @@ -1275,7 +1300,11 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { // 'Q' key support = cheap test of whether this is an alpha-capable kbd if (hasKeycodeLocked(device, AKEYCODE_Q)) { - device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY; + char value[PROPERTY_VALUE_MAX]; + property_get("ro.ignore_atkbd", value, "0"); + if ((device->identifier.name != "AT Translated Set 2 keyboard") || (!atoi(value))) { + device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY; + } } // See if this device has a DPAD. @@ -1617,7 +1646,7 @@ status_t EventHub::readNotifyLocked() { if(event->len) { strcpy(filename, event->name); if(event->mask & IN_CREATE) { - openDeviceLocked(devname); + openDeviceLocked(devname, true); } else { ALOGI("Removing device '%s' due to inotify event\n", devname); closeDeviceByPathLocked(devname); diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h index 0f94c77..ed61319 100644 --- a/services/inputflinger/EventHub.h +++ b/services/inputflinger/EventHub.h @@ -379,6 +379,7 @@ private: }; status_t openDeviceLocked(const char *devicePath); + status_t openDeviceLocked(const char *devicePath, bool ignoreAlreadyOpened); void createVirtualKeyboardLocked(); void addDeviceLocked(Device* device); void assignDescriptorLocked(InputDeviceIdentifier& identifier); diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index b2cbfe8..fb270ed 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -1345,7 +1345,7 @@ TouchButtonAccumulator::TouchButtonAccumulator() : } void TouchButtonAccumulator::configure(InputDevice* device) { - mHaveBtnTouch = device->hasKey(BTN_TOUCH); + mHaveBtnTouch = device->hasKey(BTN_TOUCH) || device->hasKey(BTN_LEFT); mHaveStylus = device->hasKey(BTN_TOOL_PEN) || device->hasKey(BTN_TOOL_RUBBER) || device->hasKey(BTN_TOOL_BRUSH) @@ -1354,7 +1354,7 @@ void TouchButtonAccumulator::configure(InputDevice* device) { } void TouchButtonAccumulator::reset(InputDevice* device) { - mBtnTouch = device->isKeyPressed(BTN_TOUCH); + mBtnTouch = device->isKeyPressed(BTN_TOUCH) || device->isKeyPressed(BTN_LEFT); mBtnStylus = device->isKeyPressed(BTN_STYLUS); // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch mBtnStylus2 = @@ -1393,6 +1393,7 @@ void TouchButtonAccumulator::process(const RawEvent* rawEvent) { if (rawEvent->type == EV_KEY) { switch (rawEvent->code) { case BTN_TOUCH: + case BTN_LEFT: mBtnTouch = rawEvent->value; break; case BTN_STYLUS: @@ -2940,6 +2941,19 @@ void TouchInputMapper::configure(nsecs_t when, configureSurface(when, &resetNeeded); } + if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) { + // Get 5-point calibration parameters + int *p = mCalibration.fiveCal; + p[6] = 0; + if (FILE *file = fopen("/data/misc/tscal/pointercal", "r")) { + if (fscanf(file, "%d %d %d %d %d %d %d", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5], &p[6]) == 7) { + p[0] *= mXScale, p[1] *= mYScale, p[3] *= mXScale, p[4] *= mYScale; + ALOGD("pointercal loaded ok"); + } + fclose(file); + } + } + if (changes && resetNeeded) { // Send reset, unless this is the first time the device has been configured, // in which case the reader will call reset itself after all mappers are ready. @@ -2962,15 +2976,15 @@ void TouchInputMapper::configureParameters() { // multitouch. The spot-based presentation relies on being able to accurately // locate two or more fingers on the touch pad. mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT) - ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS; + ? Parameters::GESTURE_MODE_SINGLE_TOUCH : Parameters::GESTURE_MODE_MULTI_TOUCH; String8 gestureModeString; if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"), gestureModeString)) { - if (gestureModeString == "pointer") { - mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER; - } else if (gestureModeString == "spots") { - mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS; + if (gestureModeString == "single-touch") { + mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH; + } else if (gestureModeString == "multi-touch") { + mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH; } else if (gestureModeString != "default") { ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string()); } @@ -3038,11 +3052,11 @@ void TouchInputMapper::dumpParameters(String8& dump) { dump.append(INDENT3 "Parameters:\n"); switch (mParameters.gestureMode) { - case Parameters::GESTURE_MODE_POINTER: - dump.append(INDENT4 "GestureMode: pointer\n"); + case Parameters::GESTURE_MODE_SINGLE_TOUCH: + dump.append(INDENT4 "GestureMode: single-touch\n"); break; - case Parameters::GESTURE_MODE_SPOTS: - dump.append(INDENT4 "GestureMode: spots\n"); + case Parameters::GESTURE_MODE_MULTI_TOUCH: + dump.append(INDENT4 "GestureMode: multi-touch\n"); break; default: assert(false); @@ -3637,6 +3651,8 @@ void TouchInputMapper::parseCalibration() { out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL; } else if (pressureCalibrationString == "amplitude") { out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE; + } else if (pressureCalibrationString == "disable") { + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DISABLE; } else if (pressureCalibrationString != "default") { ALOGW("Invalid value for touch.pressure.calibration: '%s'", pressureCalibrationString.string()); @@ -3707,6 +3723,9 @@ void TouchInputMapper::resolveCalibration() { if (mRawPointerAxes.pressure.valid) { if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) { mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL; + } else if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DISABLE) { + mRawPointerAxes.pressure.valid = false; + mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE; } } else { mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE; @@ -4701,11 +4720,24 @@ void TouchInputMapper::cookPointerData() { // Adjust X, Y, and coverage coords for surface orientation. float x, y; float left, top, right, bottom; + float x_temp = float(xTransformed - mRawPointerAxes.x.minValue); + float y_temp = float(yTransformed - mRawPointerAxes.y.minValue); + float x_cal, y_cal; + int *p = mCalibration.fiveCal; + if (p[6]) { + // Apply 5-point calibration algorithm + x_cal = (x_temp * p[0] + y_temp * p[1] + p[2] ) / p[6]; + y_cal = (x_temp * p[3] + y_temp * p[4] + p[5] ) / p[6]; + ALOGV("5cal: x_temp=%f y_temp=%f x_cal=%f y_cal=%f", x_temp, y_temp, x_cal, y_cal); + } else { + x_cal = x_temp * mXScale; + y_cal = y_temp * mYScale; + } switch (mSurfaceOrientation) { case DISPLAY_ORIENTATION_90: - x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; - y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate; + x = y_cal + mYTranslate; + y = mSurfaceWidth - x_cal + mXTranslate; left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate; bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate; @@ -4716,8 +4748,8 @@ void TouchInputMapper::cookPointerData() { } break; case DISPLAY_ORIENTATION_180: - x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate; - y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate; + x = mSurfaceWidth - x_cal + mXTranslate; + y = mSurfaceHeight - y_cal + mYTranslate; left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate; right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate; bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; @@ -4728,8 +4760,8 @@ void TouchInputMapper::cookPointerData() { } break; case DISPLAY_ORIENTATION_270: - x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate; - y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; + x = mSurfaceHeight - y_cal + mYTranslate; + y = x_cal + mXTranslate; left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; @@ -4740,8 +4772,8 @@ void TouchInputMapper::cookPointerData() { } break; default: - x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; + x = x_cal + mXTranslate; + y = y_cal + mYTranslate; left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; @@ -4838,14 +4870,17 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag } // Update the pointer presentation and spots. - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT); + if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) { + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); if (finishPreviousGesture || cancelPreviousGesture) { mPointerController->clearSpots(); } - mPointerController->setSpots(mPointerGesture.currentGestureCoords, - mPointerGesture.currentGestureIdToIndex, - mPointerGesture.currentGestureIdBits); + + if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) { + mPointerController->setSpots(mPointerGesture.currentGestureCoords, + mPointerGesture.currentGestureIdToIndex, + mPointerGesture.currentGestureIdBits); + } } else { mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); } @@ -4854,9 +4889,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag switch (mPointerGesture.currentGestureMode) { case PointerGesture::NEUTRAL: case PointerGesture::QUIET: - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS - && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE - || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) { + if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH + && mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) { // Remind the user of where the pointer is after finishing a gesture with spots. mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL); } @@ -4866,15 +4900,15 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag case PointerGesture::BUTTON_CLICK_OR_DRAG: case PointerGesture::HOVER: case PointerGesture::PRESS: + case PointerGesture::SWIPE: // Unfade the pointer when the current gesture manipulates the // area directly under the pointer. mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); break; - case PointerGesture::SWIPE: case PointerGesture::FREEFORM: // Fade the pointer when the current gesture manipulates a different // area and there are spots to guide the user experience. - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { + if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) { mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); } else { mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index 30c84b1..32bf188 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -1305,8 +1305,8 @@ protected: bool hasButtonUnderPad; enum GestureMode { - GESTURE_MODE_POINTER, - GESTURE_MODE_SPOTS, + GESTURE_MODE_SINGLE_TOUCH, + GESTURE_MODE_MULTI_TOUCH, }; GestureMode gestureMode; @@ -1340,6 +1340,7 @@ protected: PRESSURE_CALIBRATION_NONE, PRESSURE_CALIBRATION_PHYSICAL, PRESSURE_CALIBRATION_AMPLITUDE, + PRESSURE_CALIBRATION_DISABLE, }; PressureCalibration pressureCalibration; @@ -1386,6 +1387,9 @@ protected: *outSize = 0; } } + + // 5-point calibration parameters + int fiveCal[7]; } mCalibration; // Affine location transformation/calibration diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 1eb2361..d77540d 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -40,6 +40,9 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES +ifneq ($(TARGET_BUILD_VARIANT),user) + LOCAL_CFLAGS += -DCONSOLE_MANAGER -DANDROID_VT=7 +endif ifeq ($(TARGET_BOARD_PLATFORM),omap4) LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY endif @@ -88,6 +91,9 @@ ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),) else LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=0 endif +ifneq ($(BOARD_GPU_DRIVERS),) + LOCAL_C_INCLUDES := external/drm_gralloc +endif LOCAL_CFLAGS += -fvisibility=hidden -Werror=format LOCAL_CFLAGS += -std=c++11 diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 13d44f3..1e42c17 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -19,6 +19,11 @@ #include <string.h> #include <math.h> +#include <fcntl.h> +#include <termios.h> +#include <linux/kd.h> +#include <linux/vt.h> + #include <cutils/properties.h> #include <utils/RefBase.h> @@ -39,11 +44,249 @@ #include "DisplayDevice.h" #include "SurfaceFlinger.h" #include "Layer.h" +#include "gralloc_drm.h" // ---------------------------------------------------------------------------- using namespace android; // ---------------------------------------------------------------------------- +#ifdef CONSOLE_MANAGER +class ConsoleManagerThread : public Thread { +public: + ConsoleManagerThread(const sp<SurfaceFlinger>&, const wp<IBinder>&); + virtual ~ConsoleManagerThread(); + + status_t releaseScreen() const; + +private: + sp<SurfaceFlinger> mFlinger; + wp<IBinder> mDisplayToken; + int consoleFd; + long prev_vt_num; + vt_mode vm; + virtual void onFirstRef(); + virtual status_t readyToRun(); + virtual void requestExit(); + virtual bool threadLoop(); + static void sigHandler(int sig); + static pid_t sSignalCatcherPid; +}; + +ConsoleManagerThread::ConsoleManagerThread(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& token) + : Thread(false), mFlinger(flinger), mDisplayToken(token), consoleFd(-1) +{ + sSignalCatcherPid = 0; + + // create a new console + char const * const ttydev = "/dev/tty0"; + int fd = open(ttydev, O_RDWR | O_SYNC); + if (fd < 0) { + ALOGE("Can't open %s, errno=%d (%s)", ttydev, errno, strerror(errno)); + consoleFd = -errno; + return; + } + ALOGD("Open /dev/tty0 OK"); + + // to make sure that we are in text mode + int res = ioctl(fd, KDSETMODE, (void*) KD_TEXT); + if (res < 0) { + ALOGE("ioctl(%d, KDSETMODE, ...) failed, res %d (%s)", + fd, res, strerror(errno)); + } + + // get the current console + struct vt_stat vs; + res = ioctl(fd, VT_GETSTATE, &vs); + if (res < 0) { + ALOGE("ioctl(%d, VT_GETSTATE, ...) failed, res %d (%s)", + fd, res, strerror(errno)); + consoleFd = -errno; + return; + } + + // switch to console 7 (which is what X normaly uses) + do { + res = ioctl(fd, VT_ACTIVATE, ANDROID_VT); + } while(res < 0 && errno == EINTR); + if (res < 0) { + ALOGE("ioctl(%d, VT_ACTIVATE, ...) failed, %d (%s) for vt %d", + fd, errno, strerror(errno), ANDROID_VT); + consoleFd = -errno; + return; + } + + do { + res = ioctl(fd, VT_WAITACTIVE, ANDROID_VT); + } while (res < 0 && errno == EINTR); + if (res < 0) { + ALOGE("ioctl(%d, VT_WAITACTIVE, ...) failed, %d %d %s for vt %d", + fd, res, errno, strerror(errno), ANDROID_VT); + consoleFd = -errno; + return; + } + + // open the new console + close(fd); + fd = open(ttydev, O_RDWR | O_SYNC); + if (fd < 0) { + ALOGE("Can't open new console %s", ttydev); + consoleFd = -errno; + return; + } + + /* disable console line buffer, echo, ... */ + struct termios ttyarg; + ioctl(fd, TCGETS , &ttyarg); + ttyarg.c_iflag = 0; + ttyarg.c_lflag = 0; + ioctl(fd, TCSETS , &ttyarg); + + // set up signals so we're notified when the console changes + // we can't use SIGUSR1 because it's used by the java-vm + vm.mode = VT_PROCESS; + vm.waitv = 0; + vm.relsig = SIGUSR2; + vm.acqsig = SIGUNUSED; + vm.frsig = 0; + + struct sigaction act; + sigemptyset(&act.sa_mask); + act.sa_handler = sigHandler; + act.sa_flags = 0; + sigaction(vm.relsig, &act, NULL); + + sigemptyset(&act.sa_mask); + act.sa_handler = sigHandler; + act.sa_flags = 0; + sigaction(vm.acqsig, &act, NULL); + + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, vm.relsig); + sigaddset(&mask, vm.acqsig); + sigprocmask(SIG_BLOCK, &mask, NULL); + + // switch to graphic mode + res = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS); + ALOGW_IF(res < 0, + "ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, res %d", fd, res); + + prev_vt_num = vs.v_active; + consoleFd = fd; +} + +ConsoleManagerThread::~ConsoleManagerThread() +{ + if (consoleFd >= 0) { + int fd = consoleFd; + int res; + ioctl(fd, KDSETMODE, (void*)KD_TEXT); + do { + res = ioctl(fd, VT_ACTIVATE, prev_vt_num); + } while(res < 0 && errno == EINTR); + do { + res = ioctl(fd, VT_WAITACTIVE, prev_vt_num); + } while(res < 0 && errno == EINTR); + close(fd); + char const * const ttydev = "/dev/tty0"; + fd = open(ttydev, O_RDWR | O_SYNC); + ioctl(fd, VT_DISALLOCATE, 0); + close(fd); + } +} + +status_t ConsoleManagerThread::releaseScreen() const +{ + int err = ioctl(consoleFd, VT_RELDISP, (void*)1); + ALOGE_IF(err < 0, "ioctl(%d, VT_RELDISP, 1) failed %d (%s)", + consoleFd, errno, strerror(errno)); + return (err < 0) ? (-errno) : status_t(NO_ERROR); +} + +void ConsoleManagerThread::onFirstRef() +{ + run("ConsoleManagerThread", PRIORITY_URGENT_DISPLAY); +} + +status_t ConsoleManagerThread::readyToRun() +{ + if (consoleFd >= 0) { + sSignalCatcherPid = gettid(); + + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, vm.relsig); + sigaddset(&mask, vm.acqsig); + sigprocmask(SIG_BLOCK, &mask, NULL); + + int res = ioctl(consoleFd, VT_SETMODE, &vm); + if (res < 0) { + ALOGE("ioctl(%d, VT_SETMODE, ...) failed, %d (%s)", + consoleFd, errno, strerror(errno)); + } + return NO_ERROR; + } + return consoleFd; +} + +void ConsoleManagerThread::requestExit() +{ + Thread::requestExit(); + if (sSignalCatcherPid != 0) { + // wake the thread up + kill(sSignalCatcherPid, SIGINT); + // wait for it... + } +} + +bool ConsoleManagerThread::threadLoop() +{ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, vm.relsig); + sigaddset(&mask, vm.acqsig); + + int sig = 0; + sigwait(&mask, &sig); + + hw_module_t const* mod; + gralloc_module_t const* gr = NULL; + status_t err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); + if (!err) { + gr = reinterpret_cast<gralloc_module_t const*>(mod); + if (!gr->perform) + gr = NULL; + } + + if (sig == vm.relsig) { + if (gr) + gr->perform(gr, GRALLOC_MODULE_PERFORM_LEAVE_VT); + mFlinger->screenReleased(mDisplayToken.promote()); + } else if (sig == vm.acqsig) { + mFlinger->screenAcquired(mDisplayToken.promote()); + if (gr) + gr->perform(gr, GRALLOC_MODULE_PERFORM_ENTER_VT); + } + + return true; +} + +void ConsoleManagerThread::sigHandler(int sig) +{ + // resend the signal to our signal catcher thread + ALOGW("received signal %d in thread %d, resending to %d", + sig, gettid(), sSignalCatcherPid); + + // we absolutely need the delays below because without them + // our main thread never gets a chance to handle the signal. + usleep(10000); + kill(sSignalCatcherPid, sig); + usleep(10000); +} + +pid_t ConsoleManagerThread::sSignalCatcherPid; +#endif + #ifdef EGL_ANDROID_swap_rectangle static constexpr bool kEGLAndroidSwapRectangle = true; #else @@ -83,6 +326,9 @@ DisplayDevice::DisplayDevice( mPageFlipCount(), mIsSecure(isSecure), mSecureLayerVisible(false), +#ifdef CONSOLE_MANAGER + mConsoleManagerThread(0), +#endif mLayerStack(NO_LAYER_STACK), mOrientation(), mPowerMode(HWC_POWER_MODE_OFF), @@ -131,6 +377,9 @@ DisplayDevice::DisplayDevice( switch (mType) { case DISPLAY_PRIMARY: mDisplayName = "Built-in Screen"; +#ifdef CONSOLE_MANAGER + mConsoleManagerThread = new ConsoleManagerThread(mFlinger, mDisplayToken); +#endif break; case DISPLAY_EXTERNAL: mDisplayName = "HDMI Screen"; @@ -149,6 +398,12 @@ DisplayDevice::~DisplayDevice() { eglDestroySurface(mDisplay, mSurface); mSurface = EGL_NO_SURFACE; } +#ifdef CONSOLE_MANAGER + if (mConsoleManagerThread != 0) { + mConsoleManagerThread->requestExitAndWait(); + ALOGD("ConsoleManagerThread: destroy primary DisplayDevice"); + } +#endif } void DisplayDevice::disconnect(HWComposer& hwc) { @@ -335,6 +590,11 @@ Region DisplayDevice::getDirtyRegion(bool repaintEverything) const { // ---------------------------------------------------------------------------- void DisplayDevice::setPowerMode(int mode) { mPowerMode = mode; +#ifdef CONSOLE_MANAGER + if (mode != HWC_POWER_MODE_NORMAL && mConsoleManagerThread != 0) { + mConsoleManagerThread->releaseScreen(); + } +#endif } int DisplayDevice::getPowerMode() const { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 8695a44..852141c 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -34,6 +34,7 @@ #include "Transform.h" struct ANativeWindow; +class ConsoleManagerThread; namespace android { @@ -205,6 +206,9 @@ private: // Whether we have a visible secure layer on this display bool mSecureLayerVisible; +#ifdef CONSOLE_MANAGER + sp<ConsoleManagerThread> mConsoleManagerThread; +#endif /* * Transaction state diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 6ef3295..70af656 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -67,6 +67,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp)); mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp)); mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); + mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1); } status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 0859149..ff30bb3 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -422,7 +422,7 @@ status_t HWComposer::queryDisplayProperties(int disp) { } // FIXME: what should we set the format to? - mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888; + mDisplayData[disp].format = HAL_PIXEL_FORMAT_BGRA_8888; mDisplayData[disp].connected = true; return NO_ERROR; } @@ -846,7 +846,7 @@ int HWComposer::getVisualID() const { // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED // is supported by the implementation. we can only be in this case // if we have HWC 1.1 - return HAL_PIXEL_FORMAT_RGBA_8888; + return HAL_PIXEL_FORMAT_BGRA_8888; //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; } else { return mFbDev->format; diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index f760200..fa1423e 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -281,11 +281,11 @@ Vector< sp<EventThread::Connection> > EventThread::waitForEvent( } // Here we figure out if we need to enable or disable vsyncs - if (timestamp && !waitForVSync) { - // we received a VSYNC but we have no clients - // don't report it, and disable VSYNC events + if (!waitForVSync) { + // we have no clients waiting on next VSYNC + // just disable VSYNC events. disableVSyncLocked(); - } else if (!timestamp && waitForVSync) { + } else if (!timestamp) { // we have at least one client, so we want vsync enabled // (TODO: this function is called right after we finish // notifying clients of a vsync, so this call will be made diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fdc3650..31889f7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -585,8 +585,31 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, public: static int getEmuDensity() { return getDensityFromProperty("qemu.sf.lcd_density"); } - static int getBuildDensity() { - return getDensityFromProperty("ro.sf.lcd_density"); } + static int getBuildDensity(const DisplayInfo& info) { + static int density = getDensityFromProperty("ro.sf.lcd_density"); +#if defined(__i386__) || defined(__x86_64__) + if (density == 0) { + uint32_t area = info.w * info.h; + if (area <= 800 * 480) { + density = 120; + } else if (area <= 1024 * 600) { + density = 130; + } else if (area < 1024 * 768) { + density = 140; + } else if (area < 1920 * 1080) { + density = 160; + } else if (area < 2160 * 1440) { + density = 240; + } else if (area < 2736 * 1824) { + density = 280; + } else { + density = 320; + } + ALOGI("auto set density to %d", density); + } +#endif + return density; + } }; configs->clear(); @@ -599,10 +622,12 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, float xdpi = hwConfig.xdpi; float ydpi = hwConfig.ydpi; + info.w = hwConfig.width; + info.h = hwConfig.height; if (type == DisplayDevice::DISPLAY_PRIMARY) { // The density of the device is provided by a build property - float density = Density::getBuildDensity() / 160.0f; + float density = Density::getBuildDensity(info) / 160.0f; if (density == 0) { // the build doesn't provide a density -- this is wrong! // use xdpi instead @@ -626,8 +651,6 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, info.orientation = 0; } - info.w = hwConfig.width; - info.h = hwConfig.height; info.xdpi = xdpi; info.ydpi = ydpi; info.fps = float(1e9 / hwConfig.refresh); @@ -757,6 +780,20 @@ void SurfaceFlinger::waitForEvent() { mEventQueue.waitMessage(); } +#ifdef CONSOLE_MANAGER +void SurfaceFlinger::screenReleased(const sp<IBinder>& display) { + // this may be called by a signal handler, we can't do too much in here + setPowerMode(display, HWC_POWER_MODE_OFF); + signalLayerUpdate(); +} + +void SurfaceFlinger::screenAcquired(const sp<IBinder>& display) { + // this may be called by a signal handler, we can't do too much in here + setPowerMode(display, HWC_POWER_MODE_NORMAL); + signalLayerUpdate(); +} +#endif + void SurfaceFlinger::signalTransaction() { mEventQueue.invalidate(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b3baadd..10a74da 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -134,6 +134,9 @@ public: return *mRenderEngine; } + void screenReleased(const sp<IBinder>& display); + void screenAcquired(const sp<IBinder>& display); + private: friend class Client; friend class DisplayEventConnection; |