Welcome 微信登录

首页 / 操作系统 / Linux / 探寻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效果,让我们跟踪下代码,先贴上相关代码:  frameworksaseservicesjavacomandroidserverPowerManagerService.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帧。 当然,该函数有许多限制,不符合就会半途退出,你就看不到动画效果啦。