1、修改Android的开关机铃声


待续……


2、修改Android开关机画面

开机画面包括三个过程

2.1、bootloader的开机画面

待续……

2.2、Android系统init时的开机画面





2.2.1、Android系统init时,装载initlogo.rle的简单流程。

Androidinit时,会读取 /initlogo.rle文件,如果读取成功,就会在/dev/graphics/fb0显示initlogo.rle;如果读取失败,打开/dev/tty0,输出文本“A N D R I O D”字样。

相关代码:

/system/core/init/init.c
/system/core/init/init.h
/system/core/init/init.rc
/system/core/init/logo.c

@/system/core/init/init.c


  1. static int console_init_action(int nargs, char **args)  {      int fd;      char tmp[PROP_VALUE_MAX];        if (console[0]) {          snprintf(tmp, sizeof(tmp), "/dev/%s", console);          console_name = strdup(tmp);      }        fd = open(console_name, O_RDWR);      if (fd >= 0)          have_console = 1;      close(fd);        if( load_565rle_image(INIT_IMAGE_FILE) ) {//在init.h文件定义                 //#define INIT_IMAGE_FILE    "/initlogo.rle"              fd = open("/dev/tty0", O_WRONLY);                   if (fd >= 0) {//如果找不到initlog.rle图片,则打开TEXT模式,              const char *msg;                  msg = "\n"              "\n"              "\n"              "\n"              "\n"              "\n"              "\n"  // console is 40 cols x 30 lines              "\n"              "\n"              "\n"              "\n"              "\n"              "\n"              "\n"              "             A N D R O I D ";//打印ANDROID字样的问题。              write(fd, msg, strlen(msg));              close(fd);          }      }      return 0;  }  




@/system/core/init/logo.c

static int fb_open(struct FB *fb)  {      fb->fd = open("/dev/graphics/fb0", O_RDWR);//会在/dev/graphics/fb0显示initlogo.rle      if (fb->fd < 0)          return -1;        if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0)          goto fail;      if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0)          goto fail;        fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE,                       MAP_SHARED, fb->fd, 0);      if (fb->bits == MAP_FAILED)          goto fail;        return 0;    fail:      close(fb->fd);      return -1;  }    /************部分省略****************/          /* 565RLE image format: [count(2 bytes), rle(2 bytes)] */    int load_565rle_image(char *fn)  {      struct FB fb;      struct stat s;      unsigned short *data, *bits, *ptr;      unsigned count, max;      int fd;        if (vt_set_mode(1))           return -1;        fd = open(fn, O_RDONLY);      if (fd < 0) {          ERROR("cannot open '%s'\n", fn);          goto fail_restore_text;      }        if (fstat(fd, &s) < 0) {          goto fail_close_file;      }        data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);      if (data == MAP_FAILED)          goto fail_close_file;        if (fb_open(&fb))          goto fail_unmap_data;        max = fb_width(&fb) * fb_height(&fb);      ptr = data;      count = s.st_size;      bits = fb.bits;      while (count > 3) {          unsigned n = ptr[0];          if (n > max)              break;          android_memset16(bits, ptr[1], n << 1);          bits += n;          max -= n;          ptr += 2;          count -= 4;      }        munmap(data, s.st_size);      fb_update(&fb);      fb_close(&fb);      close(fd);      unlink(fn);      return 0;    fail_unmap_data:      munmap(data, s.st_size);      fail_close_file:      close(fd);  fail_restore_text:      vt_set_mode(0);      return -1;  }  



2.2.2、修改方法:

2.2.2.1、找到一张符合机器分辨率的bmp图像,把bmp图片转换成为raw图像

要注意分辨率问题,若是不符合机器分辨率,可能显示拉伸或者花屏之类等等各种情况。

使用到的工具imagemagick,若没有,用apt安装即可。


  1. convert-depth8initlogo.bmprgb:initlogo.raw

2.2.2.2、把raw图像转换为rle图像即可。


使用的工具rgb2565,编译Android系统源代码成功时,最红再编译SDK(执行make PRODUCT-sdk-sdk),编译SDK成功之后,在\out\host\linux-x86\bin生成rgb2565。然后在rgb2565目录下执行如下命令


  1. ./rgb2565-rle<initlogo.raw>initlogo.rle

2.2.2.3、替换文件

若是想在虚拟机上面测试,当系统编译完成之后,把initlogo.rle文件copy到\out\target\product\generic\root目录下,然后把\out\target\product\generic的ramdisk.img删除掉,再执行以下make命令,就可以生成新的ramdisk.img了,把ramdisk.img替代虚拟机镜像的ramdisk.img目录即可。因为root目录是ramdisk.img解包之后的文件夹,这一步只是把rle文件打包到ramdisk.img里面。

若是在一些机器的SDK修改开机画面,则可以到devices目录下的相应芯片厂商那里找找mk文件,然后编辑

如tcc892X是如下路径

\device\telechips\tcc8920st\device_base.mk

修改或者添加为


  1. PRODUCT_COPY_FILES+=\
  2. device/telechips/common/initlogo_conowen.rle:root/initlogo.rle

事实上,这就是一个copy的过程,和之前的添加第三方apk没啥区别。

2.3、Android系统最后的开机动画(类似windows的进度条)

相关代码:

frameworks\base\cmds\bootanimation\BootAnimation.cpp

frameworks\base\cmds\bootanimation\BootAnimation.h

2.3.1、Android开机动画有两种方式,一种是系统的默认开机动画,由两张png图片构成,由代码控制背景图片的移动,造成动画效果;

相关资源

frameworks\base\core\res\assets\images\android-logo-mask.png
Android默认开机动画的前景图片,文字部分镂空,尺寸256×64

\frameworks\base\core\res\assets\images\android-logo-shine.png

Android默认开机动画的背景图片,尺寸512×64

2.3.2、另外一种是用户自定义的动画,动画打包为一个bootanimation.zip文件,存储在以下地方。

[cpp] view plain copy
  1. //来自Bootanimation.cpp的宏定义
  2. #defineUSER_BOOTANIMATION_FILE"/data/local/bootanimation.zip"
  3. #defineSYSTEM_BOOTANIMATION_FILE"/system/media/bootanimation.zip"
  4. #defineSYSTEM_ENCRYPTED_BOOTANIMATION_FILE"/system/media/bootanimation-encrypted.zip"

系统会先读取上述路径,查询是否存在bootanimation.zip文件,并且可以成功加载。若是都成立,系统的开机动画则是用户自定义的bootanimation.zip开机方式。否则采用系统默认的开机动画。

2.3.3、开机动画的函数实现流程。

首先,BootAnimation里面的BootAnimation类继承thread类,开始时,由系统调用BootAnimation类的成员函数onFirstRef(),在这个函数里面主要是调用了父类Thread的成员函数run,然后就会创建一个新的线程。

void BootAnimation::onFirstRef() {      status_t err = mSession->linkToComposerDeath(this);      LOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));      if (err == NO_ERROR) {          run("BootAnimation", PRIORITY_DISPLAY);//开始新的线程      }  }  


线程开始运行时,会调用BootAnimation类的成员函数readyToRun()来作一些初始化工作,如读取给定路径的bootanimation.zip。

status_t BootAnimation::readyToRun() {      mAssets.addDefaultAssets();        DisplayInfo dinfo;      status_t status = session()->getDisplayInfo(0, &dinfo);      if (status)          return -1;        // create the native surface      sp<SurfaceControl> control = session()->createSurface(              0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);        SurfaceComposerClient::openGlobalTransaction();      control->setLayer(0x40000000);      SurfaceComposerClient::closeGlobalTransaction();        sp<Surface> s = control->getSurface();        // initialize opengl and egl      const EGLint attribs[] = {              EGL_RED_SIZE,   8,              EGL_GREEN_SIZE, 8,              EGL_BLUE_SIZE,  8,              EGL_DEPTH_SIZE, 0,              EGL_NONE      };      EGLint w, h, dummy;      EGLint numConfigs;      EGLConfig config;      EGLSurface surface;      EGLContext context;        EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);        eglInitialize(display, 0, 0);      eglChooseConfig(display, attribs, &config, 1, &numConfigs);      surface = eglCreateWindowSurface(display, config, s.get(), NULL);      context = eglCreateContext(display, config, NULL, NULL);      eglQuerySurface(display, surface, EGL_WIDTH, &w);      eglQuerySurface(display, surface, EGL_HEIGHT, &h);        if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)          return NO_INIT;        mDisplay = display;      mContext = context;      mSurface = surface;      mWidth = w;      mHeight = h;      mFlingerSurfaceControl = control;      mFlingerSurface = s;        mAndroidAnimation = true;//默认是采用系统的默认开机动画,所以mAndroidAnimation默认为true        // If the device has encryption turned on or is in process       // of being encrypted we show the encrypted boot animation.      char decrypt[PROPERTY_VALUE_MAX];      property_get("vold.decrypt", decrypt, "");        bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);        if ((encryptedAnimation &&              (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&              (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||                ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&              (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||                ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&              (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {          mAndroidAnimation = false;//若成功读取到bootanimation.zip文件,标志位为false,也就是采用用户自定义的动画方案      }        return NO_ERROR;  }  


之后再调用BootAnimation类的成员函数threadLoop()来显示Android系统的开机动画。

bool BootAnimation::threadLoop()  {      bool r;      if (mAndroidAnimation) {//由mAndroidAnimation这个标志位来决定到底播放哪一种          r = android();//播放系统默认的动画      } else {          r = movie();//播放用户自定义的动画      }        eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);      eglDestroyContext(mDisplay, mContext);      eglDestroySurface(mDisplay, mSurface);      mFlingerSurface.clear();      mFlingerSurfaceControl.clear();      eglTerminate(mDisplay);      IPCThreadState::self()->stopProcess();      return r;  }    bool BootAnimation::android()  {      initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");      initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");//读取默认开机动画的两张png图片        // clear screen      glShadeModel(GL_FLAT);      glDisable(GL_DITHER);      glDisable(GL_SCISSOR_TEST);      glClearColor(0,0,0,1);      glClear(GL_COLOR_BUFFER_BIT);      eglSwapBuffers(mDisplay, mSurface);        glEnable(GL_TEXTURE_2D);      glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);        const GLint xc = (mWidth  - mAndroid[0].w) / 2;      const GLint yc = (mHeight - mAndroid[0].h) / 2;      const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);        glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),              updateRect.height());        // Blend state      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);      glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);        const nsecs_t startTime = systemTime();      do {          nsecs_t now = systemTime();          double time = now - startTime;          float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;          GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;          GLint x = xc - offset;            glDisable(GL_SCISSOR_TEST);          glClear(GL_COLOR_BUFFER_BIT);            glEnable(GL_SCISSOR_TEST);          glDisable(GL_BLEND);          glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);          glDrawTexiOES(x,                 yc, 0, mAndroid[1].w, mAndroid[1].h);          glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);            glEnable(GL_BLEND);          glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);          glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);            EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);          if (res == EGL_FALSE)              break;            // 12fps: don't animate too fast to preserve CPU          const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);          if (sleepTime > 0)              usleep(sleepTime);      } while (!exitPending());        glDeleteTextures(1, &mAndroid[0].name);      glDeleteTextures(1, &mAndroid[1].name);      return false;  }      bool BootAnimation::movie()  {      ZipFileRO& zip(mZip);        size_t numEntries = zip.getNumEntries();      ZipEntryRO desc = zip.findEntryByName("desc.txt");      FileMap* descMap = zip.createEntryFileMap(desc);      LOGE_IF(!descMap, "descMap is null");      if (!descMap) {          return false;      }        String8 desString((char const*)descMap->getDataPtr(),              descMap->getDataLength());      char const* s = desString.string();        Animation animation;        // Parse the description file      for (;;) {          const char* endl = strstr(s, "\n");          if (!endl) break;          String8 line(s, endl - s);          const char* l = line.string();          int fps, width, height, count, pause;          char path[256];          if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {              //LOGD("> w=%d, h=%d, fps=%d", fps, width, height);              animation.width = width;              animation.height = height;              animation.fps = fps;          }          if (sscanf(l, "p %d %d %s", &count, &pause, path) == 3) {              //LOGD("> count=%d, pause=%d, path=%s", count, pause, path);              Animation::Part part;              part.count = count;              part.pause = pause;              part.path = path;              animation.parts.add(part);          }          s = ++endl;      }        // read all the data structures      const size_t pcount = animation.parts.size();      for (size_t i=0 ; i<numEntries ; i++) {          char name[256];          ZipEntryRO entry = zip.findEntryByIndex(i);          if (zip.getEntryFileName(entry, name, 256) == 0) {              const String8 entryName(name);              const String8 path(entryName.getPathDir());              const String8 leaf(entryName.getPathLeaf());              if (leaf.size() > 0) {                  for (int j=0 ; j<pcount ; j++) {                      if (path == animation.parts[j].path) {                          int method;                          // supports only stored png files                          if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) {                              if (method == ZipFileRO::kCompressStored) {                                  FileMap* map = zip.createEntryFileMap(entry);                                  if (map) {                                      Animation::Frame frame;                                      frame.name = leaf;                                      frame.map = map;                                      Animation::Part& part(animation.parts.editItemAt(j));                                      part.frames.add(frame);                                  }                              }                          }                      }                  }              }          }      }        // clear screen      glShadeModel(GL_FLAT);      glDisable(GL_DITHER);      glDisable(GL_SCISSOR_TEST);      glDisable(GL_BLEND);      glClearColor(0,0,0,1);      glClear(GL_COLOR_BUFFER_BIT);        eglSwapBuffers(mDisplay, mSurface);        glBindTexture(GL_TEXTURE_2D, 0);      glEnable(GL_TEXTURE_2D);      glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);      glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);      glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);      glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);      glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);        const int xc = (mWidth - animation.width) / 2;      const int yc = ((mHeight - animation.height) / 2);      nsecs_t lastFrame = systemTime();      nsecs_t frameDuration = s2ns(1) / animation.fps;        Region clearReg(Rect(mWidth, mHeight));      clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));        for (int i=0 ; i<pcount && !exitPending() ; i++) {          const Animation::Part& part(animation.parts[i]);          const size_t fcount = part.frames.size();          glBindTexture(GL_TEXTURE_2D, 0);            for (int r=0 ; !part.count || r<part.count ; r++) {              for (int j=0 ; j<fcount && !exitPending(); j++) {                  const Animation::Frame& frame(part.frames[j]);                    if (r > 0) {                      glBindTexture(GL_TEXTURE_2D, frame.tid);                  } else {                      if (part.count != 1) {                          glGenTextures(1, &frame.tid);                          glBindTexture(GL_TEXTURE_2D, frame.tid);                          glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);                          glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);                      }                      initTexture(                              frame.map->getDataPtr(),                              frame.map->getDataLength());                  }                    if (!clearReg.isEmpty()) {                      Region::const_iterator head(clearReg.begin());                      Region::const_iterator tail(clearReg.end());                      glEnable(GL_SCISSOR_TEST);                      while (head != tail) {                          const Rect& r(*head++);                          glScissor(r.left, mHeight - r.bottom,                                  r.width(), r.height());                          glClear(GL_COLOR_BUFFER_BIT);                      }                      glDisable(GL_SCISSOR_TEST);                  }                  glDrawTexiOES(xc, yc, 0, animation.width, animation.height);                  eglSwapBuffers(mDisplay, mSurface);                    nsecs_t now = systemTime();                  nsecs_t delay = frameDuration - (now - lastFrame);                  lastFrame = now;                  long wait = ns2us(frameDuration);                  if (wait > 0)                      usleep(wait);              }              usleep(part.pause * ns2us(frameDuration));          }            // free the textures for this part          if (part.count != 1) {              for (int j=0 ; j<fcount ; j++) {                  const Animation::Frame& frame(part.frames[j]);                  glDeleteTextures(1, &frame.tid);              }          }      }        return false;  }  


2.3.4、制作bootanimation.zip

拿CM7的bootanimation.zip的做个例子,首先解压做个zip文件。

2.3.4.1、

可以发现里面由两个文件夹和一个desc.txt(固定文件名)文档构成的


  1. 48048024
  2. p10android
  3. p00part1

第一行的三个数字分别表示开机动画在屏幕中的显示宽度、高度以及帧速(fps)(每秒钟传输的图片的数量,若是24,表示一秒钟有24张图片刷新,每一帧图片的停留时间为1/24秒)。

接下来的行定义是一样的,后面的有多少个文件夹,就接来下就写多少行来定义文件夹里面的图片就行。

第1个参数:标志符:
必须是: p


第2个参数:文件夹的图片完全播放完的循环次数:
0 : 表示本文件夹里面的图片无限循环


第3个参数:每一个循环的间隔时间:
单位是一个帧的持续时间,比如帧数是24,那么帧的持续时间就是1秒/24 。
若第3个参数为10表示————以帧数24fps播放完了android文件夹的文件,然后等待10个帧的持续时间【也就是10*(1/24)】,然后在以24fps来重复播放这个文件夹的下面的图片。以此类推。

若第3个参数为0表示————每次循环的间隔时间为0

第4个参数:文件夹名称
文件夹中的图片文件的加载刷新按文件名的名称排序。

2.3.4.2、制作


建立文件夹bootanimation,然后在里面按照规范建立desc.txt文件,把图片文件夹拖进去bootanimation文件夹里面。注意图片的文件名的顺序。

在linux下面执行以下命令即可。


  1. zip-0bootanimation.zipandroid/*pngpart1/*pngdesc.txt

zip -0表示无压缩

也可以在windows下面用rar软件打包为zip,压缩标准选择为存储就行。(不压缩)

然后就生成了bootanimation.zip

更多相关文章

  1. Android窗口抖动之动画实现
  2. Android(安卓)动画 Activity切换动画
  3. Android创建和配置布局动画
  4. android 图片按照动画不停移动
  5. Android(安卓)Dialog设置动画
  6. Android应用程序启动画面
  7. android的动画实例
  8. Android使用xml中定义的动画效果
  9. Android(安卓)有入场动画的Popuwindow

随机推荐

  1. 真机调式
  2. Android有用代码片段(三)
  3. Android(安卓)Activity生命周期--应知应
  4. Android各版本适配之8.0
  5. Android截屏
  6. Android中手机震动的设置(Vibrator)的步骤(A
  7. Android(安卓)4.0 开发者指南(28) —— R
  8. Android寮€鍙戦」鐩疄璁璂ay_2
  9. CactiPhone: 移动设备上查看Cacti
  10. 【起航计划 016】2015 起航计划 Android(