Android 2.3 对关屏进行了优化,增加了一种类似于关闭电视的效果
Android系统默认使用的关屏效果是fade,要激活旧CRT效果,需要修改以下文件,关闭fade效果。
frameworks/base/core/res/res/values/config.xml
- - < 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
-
class = "cpp" name= "code" > 131 static void Android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation(JNIEnv* env,
- 132 jobject obj, jint mode) {
- 133 sp
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
msg = new MessageTurnElectronBeamOff( this , mode); - 2406 status_t res = postMessageSync(msg);
- 2407 if (res == NO_ERROR) {
- 2408 res = static_cast
( 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
- 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
- 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帧。
当然,该函数有许多限制,不符合就会半途退出,你就看不到动画效果啦。