Android 开机画面和wallpaper总结
1 kernel的开机画面修改
1、图片需求:
图片格式:png
图片大小:1024x600(具体示lcd分辨率而定)。
2、转换图片png图片。
假设logo.png已经在目录"kernel/drivers/video/logo/logo.png"下,在kernel中依次执行一下步骤:
# cd kernel/drivers/video/logo
# pngtopnm logo.png > logo_linux.pnm
# pnmquant 224 logo_linux.pnm > logo_linux_clut224.pnm
# pnmtoplainpnm logo_linux_clut224.pnm > logo_linux_clut224.ppm
3、修改kernel config。
如果想要修改菜单配置,可以在kernel目录下执行make menuconfig;然后
进Device Drivers
进Graphics Support
进Bootop logo
进standard 224-clor Linux logo选择性加入图片
2 Android的开机画面修改
1、图片需求:
图片格式:png
图片大小:1024x600(具体示lcd分辨率而定)。
图片背景:黑色背景(推荐)
2、制作图片。
2.1 part0
将不需要重复播放的动画导成一张张的png图片(所有图片大小必须相同),依次命名为"00001.png","00002.png",...
(如 00001.png、00002.png、...、00074.png)
将整理好的图片放到"part0"目录下
2.2 part1
将不需要重复播放的动画导成一张张的png图片(所有图片大小必须相同),紧接着part0的图片名称继续命名。
(如 00075.png、00076.png)
将整理好的图片放到"part1"目录下
3、编辑"desc.txt"
如下所示:
desc.txt里面的命令格式如下:
1024 600 30
p 1 0 part0
p 0 0 part1
我逐一解释一下:
1024 600意思是说你开机动画在屏幕先以多少的分辨率显示,注意不要超过屏幕的分辨率,否则你的画面就显示不全了。
30 这个数字是代表着每秒播放的帧数,拿这个开机画面来说,part0文件夹里面共76张图片,播放时间就是76/30=2.533333秒播放完毕,当然在手机里面会有一定的延时,尤其是你的图片文件比较大的情况下,手机播快起来比较卡。
以下部分是实现画面重复位置的
p 1(代表着播放一次) 0(空指令)part0 */这句指令就代表这part0文件夹内的图片只按名称顺序播放一次
p 0(重复播放)0 (空指令)part1 */这一句指令代表着part1文件夹内的图片会循环反复播放
还有一种是指令不常用,下面也解释一下:
p 0 10 part1 这里面的那个10代表着播放完part1文件夹内的图片一遍之后稍作停顿,然后再循环播放一遍,再停顿少许,再播放,再停顿稍许·········重复下去
p 1 10 part1 同理,这句代表着播放完part1文件夹内的图片之后稍作停顿然后继续执行吓一条命令。
4、打包
必须在"windows"系统下,将"part0"、"part1"、"desc.txt"一起打包成"bootanimation.zip"。
打包的时候,必须是"zip"格式,而且压缩方式是“存储”。否则,android不能识别到,会出现黑屏!
5、动画测试
5.1 将制作好的"bootanimation.zip"通过adb导入到android进行测试,命令如下。
# adb remount
# adb push bootanimation.zip /system/media/bootanimation.zip
# adb reboot
5.2 若不需要"bootanimation.zip"动画,直接将"bootanimation.zip"从"system/media"中删除即可。
3 android的默认墙纸修改
1、Android默认墙纸的路径:
frameworks/base/core/res/res/drawable/default_wallpaper.jpg
路径根据工程的不同可以稍微有点变化;具体图片的大小,可以参考原图or根据分辨率计算。
2、同步墙纸到“墙纸设置”选项中
下面解释一下将“修改的墙纸”同步到Launcher2的墙纸设置选项中
2.1 找到Laucher2中实际使用的墙纸和对应的配置文件。例如:
墙纸的配置文件路径,
packages/apps/Launcher2/res/values-sw720dp/wallpapers.xml
墙纸的路径:
packages/apps/Launcher2/res/drawable-sw720dp-nodpi/wallpaper_architecture.jpg
packages/apps/Launcher2/res/drawable-sw720dp-nodpi/wallpaper_architecture_small.jpg
2.2 根据已有的图片,来制作实际的图片。
附录一 android的开机动画流程
1、开机动画程序bootanimation
程序目录:frameworks/base/cmds/bootanimation
主要文件:frameworks/base/cmds/bootanimation/BootAnimation.cpp
调用位置: 在init.rc中调用bootanimation
2、bootanimation流程
2.1 显示方式
判断是否存在"/data/local/bootanimation.zip"或"/system/media/bootanimation.zip",
若存在的话,则显示bootanimation.zip中的动画;
若不存在的话,则显示系统默认的android闪动画面。
具体的代码(在BootAnimation.cpp中):
--> readyToRun()中判断bootanimation.zip是否存在
--> threadLoop()中根据mAndroidAnimation的值,来区分不同的显示方式
--> 若mAndroidAnimation为true,则显示默认的动画,调用android()
若mAndroidAnimation为false,则显示bootanimation.zip中的动画,调用movie()
3、程序代码
BootAnimation.cpp如下:
1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "BootAnimation" 18 19 #include <stdint.h> 20 #include <sys/types.h> 21 #include <math.h> 22 #include <fcntl.h> 23 #include <utils/misc.h> 24 #include <signal.h> 25 26 #include <cutils/properties.h> 27 28 #include <androidfw/AssetManager.h> 29 #include <binder/IPCThreadState.h> 30 #include <utils/Atomic.h> 31 #include <utils/Errors.h> 32 #include <utils/Log.h> 33 #include <utils/threads.h> 34 35 #include <ui/PixelFormat.h> 36 #include <ui/Rect.h> 37 #include <ui/Region.h> 38 #include <ui/DisplayInfo.h> 39 #include <ui/FramebufferNativeWindow.h> 40 41 #include <gui/Surface.h> 42 #include <gui/SurfaceComposerClient.h> 43 44 #include <core/SkBitmap.h> 45 #include <core/SkStream.h> 46 #include <images/SkImageDecoder.h> 47 #include <media/mediaplayer.h> 48 49 #include <GLES/gl.h> 50 #include <GLES/glext.h> 51 #include <EGL/eglext.h> 52 53 #include "BootAnimation.h" 54 55 #define USER_BOOTANIMATION_FILE "/data/local/bootanimation.zip" 56 #define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip" 57 #define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip" 58 #define USER_SHUTDOWN_BOOTANIMATION_FILE "/data/local/shutdownanimation.zip" 59 #define SYSTEM_SHUTDOWN_BOOTANIMATION_FILE "/system/media/shutdownanimation.zip" 60 #define EXIT_PROP_NAME "service.bootanim.exit" 61 #define BOOTMUSIC_FILE "/system/media/audio/boot.ogg" 62 63 //add by cjf 64 #define BOOTANIMATION_VIDEO "/system/media/bootanimation.mp4" 65 66 #define FIXED_ONE 1 67 68 extern "C" int clock_nanosleep(clockid_t clock_id, int flags, 69 const struct timespec *request, 70 struct timespec *remain); 71 72 namespace android { 73 74 // --------------------------------------------------------------------------- 75 76 BootAnimation::BootAnimation() : Thread(false) 77 { 78 mSession = new SurfaceComposerClient(); 79 mHardwareRotation = 0; 80 mFakeRotation = false; 81 mShutdown = false; 82 char property[PROPERTY_VALUE_MAX]; 83 if (property_get("ro.sf.hwrotation", property, "0") > 0) { 84 mHardwareRotation = atoi(property); 85 } 86 87 if (property_get("ro.sf.fakerotation", property, "false") > 0) { 88 mFakeRotation = !strcmp(property, "true"); 89 } 90 mReverseAxis = mFakeRotation; 91 } 92 93 BootAnimation::~BootAnimation() { 94 } 95 96 void BootAnimation::isShutdown(bool shutdown) { 97 mShutdown = shutdown; 98 } 99 100 101 void BootAnimation::onFirstRef() { 102 status_t err = mSession->linkToComposerDeath(this); 103 ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err)); 104 if (err == NO_ERROR) { 105 run("BootAnimation", PRIORITY_DISPLAY); 106 } 107 } 108 109 sp<SurfaceComposerClient> BootAnimation::session() const { 110 return mSession; 111 } 112 113 114 void BootAnimation::binderDied(const wp<IBinder>& who) 115 { 116 // woah, surfaceflinger died! 117 ALOGD("SurfaceFlinger died, exiting..."); 118 119 // calling requestExit() is not enough here because the Surface code 120 // might be blocked on a condition variable that will never be updated. 121 kill( getpid(), SIGKILL ); 122 requestExit(); 123 } 124 125 status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, 126 const char* name) { 127 Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); 128 if (!asset) 129 return NO_INIT; 130 SkBitmap bitmap; 131 SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(), 132 &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode); 133 asset->close(); 134 delete asset; 135 136 // ensure we can call getPixels(). No need to call unlock, since the 137 // bitmap will go out of scope when we return from this method. 138 bitmap.lockPixels(); 139 140 const int w = bitmap.width(); 141 const int h = bitmap.height(); 142 const void* p = bitmap.getPixels(); 143 144 GLint crop[4] = { 0, h, w, -h }; 145 texture->w = w; 146 texture->h = h; 147 148 glGenTextures(1, &texture->name); 149 glBindTexture(GL_TEXTURE_2D, texture->name); 150 151 switch (bitmap.getConfig()) { 152 case SkBitmap::kA8_Config: 153 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, 154 GL_UNSIGNED_BYTE, p); 155 break; 156 case SkBitmap::kARGB_4444_Config: 157 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 158 GL_UNSIGNED_SHORT_4_4_4_4, p); 159 break; 160 case SkBitmap::kARGB_8888_Config: 161 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 162 GL_UNSIGNED_BYTE, p); 163 break; 164 case SkBitmap::kRGB_565_Config: 165 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, 166 GL_UNSIGNED_SHORT_5_6_5, p); 167 break; 168 default: 169 break; 170 } 171 172 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); 173 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 174 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 175 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 176 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 177 178 return NO_ERROR; 179 } 180 181 status_t BootAnimation::initTexture(void* buffer, size_t len) 182 { 183 //StopWatch watch("blah"); 184 185 SkBitmap bitmap; 186 SkMemoryStream stream(buffer, len); 187 SkImageDecoder* codec = SkImageDecoder::Factory(&stream); 188 codec->setDitherImage(false); 189 if (codec) { 190 codec->decode(&stream, &bitmap, 191 SkBitmap::kARGB_8888_Config, 192 SkImageDecoder::kDecodePixels_Mode); 193 delete codec; 194 } 195 196 // ensure we can call getPixels(). No need to call unlock, since the 197 // bitmap will go out of scope when we return from this method. 198 bitmap.lockPixels(); 199 200 const int w = bitmap.width(); 201 const int h = bitmap.height(); 202 const void* p = bitmap.getPixels(); 203 204 GLint crop[4] = { 0, h, w, -h }; 205 int tw = 1 << (31 - __builtin_clz(w)); 206 int th = 1 << (31 - __builtin_clz(h)); 207 if (tw < w) tw <<= 1; 208 if (th < h) th <<= 1; 209 210 mBMPWidth = w; 211 mBMPHeight = h; 212 mTexWidth = tw; 213 mTexHeight = th; 214 215 switch (bitmap.getConfig()) { 216 case SkBitmap::kARGB_8888_Config: 217 if (tw != w || th != h) { 218 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, 219 GL_UNSIGNED_BYTE, 0); 220 glTexSubImage2D(GL_TEXTURE_2D, 0, 221 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p); 222 } else { 223 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, 224 GL_UNSIGNED_BYTE, p); 225 } 226 break; 227 228 case SkBitmap::kRGB_565_Config: 229 if (tw != w || th != h) { 230 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, 231 GL_UNSIGNED_SHORT_5_6_5, 0); 232 glTexSubImage2D(GL_TEXTURE_2D, 0, 233 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); 234 } else { 235 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, 236 GL_UNSIGNED_SHORT_5_6_5, p); 237 } 238 break; 239 default: 240 break; 241 } 242 243 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); 244 245 return NO_ERROR; 246 } 247 248 //add by cjf 249 status_t BootAnimation::initTexture(SkBitmap bitmap) 250 { 251 252 // ensure we can call getPixels(). No need to call unlock, since the 253 // bitmap will go out of scope when we return from this method. 254 bitmap.lockPixels(); 255 256 const int w = bitmap.width(); 257 const int h = bitmap.height(); 258 const void* p = bitmap.getPixels(); 259 260 GLint crop[4] = { 0, h, w, -h }; 261 int tw = 1 << (31 - __builtin_clz(w)); 262 int th = 1 << (31 - __builtin_clz(h)); 263 if (tw < w) tw <<= 1; 264 if (th < h) th <<= 1; 265 266 mBMPWidth = w; 267 mBMPHeight = h; 268 mTexWidth = tw; 269 mTexHeight = th; 270 271 switch (bitmap.getConfig()) { 272 case SkBitmap::kARGB_8888_Config: 273 if (tw != w || th != h) { 274 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, 275 GL_UNSIGNED_BYTE, 0); 276 glTexSubImage2D(GL_TEXTURE_2D, 0, 277 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p); 278 } else { 279 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, 280 GL_UNSIGNED_BYTE, p); 281 } 282 break; 283 284 case SkBitmap::kRGB_565_Config: 285 if (tw != w || th != h) { 286 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, 287 GL_UNSIGNED_SHORT_5_6_5, 0); 288 glTexSubImage2D(GL_TEXTURE_2D, 0, 289 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); 290 } else { 291 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, 292 GL_UNSIGNED_SHORT_5_6_5, p); 293 } 294 break; 295 default: 296 break; 297 } 298 299 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); 300 301 return NO_ERROR; 302 } 303 304 status_t BootAnimation::readyToRun() { 305 mAssets.addDefaultAssets(); 306 307 DisplayInfo dinfo; 308 status_t status = session()->getDisplayInfo(0, &dinfo); 309 if (status) 310 return -1; 311 312 // create the native surface 313 sp<SurfaceControl> control = session()->createSurface( 314 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565); 315 316 SurfaceComposerClient::openGlobalTransaction(); 317 control->setLayer(0x40000000); 318 SurfaceComposerClient::closeGlobalTransaction(); 319 320 sp<Surface> s = control->getSurface(); 321 // initialize opengl and egl 322 const EGLint attribs[] = { 323 EGL_RED_SIZE, 8, 324 EGL_GREEN_SIZE, 8, 325 EGL_BLUE_SIZE, 8, 326 EGL_DEPTH_SIZE, 0, 327 EGL_NONE 328 }; 329 EGLint w, h, dummy; 330 EGLint numConfigs; 331 EGLConfig config; 332 EGLSurface surface; 333 EGLContext context; 334 335 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 336 337 eglInitialize(display, 0, 0); 338 eglChooseConfig(display, attribs, &config, 1, &numConfigs); 339 surface = eglCreateWindowSurface(display, config, s.get(), NULL); 340 context = eglCreateContext(display, config, NULL, NULL); 341 eglQuerySurface(display, surface, EGL_WIDTH, &w); 342 eglQuerySurface(display, surface, EGL_HEIGHT, &h); 343 344 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) 345 return NO_INIT; 346 347 mDisplay = display; 348 mContext = context; 349 mSurface = surface; 350 mWidth = w; 351 mHeight = h; 352 mFlingerSurfaceControl = control; 353 mFlingerSurface = s; 354 355 mAndroidAnimation = true; 356 357 // If the device has encryption turned on or is in process 358 // of being encrypted we show the encrypted boot animation. 359 char decrypt[PROPERTY_VALUE_MAX]; 360 property_get("vold.decrypt", decrypt, ""); 361 362 bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt); 363 364 if ((encryptedAnimation && 365 (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) && 366 (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) || 367 368 ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) && 369 (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) || 370 371 ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) && 372 (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) { 373 mAndroidAnimation = false; 374 } 375 if (!mShutdown) { 376 status_t err = mZip.open("/data/local/bootanimation.zip"); 377 if (err != NO_ERROR) { 378 err = mZip.open("/system/media/bootanimation.zip"); 379 if (err != NO_ERROR) { 380 mAndroidAnimation = true; 381 } 382 } 383 384 //add by cjf 385 mMovie = SkMovie::DecodeFile("/system/media/bootanimation.gif"); 386 if (mMovie) { 387 mGifAnimation = true; 388 } 389 if (access(BOOTANIMATION_VIDEO, R_OK) == 0) { 390 mVideo = true; 391 } 392 393 } else { 394 status_t err = mZip.open("/data/local/shutdownanimation.zip"); 395 if (err != NO_ERROR) { 396 err = mZip.open("/system/media/shutdownanimation.zip"); 397 if (err != NO_ERROR) { 398 mAndroidAnimation = true; 399 } 400 } 401 } 402 return NO_ERROR; 403 } 404 405 bool BootAnimation::threadLoop() 406 { 407 bool r; 408 409 //add by cjf 410 if (mVideo) { 411 r = video(); 412 } else if (mGifAnimation) { 413 r = gifMovie(); 414 } else 415 416 if (mAndroidAnimation) { 417 r = android(); 418 } else { 419 r = movie(); 420 } 421 422 // No need to force exit anymore 423 property_set(EXIT_PROP_NAME, "0"); 424 425 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 426 eglDestroyContext(mDisplay, mContext); 427 eglDestroySurface(mDisplay, mSurface); 428 mFlingerSurface.clear(); 429 mFlingerSurfaceControl.clear(); 430 eglTerminate(mDisplay); 431 IPCThreadState::self()->stopProcess(); 432 return r; 433 } 434 435 void BootAnimation::getTexCoordinate() { 436 437 GLfloat w_scale = float(mBMPWidth)/mTexWidth; 438 GLfloat h_scale = float(mBMPHeight)/mTexHeight; 439 440 if (mFakeRotation) { 441 mTexCoords[0]=0; mTexCoords[1]=FIXED_ONE*h_scale; 442 mTexCoords[2]=0; mTexCoords[3]=0; 443 mTexCoords[4]=FIXED_ONE*w_scale; mTexCoords[5]=0; 444 mTexCoords[6]=FIXED_ONE*w_scale; mTexCoords[7]=FIXED_ONE*h_scale; 445 } else { 446 mTexCoords[0]=0; mTexCoords[1]=0; 447 mTexCoords[2]=FIXED_ONE*w_scale; mTexCoords[3]=0; 448 mTexCoords[4]=FIXED_ONE*w_scale; mTexCoords[5]=FIXED_ONE*h_scale; 449 mTexCoords[6]=0; mTexCoords[7]=FIXED_ONE*h_scale; 450 } 451 } 452 453 void BootAnimation::playMusic() 454 { 455 sp<MediaPlayer> mp = new MediaPlayer(); 456 if ((0 == access(BOOTMUSIC_FILE, F_OK)) && mp != NULL) { 457 mp->setDataSource(BOOTMUSIC_FILE, NULL); 458 mp->prepare(); 459 mp->start(); 460 } 461 } 462 463 464 bool BootAnimation::android() 465 { 466 initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); 467 initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png"); 468 mBMPWidth = mTexWidth = mBMPHeight = mTexHeight = 1; 469 getTexCoordinate(); 470 int first = true; 471 472 // to add startup music 473 #ifdef BOOTMUSIC_FILE 474 playMusic(); 475 #endif 476 477 // clear screen 478 glShadeModel(GL_FLAT); 479 glDisable(GL_DITHER); 480 glViewport(0, 0, mWidth, mHeight); 481 glMatrixMode(GL_PROJECTION); 482 glLoadIdentity(); 483 float ratio = mWidth / mHeight; 484 glFrustumf(-ratio, ratio, -1, 1, 0, 1); 485 glMatrixMode(GL_MODELVIEW); 486 glLoadIdentity(); 487 glOrthof(0, mWidth, mHeight, 0, 0, 1); 488 489 glEnable(GL_TEXTURE_2D); 490 glEnableClientState(GL_VERTEX_ARRAY); 491 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 492 glDisable(GL_SCISSOR_TEST); 493 494 glClearColor(0,0,0,1); 495 glClear(GL_COLOR_BUFFER_BIT); 496 eglSwapBuffers(mDisplay, mSurface); 497 498 // Blend state 499 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 500 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 501 502 if (mReverseAxis) { 503 exchangeParameters(&mWidth, &mHeight); 504 } 505 506 GLfloat xc = float(mWidth - mAndroid[0].w) / 2; 507 GLfloat yc = float(mHeight - mAndroid[0].h) / 2; 508 509 if (mReverseAxis) { 510 exchangeParameters(&xc, &yc); 511 exchangeParameters(&mAndroid[0].w, &mAndroid[0].h); 512 exchangeParameters(&mAndroid[1].w, &mAndroid[1].h); 513 } 514 515 const GLfloat mask_vertices[] = { 516 xc, yc, 0, 517 xc+mAndroid[0].w, yc, 0, 518 xc+mAndroid[0].w, yc+mAndroid[0].h, 0, 519 xc, yc+mAndroid[0].h, 0 520 }; 521 522 const GLfloat shine_vertices[] = { 523 xc, yc, 0, 524 xc+mAndroid[1].w, yc, 0, 525 xc+mAndroid[1].w, yc+mAndroid[1].h, 0, 526 xc, yc+mAndroid[1].h, 0 527 }; 528 529 const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; 530 int nelem = sizeof(indices)/sizeof(indices[0]); 531 532 const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); 533 glScissor(updateRect.left, updateRect.top, updateRect.width(), 534 updateRect.height()); 535 536 const nsecs_t startTime = systemTime(); 537 do { 538 nsecs_t now = systemTime(); 539 double time = now - startTime; 540 float t = 0; 541 GLint x, y, offset; 542 543 if (mReverseAxis) { 544 t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].h; 545 offset = (1 - (t - floorf(t))) * mAndroid[1].h; 546 y = yc - offset; 547 } else { 548 t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; 549 offset = (1 - (t - floorf(t))) * mAndroid[1].w; 550 x = xc - offset; 551 } 552 553 glMatrixMode(GL_TEXTURE); 554 glLoadIdentity(); 555 glMatrixMode(GL_MODELVIEW); 556 557 558 glDisable(GL_SCISSOR_TEST); 559 glClear(GL_COLOR_BUFFER_BIT); 560 glEnable(GL_SCISSOR_TEST); 561 562 if (mReverseAxis) { 563 glTranslatef(0, -offset, 0); 564 } else { 565 glTranslatef(-offset, 0, 0); 566 } 567 glDisable(GL_BLEND); 568 glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); 569 glVertexPointer(3, GL_FLOAT, 0, shine_vertices); 570 glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords); 571 glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices); 572 573 if (mReverseAxis) { 574 glTranslatef(0, mAndroid[1].h, 0); 575 } else { 576 glTranslatef(mAndroid[1].w, 0, 0); 577 } 578 glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices); 579 580 if (mReverseAxis) { 581 glTranslatef(0, offset - mAndroid[1].h, 0); 582 } else { 583 glTranslatef(offset - mAndroid[1].w, 0, 0); 584 } 585 586 glEnable(GL_BLEND); 587 glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); 588 glVertexPointer(3, GL_FLOAT, 0, mask_vertices); 589 glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords); 590 glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices); 591 592 EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); 593 if (res == EGL_FALSE) 594 break; 595 596 // 12fps: don't animate too fast to preserve CPU 597 const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now); 598 if (sleepTime > 0) 599 usleep(sleepTime); 600 601 checkExit(); 602 } while (!exitPending()); 603 604 glDeleteTextures(1, &mAndroid[0].name); 605 glDeleteTextures(1, &mAndroid[1].name); 606 return false; 607 } 608 609 610 void BootAnimation::checkExit() { 611 // Allow surface flinger to gracefully request shutdown 612 if(mShutdown)//shutdown animation 613 { 614 return; 615 } 616 char value[PROPERTY_VALUE_MAX]; 617 property_get(EXIT_PROP_NAME, value, "0"); 618 int exitnow = atoi(value); 619 if (exitnow) { 620 requestExit(); 621 } 622 } 623 624 bool BootAnimation::movie() 625 { 626 #ifdef BOOTMUSIC_FILE 627 playMusic(); 628 #endif 629 ZipFileRO& zip(mZip); 630 631 size_t numEntries = zip.getNumEntries(); 632 ZipEntryRO desc = zip.findEntryByName("desc.txt"); 633 FileMap* descMap = zip.createEntryFileMap(desc); 634 ALOGE_IF(!descMap, "descMap is null"); 635 if (!descMap) { 636 return false; 637 } 638 639 String8 desString((char const*)descMap->getDataPtr(), 640 descMap->getDataLength()); 641 char const* s = desString.string(); 642 643 Animation animation; 644 645 // Parse the description file 646 for (;;) { 647 const char* endl = strstr(s, "\n"); 648 if (!endl) break; 649 String8 line(s, endl - s); 650 const char* l = line.string(); 651 int fps, width, height, count, pause; 652 char path[256]; 653 char pathType; 654 if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { 655 //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); 656 if (mReverseAxis) { 657 animation.width = height; 658 animation.height = width; 659 } else { 660 animation.width = width; 661 animation.height = height; 662 } 663 animation.fps = fps; 664 } 665 else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) { 666 //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path); 667 Animation::Part part; 668 part.playUntilComplete = pathType == 'c'; 669 part.count = count; 670 part.pause = pause; 671 part.path = path; 672 animation.parts.add(part); 673 } 674 675 s = ++endl; 676 } 677 678 // read all the data structures 679 const size_t pcount = animation.parts.size(); 680 for (size_t i=0 ; i<numEntries ; i++) { 681 char name[256]; 682 ZipEntryRO entry = zip.findEntryByIndex(i); 683 if (zip.getEntryFileName(entry, name, 256) == 0) { 684 const String8 entryName(name); 685 const String8 path(entryName.getPathDir()); 686 const String8 leaf(entryName.getPathLeaf()); 687 if (leaf.size() > 0) { 688 for (int j=0 ; j<pcount ; j++) { 689 if (path == animation.parts[j].path) { 690 int method; 691 // supports only stored png files 692 if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) { 693 if (method == ZipFileRO::kCompressStored) { 694 FileMap* map = zip.createEntryFileMap(entry); 695 if (map) { 696 Animation::Frame frame; 697 frame.name = leaf; 698 frame.map = map; 699 Animation::Part& part(animation.parts.editItemAt(j)); 700 part.frames.add(frame); 701 } 702 } 703 } 704 } 705 } 706 } 707 } 708 } 709 710 // clear screen 711 glShadeModel(GL_FLAT); 712 glDisable(GL_DITHER); 713 glViewport(0, 0, mWidth, mHeight); 714 glMatrixMode(GL_PROJECTION); 715 glLoadIdentity(); 716 float ratio = mWidth / mHeight; 717 glFrustumf(-ratio, ratio, -1, 1, 0, 1); 718 glMatrixMode(GL_MODELVIEW); 719 glLoadIdentity(); 720 glOrthof(0, mWidth, mHeight, 0, 0, 1); 721 722 glEnable(GL_TEXTURE_2D); 723 glEnableClientState(GL_VERTEX_ARRAY); 724 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 725 glDisable(GL_SCISSOR_TEST); 726 727 glClearColor(0,0,0,1); 728 glClear(GL_COLOR_BUFFER_BIT); 729 eglSwapBuffers(mDisplay, mSurface); 730 731 glBindTexture(GL_TEXTURE_2D, 0); 732 glEnable(GL_TEXTURE_2D); 733 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 734 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 735 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 736 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 737 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 738 739 const int xc = (mWidth - animation.width) / 2; 740 const int yc = ((mHeight - animation.height) / 2); 741 nsecs_t lastFrame = systemTime(); 742 nsecs_t frameDuration = s2ns(1) / animation.fps; 743 744 Region clearReg(Rect(mWidth, mHeight)); 745 clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); 746 747 const GLfloat vertices[] = { 748 xc, yc, 0, 749 xc+animation.width, yc, 0, 750 xc+animation.width, yc+animation.height, 0, 751 xc, yc+animation.height, 0 752 }; 753 754 const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; 755 int nelem = sizeof(indices)/sizeof(indices[0]); 756 757 for (int i=0 ; i<pcount ; i++) { 758 const Animation::Part& part(animation.parts[i]); 759 const size_t fcount = part.frames.size(); 760 glBindTexture(GL_TEXTURE_2D, 0); 761 762 for (int r=0 ; !part.count || r<part.count ; r++) { 763 // Exit any non playuntil complete parts immediately 764 if(exitPending() && !part.playUntilComplete) 765 break; 766 767 for (int j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { 768 const Animation::Frame& frame(part.frames[j]); 769 nsecs_t lastFrame = systemTime(); 770 771 if (r > 0) { 772 glBindTexture(GL_TEXTURE_2D, frame.tid); 773 } else { 774 if (part.count != 1) { 775 glGenTextures(1, &frame.tid); 776 glBindTexture(GL_TEXTURE_2D, frame.tid); 777 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 778 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 779 } 780 initTexture( 781 frame.map->getDataPtr(), 782 frame.map->getDataLength()); 783 784 getTexCoordinate(); 785 } 786 787 788 if (!clearReg.isEmpty()) { 789 Region::const_iterator head(clearReg.begin()); 790 Region::const_iterator tail(clearReg.end()); 791 glEnable(GL_SCISSOR_TEST); 792 while (head != tail) { 793 const Rect& r(*head++); 794 glScissor(r.left, mHeight - r.bottom, 795 r.width(), r.height()); 796 glClear(GL_COLOR_BUFFER_BIT); 797 } 798 glDisable(GL_SCISSOR_TEST); 799 } 800 801 glVertexPointer(3, GL_FLOAT, 0, vertices); 802 glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords); 803 glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices); 804 805 eglSwapBuffers(mDisplay, mSurface); 806 807 nsecs_t now = systemTime(); 808 nsecs_t delay = frameDuration - (now - lastFrame); 809 //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay)); 810 lastFrame = now; 811 812 if (delay > 0) { 813 struct timespec spec; 814 spec.tv_sec = (now + delay) / 1000000000; 815 spec.tv_nsec = (now + delay) % 1000000000; 816 int err; 817 do { 818 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); 819 } while (err<0 && errno == EINTR); 820 } 821 822 checkExit(); 823 } 824 825 usleep(part.pause * ns2us(frameDuration)); 826 827 // For infinite parts, we've now played them at least once, so perhaps exit 828 if(exitPending() && !part.count) 829 break; 830 } 831 832 // free the textures for this part 833 if (part.count != 1) { 834 for (int j=0 ; j<fcount ; j++) { 835 const Animation::Frame& frame(part.frames[j]); 836 glDeleteTextures(1, &frame.tid); 837 } 838 } 839 } 840 841 return false; 842 } 843 844 845 bool BootAnimation::video() 846 { 847 const float MAX_FPS = 60.0f; 848 const bool LOOP = true; 849 const float CHECK_DELAY = ns2us(s2ns(1) / MAX_FPS); 850 851 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 852 eglDestroySurface(mDisplay, mSurface); 853 854 float asp = 1.0f * mWidth / mHeight; 855 SurfaceComposerClient::openGlobalTransaction(); 856 mFlingerSurfaceControl->setPosition(mWidth, 0); 857 mFlingerSurfaceControl->setMatrix(0, 1 / asp, -asp, 0); 858 SurfaceComposerClient::closeGlobalTransaction(); 859 860 sp<MediaPlayer> mp = new MediaPlayer(); 861 mp->setDataSource(BOOTANIMATION_VIDEO, NULL); 862 mp->setLooping(true); 863 mp->setVideoSurfaceTexture(mFlingerSurface->getSurfaceTexture()); 864 mp->prepare(); 865 mp->start(); 866 while(true) { 867 if(exitPending()) 868 break; 869 usleep(CHECK_DELAY); 870 checkExit(); 871 } 872 mp->stop(); 873 return false; 874 } 875 876 //add by cjf 877 bool BootAnimation::gifMovie() 878 { 879 #ifdef BOOTMUSIC_FILE 880 playMusic(); 881 #endif 882 GLuint texture = 0; 883 SkMSec duration = mMovie->duration(); 884 int width = mMovie->width(); 885 int height = mMovie->height(); 886 887 const float SPEED = 1.0f; 888 const float MAX_FPS = 60.0f; 889 const bool LOOP = true; 890 const SkMSec LOOP_DELAY = 3000; 891 892 // clear screen 893 glShadeModel(GL_FLAT); 894 glDisable(GL_DITHER); 895 glViewport(0, 0, mWidth, mHeight); 896 glMatrixMode(GL_PROJECTION); 897 glLoadIdentity(); 898 float ratio = mWidth / mHeight; 899 glFrustumf(-ratio, ratio, -1, 1, 0, 1); 900 glMatrixMode(GL_MODELVIEW); 901 glLoadIdentity(); 902 glOrthof(0, mWidth, mHeight, 0, 0, 1); 903 904 glEnable(GL_TEXTURE_2D); 905 glEnableClientState(GL_VERTEX_ARRAY); 906 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 907 glDisable(GL_SCISSOR_TEST); 908 909 glClearColor(0,0,0,1); 910 glClear(GL_COLOR_BUFFER_BIT); 911 eglSwapBuffers(mDisplay, mSurface); 912 913 glBindTexture(GL_TEXTURE_2D, 0); 914 glEnable(GL_TEXTURE_2D); 915 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 916 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 917 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 918 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 919 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 920 921 922 if (mReverseAxis) { 923 exchangeParameters(&width, &height); 924 } 925 926 927 const int xc = (mWidth - width) / 2; 928 const int yc = ((mHeight - height) / 2); 929 nsecs_t frameDuration = s2ns(1) / MAX_FPS; 930 931 Region clearReg(Rect(mWidth, mHeight)); 932 clearReg.subtractSelf(Rect(xc, yc, xc+width, yc+height)); 933 934 const GLfloat vertices[] = { 935 xc, yc, 0, 936 xc+width, yc, 0, 937 xc+width, yc+height, 0, 938 xc, yc+height, 0 939 }; 940 941 const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; 942 int nelem = sizeof(indices)/sizeof(indices[0]); 943 944 glBindTexture(GL_TEXTURE_2D, 0); 945 946 nsecs_t firstFrame = systemTime(); 947 948 while (true) { 949 if(exitPending()) 950 break; 951 nsecs_t lastFrame = systemTime(); 952 953 SkMSec time = SPEED * (lastFrame - firstFrame) / 1000000; 954 955 if (LOOP & time >= duration) { 956 usleep(LOOP_DELAY * 1000); 957 firstFrame = systemTime(); 958 time = 0; 959 } 960 961 mMovie->setTime(time); 962 963 glGenTextures(1, &texture); 964 glBindTexture(GL_TEXTURE_2D, texture); 965 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 966 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 967 initTexture(mMovie->bitmap()); 968 getTexCoordinate(); 969 970 if (!clearReg.isEmpty()) { 971 Region::const_iterator head(clearReg.begin()); 972 Region::const_iterator tail(clearReg.end()); 973 glEnable(GL_SCISSOR_TEST); 974 while (head != tail) { 975 const Rect& r(*head++); 976 glScissor(r.left, mHeight - r.bottom, 977 r.width(), r.height()); 978 glClear(GL_COLOR_BUFFER_BIT); 979 } 980 glDisable(GL_SCISSOR_TEST); 981 } 982 983 glVertexPointer(3, GL_FLOAT, 0, vertices); 984 glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords); 985 glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices); 986 987 eglSwapBuffers(mDisplay, mSurface); 988 989 nsecs_t now = systemTime(); 990 nsecs_t delay = frameDuration - (now - lastFrame); 991 lastFrame = now; 992 993 if (delay > 0) { 994 struct timespec spec; 995 spec.tv_sec = (now + delay) / 1000000000; 996 spec.tv_nsec = (now + delay) % 1000000000; 997 int err; 998 do { 999 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); 1000 } while (err<0 && errno == EINTR); 1001 } 1002 1003 checkExit(); 1004 glDeleteTextures(1, &texture); 1005 } 1006 1007 return false; 1008 } 1009 1010 // --------------------------------------------------------------------------- 1011 1012 } 1013 ; // namespace android