探寻Android系统中的Old CRT OFF-Screen Animation


CM7手机的CRT关屏效果非常赞,在网上搜了半天,发现原来这是Android系统自带的功能,只是没有使能而已。

 

Android系统默认使用的关屏效果是fade,要激活旧CRT效果,需要修改以下文件,关闭fade效果。

 

 

frameworks/base/core/res/res/values/config.xml

    

     <!-- If this is true, the screen will fade off. -->

-    <bool name="config_animateScreenLights">true</bool>

+    <bool name="config_animateScreenLights">false</bool>

 

 

为啥如此修改就可以激活旧CRT效果,让我们跟踪下代码,先贴上相关代码:

 

 

frameworks\base\services\java\com\android\server\PowerManagerService.java

 

 

    475                 mAnimationSetting = 0;

    476                 if (windowScale > 0.5f) {

    477                     mAnimationSetting |= ANIM_SETTING_OFF;

    478                 }

 

 

   2284         public void run() {

   2285             if (mAnimateScreenLights) {

   2286                 synchronized (mLocks) {

   2287                     long now = SystemClock.uptimeMillis();

   2288                     boolean more = mScreenBrightness.stepLocked();

   2289                     if (more) {

   2290                         mScreenOffHandler.postAtTime(this, now+(1000/60));

   2291                     }

   2292                 }

   2293             } else {

   2294                 synchronized (mLocks) {

   2295                     // we're turning off

   2296                     final boolean animate = animating && targetValue == Power.BRIGHTNESS_OFF;

   2297                     if (animate) {

   2298                         // It's pretty scary to hold mLocks for this long, and we should

   2299                         // redesign this, but it works for now.

   2300                         nativeStartSurfaceFlingerAnimation(

   2301                                 mScreenOffReason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR

   2302                                 ? 0 : mAnimationSetting);

   2303                     }

   2304                     mScreenBrightness.jumpToTargetLocked();

   2305                 }

   2306             }

   2307         }

   2308     }

 

 

frameworks/base/services/jni/com_android_server_PowerManagerService.cpp

 

 

    131 static void android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation(JNIEnv* env,

    132         jobject obj, jint mode) {

    133     sp<ISurfaceComposer> s(ComposerService::getComposerService());

    134     s->turnElectronBeamOff(mode);

    135 }

 

 

frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp

 

   2385 status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)

   2386 {

   2387     class MessageTurnElectronBeamOff : public MessageBase {

   2388         SurfaceFlinger* flinger;

   2389         int32_t mode;

   2390         status_t result;

   2391     public:

   2392         MessageTurnElectronBeamOff(SurfaceFlinger* flinger, int32_t mode)

   2393             : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {

   2394         }

   2395         status_t getResult() const {

   2396             return result;

   2397         }

   2398         virtual bool handler() {

   2399             Mutex::Autolock _l(flinger->mStateLock);

   2400             result = flinger->turnElectronBeamOffImplLocked(mode);

   2401             return true;

   2402         }

   2403     };

   2404

   2405     sp<MessageBase> msg = new MessageTurnElectronBeamOff(this, mode);

   2406     status_t res = postMessageSync(msg);

   2407     if (res == NO_ERROR) {

   2408         res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();

   2409

   2410         // work-around: when the power-manager calls us we activate the

   2411         // animation. eventually, the "on" animation will be called

   2412         // by the power-manager itself

   2413         mElectronBeamAnimationMode = mode;

   2414     }

   2415     return res;

   2416 }

 

 

   2363 status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode)

   2364 {

   2365     DisplayHardware& hw(graphicPlane(0).editDisplayHardware());

   2366     if (!hw.canDraw()) {

   2367         // we're already off

   2368         return NO_ERROR;

   2369     }

   2370     if (mode & ISurfaceComposer::eElectronBeamAnimationOff) {

   2371         electronBeamOffAnimationImplLocked();

   2372     }

   2373

   2374     // always clear the whole screen at the end of the animation

   2375     glClearColor(0,0,0,1);

   2376     glDisable(GL_SCISSOR_TEST);

   2377     glClear(GL_COLOR_BUFFER_BIT);

   2378     glEnable(GL_SCISSOR_TEST);

   2379     hw.flip( Region(hw.bounds()) );

   2380

   2381     hw.setCanDraw(false);

   2382     return NO_ERROR;

   2383 }

 

   2073 status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()

   2074 {

   2075     status_t result = PERMISSION_DENIED;

   2076

   2077     if (!GLExtensions::getInstance().haveFramebufferObject())

   2078         return INVALID_OPERATION;

   2079

   2080     // get screen geometry

   2081     const DisplayHardware& hw(graphicPlane(0).displayHardware());

   2082     const uint32_t hw_w = hw.getWidth();

   2083     const uint32_t hw_h = hw.getHeight();

   2084     const Region screenBounds(hw.bounds());

   2085

   2086     GLfloat u, v;

   2087     GLuint tname;

   2088     result = renderScreenToTextureLocked(0, &tname, &u, &v);

   2089     if (result != NO_ERROR) {

   2090         return result;

   2091     }

   2092

   2093     GLfloat vtx[8];

   2094     const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };

   2095     glEnable(GL_TEXTURE_2D);

   2096     glBindTexture(GL_TEXTURE_2D, tname);

   2097     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

   2098     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

   2099     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

   2100     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

   2101     glEnableClientState(GL_TEXTURE_COORD_ARRAY);

   2102     glVertexPointer(2, GL_FLOAT, 0, vtx);

   2103

   2104     class s_curve_interpolator {

   2105         const float nbFrames, s, v;

   2106     public:

   2107         s_curve_interpolator(int nbFrames, float s)

   2108         : nbFrames(1.0f / (nbFrames-1)), s(s),

   2109           v(1.0f + expf(-s + 0.5f*s)) {

   2110         }

   2111         float operator()(int f) {

   2112             const float x = f * nbFrames;

   2113             return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;

   2114         }

   2115     };

   2116

   2117     class v_stretch {

   2118         const GLfloat hw_w, hw_h;

   2119     public:

   2120         v_stretch(uint32_t hw_w, uint32_t hw_h)

   2121         : hw_w(hw_w), hw_h(hw_h) {

   2122         }

   2123         void operator()(GLfloat* vtx, float v) {

   2124             const GLfloat w = hw_w + (hw_w * v);

   2125             const GLfloat h = hw_h - (hw_h * v);

   2126             const GLfloat x = (hw_w - w) * 0.5f;

   2127             const GLfloat y = (hw_h - h) * 0.5f;

   2128             vtx[0] = x;         vtx[1] = y;

   2129             vtx[2] = x;         vtx[3] = y + h;

   2130             vtx[4] = x + w;     vtx[5] = y + h;

   2131             vtx[6] = x + w;     vtx[7] = y;

   2132         }

   2133     };

   2134

   2135     class h_stretch {

   2136         const GLfloat hw_w, hw_h;

   2137     public:

   2138         h_stretch(uint32_t hw_w, uint32_t hw_h)

   2139         : hw_w(hw_w), hw_h(hw_h) {

   2140         }

   2141         void operator()(GLfloat* vtx, float v) {

   2142             const GLfloat w = hw_w - (hw_w * v);

   2143             const GLfloat h = 1.0f;

   2144             const GLfloat x = (hw_w - w) * 0.5f;

   2145             const GLfloat y = (hw_h - h) * 0.5f;

   2146             vtx[0] = x;         vtx[1] = y;

   2147             vtx[2] = x;         vtx[3] = y + h;

   2148             vtx[4] = x + w;     vtx[5] = y + h;

   2149             vtx[6] = x + w;     vtx[7] = y;

   2150         }

   2151     };

   2152

   2153     // the full animation is 24 frames

   2154     const int nbFrames = 12;

   2155     s_curve_interpolator itr(nbFrames, 7.5f);

   2156     s_curve_interpolator itg(nbFrames, 8.0f);

   2157     s_curve_interpolator itb(nbFrames, 8.5f);

   2158

   2159     v_stretch vverts(hw_w, hw_h);

   2160     glEnable(GL_BLEND);

   2161     glBlendFunc(GL_ONE, GL_ONE);

   2162     for (int i=0 ; i<nbFrames ; i++) {

   2163         float x, y, w, h;

   2164         const float vr = itr(i);

   2165         const float vg = itg(i);

   2166         const float vb = itb(i);

   2167

   2168         // clear screen

   2169         glColorMask(1,1,1,1);

   2170         glClear(GL_COLOR_BUFFER_BIT);

   2171         glEnable(GL_TEXTURE_2D);

   2172

   2173         // draw the red plane

   2174         vverts(vtx, vr);

   2175         glColorMask(1,0,0,1);

   2176         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

   2177

   2178         // draw the green plane

   2179         vverts(vtx, vg);

   2180         glColorMask(0,1,0,1);

   2181         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

   2182

   2183         // draw the blue plane

   2184         vverts(vtx, vb);

   2185         glColorMask(0,0,1,1);

   2186         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

   2187

   2188         // draw the white highlight (we use the last vertices)

   2189         glDisable(GL_TEXTURE_2D);

   2190         glColorMask(1,1,1,1);

   2191         glColor4f(vg, vg, vg, 1);

   2192         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

   2193         hw.flip(screenBounds);

   2194     }

   2195

   2196     h_stretch hverts(hw_w, hw_h);

   2197     glDisable(GL_BLEND);

   2198     glDisable(GL_TEXTURE_2D);

   2199     glColorMask(1,1,1,1);

   2200     for (int i=0 ; i<nbFrames ; i++) {

   2201         const float v = itg(i);

   2202         hverts(vtx, v);

   2203         glClear(GL_COLOR_BUFFER_BIT);

   2204         glColor4f(1-v, 1-v, 1-v, 1);

   2205         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

   2206         hw.flip(screenBounds);

   2207     }

   2208

   2209     glColorMask(1,1,1,1);

   2210     glEnable(GL_SCISSOR_TEST);

   2211     glDisableClientState(GL_TEXTURE_COORD_ARRAY);

   2212     glDeleteTextures(1, &tname);

   2213     return NO_ERROR;

   2214 }

   2215

 

 

 

OK,看完代码回来,首先是PowerManagerService.java中

mAnimationSetting如果标记为ANIM_SETTING_OFF,则打开旧CRT动画。

 

下面关屏动作run()中,因为我们将config_animateScreenLights置为false,因此mAnimateScreenLights为fasle

分支进入else,执行nativeStartSurfaceFlingerAnimation()函数。

 

nativeStartSurfaceFlingerAnimation()函数是一个JNI调用,在com_android_server_PowerManagerService.cpp文件中,

对应surfaceflinger的s->turnElectronBeamOff(mode)函数。

 

好的,现在跳入SurfaceFlinger.cpp函数,具体调用顺序是:

turnElectronBeamOff()

|

turnElectronBeamOffImplLocked()

|

electronBeamOffAnimationImplLocked()

 

electronBeamOffAnimationImplLocked()函数将调用openGL绘值旧CRT关屏效果,大概有24帧。

 

当然,该函数有许多限制,不符合就会半途退出,你就看不到动画效果啦。

相关内容