diff options
author | Joe Onorato <joeo@google.com> | 2010-10-13 23:34:21 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-10-13 23:34:21 -0700 |
commit | eb86aaaab34687a77454fa130b08788db1317d74 (patch) | |
tree | 6a0b8bd8dc7d3bb45511902d5d6fba012a3c8b43 /services | |
parent | 4afdf666fdb034834c48445570ed9d6f4133fc71 (diff) | |
parent | 9a12a3c8d4bb20042cf69e07d268e3a04ac71f96 (diff) | |
download | frameworks_base-eb86aaaab34687a77454fa130b08788db1317d74.zip frameworks_base-eb86aaaab34687a77454fa130b08788db1317d74.tar.gz frameworks_base-eb86aaaab34687a77454fa130b08788db1317d74.tar.bz2 |
am 9a12a3c8: am ba799098: Merge changes I76513387,I335fb671 into gingerbread
Merge commit '9a12a3c8d4bb20042cf69e07d268e3a04ac71f96'
* commit '9a12a3c8d4bb20042cf69e07d268e3a04ac71f96':
Remove dead code, and make the animation a setting.
turn off the electron beam
Diffstat (limited to 'services')
-rw-r--r-- | services/java/com/android/server/PowerManagerService.java | 380 | ||||
-rw-r--r-- | services/jni/Android.mk | 3 | ||||
-rw-r--r-- | services/jni/com_android_server_PowerManagerService.cpp | 13 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp | 18 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 234 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 4 |
7 files changed, 437 insertions, 220 deletions
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 9d9ad26..36298d1 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -141,9 +141,7 @@ class PowerManagerService extends IPowerManager.Stub // used for noChangeLights in setPowerState() private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT; - static final boolean ANIMATE_SCREEN_LIGHTS = true; - static final boolean ANIMATE_BUTTON_LIGHTS = false; - static final boolean ANIMATE_KEYBOARD_LIGHTS = false; + boolean mAnimateScreenLights = true; static final int ANIM_STEPS = 60/4; // Slower animation for autobrightness changes @@ -201,15 +199,12 @@ class PowerManagerService extends IPowerManager.Stub private UnsynchronizedWakeLock mPreventScreenOnPartialLock; private UnsynchronizedWakeLock mProximityPartialLock; private HandlerThread mHandlerThread; + private HandlerThread mScreenOffThread; + private Handler mScreenOffHandler; private Handler mHandler; private final TimeoutTask mTimeoutTask = new TimeoutTask(); - private final LightAnimator mLightAnimator = new LightAnimator(); private final BrightnessState mScreenBrightness = new BrightnessState(SCREEN_BRIGHT_BIT); - private final BrightnessState mKeyboardBrightness - = new BrightnessState(KEYBOARD_BRIGHT_BIT); - private final BrightnessState mButtonBrightness - = new BrightnessState(BUTTON_BRIGHT_BIT); private boolean mStillNeedSleepNotification; private boolean mIsPowered = false; private IActivityManager mActivityService; @@ -261,6 +256,7 @@ class PowerManagerService extends IPowerManager.Stub private native void nativeInit(); private native void nativeSetPowerState(boolean screenOn, boolean screenBright); + private native void nativeStartSurfaceFlingerAnimation(); /* static PrintStream mLog; @@ -485,6 +481,35 @@ class PowerManagerService extends IPowerManager.Stub mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD); mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION); + nativeInit(); + synchronized (mLocks) { + updateNativePowerStateLocked(); + } + + mInitComplete = false; + mScreenOffThread = new HandlerThread("PowerManagerService.mScreenOffThread") { + @Override + protected void onLooperPrepared() { + mScreenOffHandler = new Handler(); + synchronized (mScreenOffThread) { + mInitComplete = true; + mScreenOffThread.notifyAll(); + } + } + }; + mScreenOffThread.start(); + + synchronized (mScreenOffThread) { + while (!mInitComplete) { + try { + mScreenOffThread.wait(); + } catch (InterruptedException e) { + // Ignore + } + } + } + + mInitComplete = false; mHandlerThread = new HandlerThread("PowerManagerService") { @Override protected void onLooperPrepared() { @@ -531,6 +556,9 @@ class PowerManagerService extends IPowerManager.Stub Resources resources = mContext.getResources(); + mAnimateScreenLights = resources.getBoolean( + com.android.internal.R.bool.config_animateScreenLights); + mUnplugTurnsOnScreen = resources.getBoolean( com.android.internal.R.bool.config_unplugTurnsOnScreen); @@ -1093,8 +1121,6 @@ class PowerManagerService extends IPowerManager.Stub pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness); pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled); mScreenBrightness.dump(pw, " mScreenBrightness: "); - mKeyboardBrightness.dump(pw, " mKeyboardBrightness: "); - mButtonBrightness.dump(pw, " mButtonBrightness: "); int N = mLocks.size(); pw.println(); @@ -1724,7 +1750,8 @@ class PowerManagerService extends IPowerManager.Stub // I don't think we need to check the current state here because all of these // Power.setScreenState and sendNotificationLocked can both handle being // called multiple times in the same state. -joeo - EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, mTouchCycles); + EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, + mTouchCycles); mLastTouchDown = 0; int err = setScreenStateLocked(false); if (err == 0) { @@ -1754,145 +1781,95 @@ class PowerManagerService extends IPowerManager.Stub int onMask = 0; int preferredBrightness = getPreferredBrightness(); - boolean startAnimation = false; if ((difference & KEYBOARD_BRIGHT_BIT) != 0) { - if (ANIMATE_KEYBOARD_LIGHTS) { - if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { - mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, - ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS, - Power.BRIGHTNESS_ON); - } else { - mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_ON, - ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS, - Power.BRIGHTNESS_OFF); - } - startAnimation = true; + if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { + offMask |= KEYBOARD_BRIGHT_BIT; } else { - if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { - offMask |= KEYBOARD_BRIGHT_BIT; - } else { - onMask |= KEYBOARD_BRIGHT_BIT; - } + onMask |= KEYBOARD_BRIGHT_BIT; } } if ((difference & BUTTON_BRIGHT_BIT) != 0) { - if (ANIMATE_BUTTON_LIGHTS) { - if ((newState & BUTTON_BRIGHT_BIT) == 0) { - mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, - ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, - Power.BRIGHTNESS_ON); - } else { - mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_ON, - ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, - Power.BRIGHTNESS_OFF); - } - startAnimation = true; + if ((newState & BUTTON_BRIGHT_BIT) == 0) { + offMask |= BUTTON_BRIGHT_BIT; } else { - if ((newState & BUTTON_BRIGHT_BIT) == 0) { - offMask |= BUTTON_BRIGHT_BIT; - } else { - onMask |= BUTTON_BRIGHT_BIT; - } + onMask |= BUTTON_BRIGHT_BIT; } } if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { - if (ANIMATE_SCREEN_LIGHTS) { - int nominalCurrentValue = -1; - // If there was an actual difference in the light state, then - // figure out the "ideal" current value based on the previous - // state. Otherwise, this is a change due to the brightness - // override, so we want to animate from whatever the current - // value is. - if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { - switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) { - case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT: - nominalCurrentValue = preferredBrightness; - break; - case SCREEN_ON_BIT: - nominalCurrentValue = Power.BRIGHTNESS_DIM; - break; - case 0: - nominalCurrentValue = Power.BRIGHTNESS_OFF; - break; - case SCREEN_BRIGHT_BIT: - default: - // not possible - nominalCurrentValue = (int)mScreenBrightness.curValue; - break; - } + int nominalCurrentValue = -1; + // If there was an actual difference in the light state, then + // figure out the "ideal" current value based on the previous + // state. Otherwise, this is a change due to the brightness + // override, so we want to animate from whatever the current + // value is. + if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { + switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) { + case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT: + nominalCurrentValue = preferredBrightness; + break; + case SCREEN_ON_BIT: + nominalCurrentValue = Power.BRIGHTNESS_DIM; + break; + case 0: + nominalCurrentValue = Power.BRIGHTNESS_OFF; + break; + case SCREEN_BRIGHT_BIT: + default: + // not possible + nominalCurrentValue = (int)mScreenBrightness.curValue; + break; } - int brightness = preferredBrightness; - int steps = ANIM_STEPS; - if ((newState & SCREEN_BRIGHT_BIT) == 0) { - // dim or turn off backlight, depending on if the screen is on - // the scale is because the brightness ramp isn't linear and this biases - // it so the later parts take longer. - final float scale = 1.5f; - float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness); - if (ratio > 1.0f) ratio = 1.0f; - if ((newState & SCREEN_ON_BIT) == 0) { - if ((oldState & SCREEN_BRIGHT_BIT) != 0) { - // was bright - steps = ANIM_STEPS; - } else { - // was dim - steps = (int)(ANIM_STEPS*ratio*scale); - } - brightness = Power.BRIGHTNESS_OFF; + } + int brightness = preferredBrightness; + int steps = ANIM_STEPS; + if ((newState & SCREEN_BRIGHT_BIT) == 0) { + // dim or turn off backlight, depending on if the screen is on + // the scale is because the brightness ramp isn't linear and this biases + // it so the later parts take longer. + final float scale = 1.5f; + float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness); + if (ratio > 1.0f) ratio = 1.0f; + if ((newState & SCREEN_ON_BIT) == 0) { + if ((oldState & SCREEN_BRIGHT_BIT) != 0) { + // was bright + steps = ANIM_STEPS; } else { - if ((oldState & SCREEN_ON_BIT) != 0) { - // was bright - steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale); - } else { - // was dim - steps = (int)(ANIM_STEPS*ratio); - } - if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) { - // If the "stay on while plugged in" option is - // turned on, then the screen will often not - // automatically turn off while plugged in. To - // still have a sense of when it is inactive, we - // will then count going dim as turning off. - mScreenOffTime = SystemClock.elapsedRealtime(); - } - brightness = Power.BRIGHTNESS_DIM; + // was dim + steps = (int)(ANIM_STEPS*ratio*scale); } - } - long identity = Binder.clearCallingIdentity(); - try { - mBatteryStats.noteScreenBrightness(brightness); - } catch (RemoteException e) { - // Nothing interesting to do. - } finally { - Binder.restoreCallingIdentity(identity); - } - if (mScreenBrightness.setTargetLocked(brightness, - steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) { - startAnimation = true; - } - } else { - if ((newState & SCREEN_BRIGHT_BIT) == 0) { - // dim or turn off backlight, depending on if the screen is on - if ((newState & SCREEN_ON_BIT) == 0) { - offMask |= SCREEN_BRIGHT_BIT; + brightness = Power.BRIGHTNESS_OFF; + } else { + if ((oldState & SCREEN_ON_BIT) != 0) { + // was bright + steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale); } else { - dimMask |= SCREEN_BRIGHT_BIT; + // was dim + steps = (int)(ANIM_STEPS*ratio); } - } else { - onMask |= SCREEN_BRIGHT_BIT; + if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) { + // If the "stay on while plugged in" option is + // turned on, then the screen will often not + // automatically turn off while plugged in. To + // still have a sense of when it is inactive, we + // will then count going dim as turning off. + mScreenOffTime = SystemClock.elapsedRealtime(); + } + brightness = Power.BRIGHTNESS_DIM; } } - } - - if (startAnimation) { - if (mSpew) { - Slog.i(TAG, "Scheduling light animator!"); + long identity = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteScreenBrightness(brightness); + } catch (RemoteException e) { + // Nothing interesting to do. + } finally { + Binder.restoreCallingIdentity(identity); } - mHandler.removeCallbacks(mLightAnimator); - mHandler.post(mLightAnimator); + mScreenBrightness.setTargetLocked(brightness, steps, + INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); } if (offMask != 0) { @@ -1934,7 +1911,7 @@ class PowerManagerService extends IPowerManager.Stub } } - class BrightnessState { + class BrightnessState implements Runnable { final int mask; boolean initialized; @@ -1954,13 +1931,13 @@ class PowerManagerService extends IPowerManager.Stub + " delta=" + delta); } - boolean setTargetLocked(int target, int stepsToTarget, int initialValue, + void setTargetLocked(int target, int stepsToTarget, int initialValue, int nominalCurrentValue) { if (!initialized) { initialized = true; curValue = (float)initialValue; } else if (targetValue == target) { - return false; + return; } targetValue = target; delta = (targetValue - @@ -1974,7 +1951,12 @@ class PowerManagerService extends IPowerManager.Stub + noticeMe); } animating = true; - return true; + + if (mSpew) { + Slog.i(TAG, "scheduling light animator"); + } + mScreenOffHandler.removeCallbacks(this); + mScreenOffHandler.post(this); } boolean stepLocked() { @@ -2000,32 +1982,50 @@ class PowerManagerService extends IPowerManager.Stub more = false; } } - //Slog.i(TAG, "Animating brightess " + curIntValue + ": " + mask); + if (mSpew) Slog.d(TAG, "Animating curIntValue=" + curIntValue + ": " + mask); setLightBrightness(mask, curIntValue); + finishAnimation(more, curIntValue); + return more; + } + + void jumpToTarget() { + if (mSpew) Slog.d(TAG, "jumpToTarget targetValue=" + targetValue + ": " + mask); + setLightBrightness(mask, targetValue); + final int tv = targetValue; + curValue = tv; + targetValue = -1; + finishAnimation(false, tv); + } + + private void finishAnimation(boolean more, int curIntValue) { animating = more; if (!more) { if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) { screenOffFinishedAnimatingLocked(mScreenOffReason); } } - return more; } - } - private class LightAnimator implements Runnable { public void run() { - synchronized (mLocks) { - long now = SystemClock.uptimeMillis(); - boolean more = mScreenBrightness.stepLocked(); - if (mKeyboardBrightness.stepLocked()) { - more = true; + if (mAnimateScreenLights) { + synchronized (mLocks) { + long now = SystemClock.uptimeMillis(); + boolean more = mScreenBrightness.stepLocked(); + if (more) { + mScreenOffHandler.postAtTime(this, now+(1000/60)); + } } - if (mButtonBrightness.stepLocked()) { - more = true; + } else { + boolean animate; + boolean jump; + synchronized (mLocks) { + jump = animating; // we haven't already run this animation + animate = jump && targetValue == Power.BRIGHTNESS_OFF; // we're turning off } - if (more) { - mHandler.postAtTime(mLightAnimator, now+(1000/60)); + if (animate) { + nativeStartSurfaceFlingerAnimation(); } + mScreenBrightness.jumpToTarget(); } } } @@ -2343,49 +2343,15 @@ class PowerManagerService extends IPowerManager.Stub Slog.d(TAG, "keyboardValue " + keyboardValue); } - boolean startAnimation = false; if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) { - if (ANIMATE_SCREEN_LIGHTS) { - if (mScreenBrightness.setTargetLocked(lcdValue, - AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS, - (int)mScreenBrightness.curValue)) { - startAnimation = true; - } - } else { - int brightnessMode = (mAutoBrightessEnabled - ? LightsService.BRIGHTNESS_MODE_SENSOR - : LightsService.BRIGHTNESS_MODE_USER); - mLcdLight.setBrightness(lcdValue, brightnessMode); - } + mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS, + INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue); } if (mButtonBrightnessOverride < 0) { - if (ANIMATE_BUTTON_LIGHTS) { - if (mButtonBrightness.setTargetLocked(buttonValue, - AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, - (int)mButtonBrightness.curValue)) { - startAnimation = true; - } - } else { - mButtonLight.setBrightness(buttonValue); - } + mButtonLight.setBrightness(buttonValue); } if (mButtonBrightnessOverride < 0 || !mKeyboardVisible) { - if (ANIMATE_KEYBOARD_LIGHTS) { - if (mKeyboardBrightness.setTargetLocked(keyboardValue, - AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, - (int)mKeyboardBrightness.curValue)) { - startAnimation = true; - } - } else { - mKeyboardLight.setBrightness(keyboardValue); - } - } - if (startAnimation) { - if (mDebugLightSensor) { - Slog.i(TAG, "lightSensorChangedLocked scheduling light animator"); - } - mHandler.removeCallbacks(mLightAnimator); - mHandler.post(mLightAnimator); + mKeyboardLight.setBrightness(keyboardValue); } } } @@ -2754,6 +2720,7 @@ class PowerManagerService extends IPowerManager.Stub } } + // for watchdog public void monitor() { synchronized (mLocks) { } } @@ -2773,34 +2740,23 @@ class PowerManagerService extends IPowerManager.Stub public void setBacklightBrightness(int brightness) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); // Don't let applications turn the screen all the way off - brightness = Math.max(brightness, Power.BRIGHTNESS_DIM); - mLcdLight.setBrightness(brightness); - mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0); - mButtonLight.setBrightness(brightness); - long identity = Binder.clearCallingIdentity(); - try { - mBatteryStats.noteScreenBrightness(brightness); - } catch (RemoteException e) { - Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e); - } finally { - Binder.restoreCallingIdentity(identity); - } + synchronized (mLocks) { + brightness = Math.max(brightness, Power.BRIGHTNESS_DIM); + mLcdLight.setBrightness(brightness); + mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0); + mButtonLight.setBrightness(brightness); + long identity = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteScreenBrightness(brightness); + } catch (RemoteException e) { + Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e); + } finally { + Binder.restoreCallingIdentity(identity); + } - // update our animation state - if (ANIMATE_SCREEN_LIGHTS) { - mScreenBrightness.curValue = brightness; - mScreenBrightness.animating = false; - mScreenBrightness.targetValue = -1; - } - if (ANIMATE_KEYBOARD_LIGHTS) { - mKeyboardBrightness.curValue = brightness; - mKeyboardBrightness.animating = false; - mKeyboardBrightness.targetValue = -1; - } - if (ANIMATE_BUTTON_LIGHTS) { - mButtonBrightness.curValue = brightness; - mButtonBrightness.animating = false; - mButtonBrightness.targetValue = -1; + // update our animation state + mScreenBrightness.targetValue = brightness; + mScreenBrightness.jumpToTarget(); } } diff --git a/services/jni/Android.mk b/services/jni/Android.mk index 459551d..d10f54f 100644 --- a/services/jni/Android.mk +++ b/services/jni/Android.mk @@ -24,7 +24,8 @@ LOCAL_SHARED_LIBRARIES := \ libnativehelper \ libsystem_server \ libutils \ - libui + libui \ + libsurfaceflinger_client LOCAL_STATIC_LIBRARIES := libusbhost diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp index 146c177..2ec20bd 100644 --- a/services/jni/com_android_server_PowerManagerService.cpp +++ b/services/jni/com_android_server_PowerManagerService.cpp @@ -20,9 +20,14 @@ #include "JNIHelp.h" #include "jni.h" + #include <limits.h> + #include <android_runtime/AndroidRuntime.h> #include <utils/Timers.h> +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/SurfaceComposerClient.h> + #include "com_android_server_PowerManagerService.h" namespace android { @@ -119,6 +124,12 @@ static void android_server_PowerManagerService_nativeSetPowerState(JNIEnv* env, gScreenBright = screenBright; } +static void android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation(JNIEnv* env, + jobject obj) { + sp<ISurfaceComposer> s(ComposerService::getComposerService()); + s->turnElectronBeamOff(0); +} + // ---------------------------------------------------------------------------- static JNINativeMethod gPowerManagerServiceMethods[] = { @@ -127,6 +138,8 @@ static JNINativeMethod gPowerManagerServiceMethods[] = { (void*) android_server_PowerManagerService_nativeInit }, { "nativeSetPowerState", "(ZZ)V", (void*) android_server_PowerManagerService_nativeSetPowerState }, + { "nativeStartSurfaceFlingerAnimation", "()V", + (void*) android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation }, }; #define FIND_CLASS(var, className) \ diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp index 1d09f84..fe9a5ab 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp @@ -359,7 +359,7 @@ status_t DisplayHardwareBase::ConsoleManagerThread::initCheck() const DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger, uint32_t displayIndex) - : mCanDraw(true) + : mCanDraw(true), mScreenAcquired(true) { mDisplayEventThread = new DisplayEventThread(flinger); if (mDisplayEventThread->initCheck() != NO_ERROR) { @@ -374,18 +374,21 @@ DisplayHardwareBase::~DisplayHardwareBase() mDisplayEventThread->requestExitAndWait(); } +void DisplayHardwareBase::setCanDraw(bool canDraw) +{ + mCanDraw = canDraw; +} bool DisplayHardwareBase::canDraw() const { - return mCanDraw; + return mCanDraw && mScreenAcquired; } void DisplayHardwareBase::releaseScreen() const { status_t err = mDisplayEventThread->releaseScreen(); if (err >= 0) { - //LOGD("screen given-up"); - mCanDraw = false; + mScreenAcquired = false; } } @@ -393,9 +396,14 @@ void DisplayHardwareBase::acquireScreen() const { status_t err = mDisplayEventThread->acquireScreen(); if (err >= 0) { - //LOGD("screen returned"); mCanDraw = true; + mScreenAcquired = true; } } +bool DisplayHardwareBase::isScreenAcquired() const +{ + return mScreenAcquired; +} + }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h index 8369bb8..fa6a0c4 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h @@ -40,7 +40,11 @@ public: // console managment void releaseScreen() const; void acquireScreen() const; + bool isScreenAcquired() const; + bool canDraw() const; + void setCanDraw(bool canDraw); + private: class DisplayEventThreadBase : public Thread { @@ -89,6 +93,7 @@ private: sp<DisplayEventThreadBase> mDisplayEventThread; mutable int mCanDraw; + mutable int mScreenAcquired; }; }; // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e6bdfd1..97365aa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -430,14 +430,14 @@ void SurfaceFlinger::handleConsoleEvents() hw.acquireScreen(); } - if (mDeferReleaseConsole && hw.canDraw()) { + if (mDeferReleaseConsole && hw.isScreenAcquired()) { // We got the release signal before the acquire signal mDeferReleaseConsole = false; hw.releaseScreen(); } if (what & eConsoleReleased) { - if (hw.canDraw()) { + if (hw.isScreenAcquired()) { hw.releaseScreen(); } else { mDeferReleaseConsole = true; @@ -1558,6 +1558,7 @@ status_t SurfaceFlinger::onTransact( case FREEZE_DISPLAY: case UNFREEZE_DISPLAY: case BOOT_FINISHED: + case TURN_ELECTRON_BEAM_OFF: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); @@ -1651,6 +1652,231 @@ status_t SurfaceFlinger::onTransact( return err; } + +// --------------------------------------------------------------------------- + +status_t SurfaceFlinger::turnElectronBeamOffImplLocked() +{ + status_t result = PERMISSION_DENIED; + + if (!GLExtensions::getInstance().haveFramebufferObject()) + return INVALID_OPERATION; + + // get screen geometry + const int dpy = 0; + const DisplayHardware& hw(graphicPlane(dpy).displayHardware()); + if (!hw.canDraw()) { + // we're already off + return NO_ERROR; + } + + const uint32_t hw_w = hw.getWidth(); + const uint32_t hw_h = hw.getHeight(); + const Region screenBounds(hw.bounds()); + GLfloat u = 1; + GLfloat v = 1; + + // make sure to clear all GL error flags + while ( glGetError() != GL_NO_ERROR ) ; + + // create a FBO + GLuint name, tname; + glGenTextures(1, &tname); + glBindTexture(GL_TEXTURE_2D, tname); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + if (glGetError() != GL_NO_ERROR) { + GLint tw = (2 << (31 - clz(hw_w))); + GLint th = (2 << (31 - clz(hw_h))); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + u = GLfloat(hw_w) / tw; + v = GLfloat(hw_h) / th; + } + glGenFramebuffersOES(1, &name); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); + glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); + + GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); + if (status == GL_FRAMEBUFFER_COMPLETE_OES) { + // redraw the screen entirely... + glClearColor(0,0,0,1); + glClear(GL_COLOR_BUFFER_BIT); + const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); + const size_t count = layers.size(); + for (size_t i=0 ; i<count ; ++i) { + const sp<LayerBase>& layer(layers[i]); + layer->drawForSreenShot(); + } + // back to main framebuffer + glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); + glDisable(GL_SCISSOR_TEST); + + GLfloat vtx[8]; + const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} }; + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tname); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, vtx); + + class s_curve_interpolator { + const float nbFrames, s, v; + public: + s_curve_interpolator(int nbFrames, float s) + : nbFrames(1.0f / (nbFrames-1)), s(s), + v(1.0f + expf(-s + 0.5f*s)) { + } + float operator()(int f) { + const float x = f * nbFrames; + return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f; + } + }; + + class v_stretch { + const GLfloat hw_w, hw_h; + public: + v_stretch(uint32_t hw_w, uint32_t hw_h) + : hw_w(hw_w), hw_h(hw_h) { + } + void operator()(GLfloat* vtx, float v) { + const GLfloat w = hw_w + (hw_w * v); + const GLfloat h = hw_h - (hw_h * v); + const GLfloat x = (hw_w - w) * 0.5f; + const GLfloat y = (hw_h - h) * 0.5f; + vtx[0] = x; vtx[1] = y; + vtx[2] = x; vtx[3] = y + h; + vtx[4] = x + w; vtx[5] = y + h; + vtx[6] = x + w; vtx[7] = y; + } + }; + + class h_stretch { + const GLfloat hw_w, hw_h; + public: + h_stretch(uint32_t hw_w, uint32_t hw_h) + : hw_w(hw_w), hw_h(hw_h) { + } + void operator()(GLfloat* vtx, float v) { + const GLfloat w = hw_w - (hw_w * v); + const GLfloat h = 1.0f; + const GLfloat x = (hw_w - w) * 0.5f; + const GLfloat y = (hw_h - h) * 0.5f; + vtx[0] = x; vtx[1] = y; + vtx[2] = x; vtx[3] = y + h; + vtx[4] = x + w; vtx[5] = y + h; + vtx[6] = x + w; vtx[7] = y; + } + }; + + // the full animation is 24 frames + const int nbFrames = 12; + + v_stretch vverts(hw_w, hw_h); + s_curve_interpolator itr(nbFrames, 7.5f); + s_curve_interpolator itg(nbFrames, 8.0f); + s_curve_interpolator itb(nbFrames, 8.5f); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + for (int i=0 ; i<nbFrames ; i++) { + float x, y, w, h; + const float vr = itr(i); + const float vg = itg(i); + const float vb = itb(i); + + // clear screen + glColorMask(1,1,1,1); + glClear(GL_COLOR_BUFFER_BIT); + glEnable(GL_TEXTURE_2D); + + // draw the red plane + vverts(vtx, vr); + glColorMask(1,0,0,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // draw the green plane + vverts(vtx, vg); + glColorMask(0,1,0,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // draw the blue plane + vverts(vtx, vb); + glColorMask(0,0,1,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // draw the white highlight (we use the last vertices) + glDisable(GL_TEXTURE_2D); + glColorMask(1,1,1,1); + glColor4f(vg, vg, vg, 1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + hw.flip(screenBounds); + } + + h_stretch hverts(hw_w, hw_h); + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glColorMask(1,1,1,1); + for (int i=0 ; i<nbFrames ; i++) { + const float v = itg(i); + hverts(vtx, v); + glClear(GL_COLOR_BUFFER_BIT); + glColor4f(1-v, 1-v, 1-v, 1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + hw.flip(screenBounds); + } + + glColorMask(1,1,1,1); + glEnable(GL_SCISSOR_TEST); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + result = NO_ERROR; + } else { + // release FBO resources + glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); + result = BAD_VALUE; + } + + glDeleteFramebuffersOES(1, &name); + glDeleteTextures(1, &tname); + + if (result == NO_ERROR) { + DisplayHardware& hw(graphicPlane(dpy).editDisplayHardware()); + hw.setCanDraw(false); + } + + return result; +} + +status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode) +{ + if (!GLExtensions::getInstance().haveFramebufferObject()) + return INVALID_OPERATION; + + class MessageTurnElectronBeamOff : public MessageBase { + SurfaceFlinger* flinger; + status_t result; + public: + MessageTurnElectronBeamOff(SurfaceFlinger* flinger) + : flinger(flinger), result(PERMISSION_DENIED) { + } + status_t getResult() const { + return result; + } + virtual bool handler() { + Mutex::Autolock _l(flinger->mStateLock); + result = flinger->turnElectronBeamOffImplLocked(); + return true; + } + }; + + sp<MessageBase> msg = new MessageTurnElectronBeamOff(this); + status_t res = postMessageSync(msg); + if (res == NO_ERROR) { + res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult(); + } + return res; +} + // --------------------------------------------------------------------------- status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, @@ -2115,6 +2341,10 @@ const DisplayHardware& GraphicPlane::displayHardware() const { return *mHw; } +DisplayHardware& GraphicPlane::editDisplayHardware() { + return *mHw; +} + const Transform& GraphicPlane::transform() const { return mGlobalTransform; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 732e57e..3470d87 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -141,6 +141,7 @@ public: int getHeight() const; const DisplayHardware& displayHardware() const; + DisplayHardware& editDisplayHardware(); const Transform& transform() const; EGLDisplay getEGLDisplay() const; @@ -200,6 +201,7 @@ public: PixelFormat* format, uint32_t reqWidth, uint32_t reqHeight); + virtual status_t turnElectronBeamOff(int32_t mode); void screenReleased(DisplayID dpy); void screenAcquired(DisplayID dpy); @@ -326,6 +328,8 @@ private: uint32_t* width, uint32_t* height, PixelFormat* format, uint32_t reqWidth = 0, uint32_t reqHeight = 0); + status_t turnElectronBeamOffImplLocked(); + friend class FreezeLock; sp<FreezeLock> getFreezeLock() const; inline void incFreezeCount() { |