【android】【Bootanimation】Bootanimation---启动和退出

本文详细解析了Android系统中开机动画(bootanimation)的启动和退出过程,包括服务配置、启动机制、关键API使用以及退出条件。通过理解这些细节,读者可以更好地掌握Android系统的初始化流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


  • 题序
     生命的开始意味着新奇,而生命的结束则多少会带来感伤与怀念,亲人的离去则是更多的痛彻心扉,以及无尽的怀念。愿逝者长眠,生者安好。
     生命有很多的长度,有些人来了,从不离开,而有些人来了,走了,再也不回头,不留下一丝的痕迹。bootanimation即是如此。
  • Bootanimation的启动
     Android kk版本中,在编译frameworke/base/cmds/bootanimation之后,会在out/target/product/device/system/bin目录下面生成一个名为bootanimation的bin档。
     而在对应的init.rc中会通过如下的service来启动boot animation。
     service bootanim /system/bin/bootanimation
          class main
          user graphics
          group graphics
          disabled
          oneshot

     其中:
      class <name> # 设置名称为name的类别,感觉有点像开机启动service的优先级,默认的class名称为default
   user <effectuserid> # 设置服务进程的effective user ID
      group <groupname> [ <groupname> ]* # 设置服务进程的effective group ID(第一个参数)和supplementary group IDs(第二个到最后)
      disabled # 设置后,不能自动地通过class名称启动,必须显式地通过service名称启动,或是 表示init进程创建只是创建它,但不立刻执行。
     oneshot# 选项表示该服务只启动一次,而如果没有oneshot选项,这个可执行程序会一直存在---如果可执行程序被杀死,则会重新启动。
    其实在这个时候,因为设置了bootanim的属性为disabled的,这就意味着在init.c中,只是创建了bootanim这个service,但是其实并没有去启动他。那么bootanim到底在什么时候启动呢。
     还是要回到init的概念中, Android系统在init.rc中定义了很多Service,具体定义格式可以参考《Android Platform Developer’s Guide》中的“Android Init Language”。Init.rc中定义的Service将会被Init进程创建,其中已经定义的服务就包含bootanimation。  每一项服务必须在/init.rc中定义.Android系统启动时,init守护进程将解析init.rc和启动属性服务,属性“ ctl.start ”和“ctl.stop ”是用来启动和停止服务的。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“ init.svc.<服务名>“属性中 。
     也就是说启动bootanim必须显式调用ctrl.start,bootanim才能够开始启动,这就是disabled这个属性的神奇之所在。
     在surfaceFlinger.cpp中,surfaceFlinger init()的时候,会通过调用startBootAnim()来启动bootanima service。
#startBootAnim() @ surfaceFlinger.cpp
void SurfaceFlinger::startBootAnim(){
     property_set("service.bootanim.exit","0");
     property_set("ctl.start","bootanim");
}
     还记不记得在init.c的main()函数中,在完全所有的初始化,如创建文件系统,解析init.rc,初始化property workspace等之后,进入了一个死循环。这个循环其实是在等待事件,如property setting,signal 及keychord等。
#main() @ init.c
void main()
{
     .....
     for(;;){
          .....
          for(i = 0; i < fd_count; i++)
          {     
               if(ufds[i].revents == POLLIN)
               {
                    if(ufds[i].fd == get_property_set_fd())
                         handle_property_set_fd();
                    else if( ufds[i].fd == get_keychord_fd())
                         handle_keychord();
                    else if ( ufds[i].fd == get_signal_fd())
                    handle_signale();
               }
          }
     }
     return 0;
}
     ok,到这儿之后,咱们再回到bootanim来。其实对于bootanim的最先入口,就是bootanimation_main().cpp中的main()函数。
#main() @ bootanimation_main.cpp
  1. int main(int argc, char** argv)  
  2. {  
  3. #if defined(HAVE_PTHREADS)  
  4.     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);  
  5. #endif  
  6.     char value[PROPERTY_VALUE_MAX];  
  7.     property_get("debug.sf.nobootanimation", value, "0");  
  8.     int noBootAnimation = atoi(value);  
  9.     LOGI_IF(noBootAnimation,  "boot animation disabled");  
  10.     if (!noBootAnimation) {  
  11.         sp<ProcessState> proc(ProcessState::self());  
  12.         ProcessState::self()->startThreadPool();  
  13.         sp<BootAnimation> boot = new BootAnimation();  
  14.   
  15.         IPCThreadState::self()->joinThreadPool();  
  16.   
  17.     }  
  18.     return 0;  
  19. }  
     bootanimation.cpp继承于Thread类,thread的启动及执行过程按下不表。
     当然,还有一种情况也会导致bootnimation启动,即当surfaceFlinger死掉的时候:
# binderDied() @ SurfaceFlinger.cpp
void SurfaceFlinger::binderDied(const wp<IBinder>& who)
{
     initializeDisplay();
     startBootAnim();
}
     自此,bootanimation的启动过程就厘清咯。我们在下一节中看看是怎么退出的。
  •      Bootanimtion的退出
     通读source code可以知道,不管是movie()模式还是android()模式,在每一次循环之后,都会调用一个api函数checkExit(),用来检测是否需要退出bootanimation
# checkExit() @ bootanimation.cpp
#define  EXIT_PROP_NAME "service.bootanim.exit"
void BootAnimation::checkExit() {
     char value[PROPERTY_VALUE_MAX];

property_get(EXIT_PROP_NAME, value, "0");//EXIT_PROP_NAME为字符串 service.bootanim.exit

int exitnow = atoi(value);

if (exitnow) {

     requestExit();

     }
}
     在android的thread类提供的方法中,有一个曰为requestexit()的api接口,其介绍如下:
      virtual void requestExit();  //ask this object's thread to exit,asynchronous,this function can be called in other thread
     从上面CheckExit的实现中,可以看到,要能够执行RequestExit(),需要"service.bootanim.exit"的属性设置成1。
     那么这个属性在启动的过程中,已经把这个属性设置成0咯,那么又是在哪个地方将其设置成1呢。
     这个其实也是surfaceFlinger干的事情。
# bootFinished() @ surfaceFlinger.cpp
void SurfaceFlinger::bootFinished()
{
     .....
     property_set("service.bootanim.exit","1");
}
     android的thread还提供了一个额外的api函数exitPending,用来查看是否执行退出正常。
      bool exitPending() const;    //returns true if requestExit () has been called
     也就是说如果requestExit()成功,则退出,否则再做一次循环。
     当然,bootanimation也存在异常退出的情况,就是binder died。
# binderDied() @ BootAnimation.cpp
void BootAnimation::binderDied(const wp<IBinder>& who)
{
     kill(getpid(),SIGKILL);
     requesetExit();
}
参考文献:
【2】http://www.tuicool.com/articles/raIFvq
<think>嗯,用户的问题是关于Android R系统中提前退出开机视频的解决方案。首先,我需要回忆一下之前提供的引用内容,特别是引用[1]中提到的海思平台的开机视频模块,以及Android原生bootanimation的代码路径。用户现在的问题是如何在Android R系统上提前结束开机动画或视频,可能是在系统启动过程中跳过或缩短这个阶段。 首先,我应该考虑Android系统的开机动画机制。通常,Android使用bootanimation服务来播放开机动画,这个服务位于frameworks/base/cmds/bootanimation。如果是海思平台,可能会有自定义的模块,比如hibootvideo。用户可能是在这个模块中需要调整,或者是在原生的bootanimation中修改。 用户提到的“提前退出”可能意味着在某个条件满足时,比如系统准备就绪,就立即停止播放开机视频。因此,解决方案可能涉及修改bootanimation或hibootvideo的代码,使其在系统启动到一定阶段后主动退出。 接下来,我需要考虑如何检测系统是否准备就绪。在Android中,系统服务启动完成后会发送ACTION_BOOT_COMPLETED广播,但开机动画可能在系统完全启动前就已经结束。不过,或许可以通过检查某个系统属性或者服务状态来判断是否应该退出开机视频。 另外,引用[1]中提到海思的hibootvideo模块,可能需要在该模块中添加退出逻辑。例如,在播放视频的循环中,定期检查系统是否已经到达某个阶段,如果是,则终止播放进程。 还需要考虑权限问题,修改系统级的动画服务可能需要系统签名或者root权限,用户可能需要在自己的设备上有相应的权限才能应用这些修改。 可能还需要调整启动顺序,确保开机视频模块在系统服务启动之前运行,但同时能够及时收到停止的信号。比如,在init.rc中调整服务的启动顺序,或者添加依赖关系。 此外,参考用户之前的问题,他们可能已经尝试过某些方法但未成功,所以需要提供具体的代码修改示例,比如修改BootAnimation.cpp中的主循环,添加退出条件检查。 最后,要确保提供的解决方案适用于Android R(即Android 11),因为不同版本的Android可能在启动流程上有差异,需要确认代码路径系统属性的兼容性。</think>根据Android系统开机视频机制分析,针对Android R系统提前退出开机视频的需求,可通过以下方案实现: ### 一、核心实现原理 Android系统通过$bootanimation$服务控制开机视频播放,其生命周期与以下两个条件绑定: $$ \text{退出条件} = (SurfaceFlinger服务就绪) \ \&\& \ (system\_server进程启动完成) $$ 当满足任意条件时,$bootanimation$进程会主动退出[^1] ### 二、具体实现步骤 1. **修改动画播放逻辑** ```cpp // frameworks/base/cmds/bootanimation/BootAnimation.cpp void BootAnimation::checkExitConditions() { // 增加提前退出判断条件 if (property_get_bool("sys.bootanim.exit_early", false)) { exitIfNeeded(); } // 原检测逻辑保持不变... } ``` 2. **添加系统属性控制** ```xml <!-- device/<vendor>/<device>/system.prop --> sys.bootanim.duration=0 # 强制设置动画持续时间为0秒 sys.bootvideo.early_exit=1 ``` 3. **调整服务启动顺序** ```rc # vendor/etc/init/hibootvideo.rc service hibootvideo /vendor/bin/hibootvideo class core user graphics group graphics disabled oneshot on property:sys.boot_completed=1 stop hibootvideo # 系统启动完成时强制停止服务 ``` ### 三、关键配置优化 1. **视频帧率控制** 在$vendor/hisilicon/modules/hibootvideo/main.cpp$中增加: ```cpp // 设置最大播放时长(单位:秒) #define MAX_PLAY_TIME 5 if(elapsed_time >= MAX_PLAY_TIME) exit(0); ``` 2. **系统服务同步检测** ```java // frameworks/base/services/core/java/com/android/server/SystemServiceManager.java public void startBootPhase(final int phase) { if(phase == PHASE_BOOT_COMPLETED){ SystemProperties.set("sys.bootanim.exit_early", "true"); } } ``` ### 四、验证方法 1. 通过ADB命令实时监控: ```bash adb shell "while true; do ps | grep bootanim; sleep 0.5; done" ``` 2. 查看内核日志确认退出时机: ```bash adb logcat | grep -E 'BootAnimation|HibootVideo' ``` **注意事项**: 1. 需要系统级签名权限才能修改bootanimation相关代码 2. 海思平台需同步修改hibootvideo模块的退出逻辑[^1] 3. 修改后需重新编译boot.img并刷机验证
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值