一、Android开机运行脚本流程

在Android启动的过程中,在kernel/init/main.c中的start_kernel->rest_init->kernel_init->init_post->run_init_process("/sbin/init")中启动了init相关脚本,

[plain] view plaincopy
  1. static noinline int init_post(void)
  2. 804{
  3. 805 /* need to finish all async __init code before freeing the memory */
  4. 806 async_synchronize_full();
  5. 807 free_initmem();
  6. 808 mark_rodata_ro();
  7. 809 system_state = SYSTEM_RUNNING;
  8. 810 numa_default_policy();
  9. 811
  10. 812 log_boot("Kernel_init_done");
  11. 813
  12. 814 current->signal->flags |= SIGNAL_UNKILLABLE;
  13. 815
  14. 816 if (ramdisk_execute_command) {
  15. 817     run_init_process(ramdisk_execute_command);
  16. 818     printk(KERN_WARNING "Failed to execute %s\n",
  17. 819             ramdisk_execute_command);
  18. 820 }
  19. 821
  20. 822 /*
  21. 823  * We try each of these until one succeeds.
  22. 824  *
  23. 825  * The Bourne shell can be used instead of init if we are
  24. 826  * trying to recover a really broken machine.
  25. 827  */
  26. 828 if (execute_command) {
  27. 829     run_init_process(execute_command);
  28. 830     printk(KERN_WARNING "Failed to execute %s.  Attempting "
  29. 831                 "defaults...\n", execute_command);
  30. 832 }
  31. 833 run_init_process("/sbin/init");
  32. 834 run_init_process("/etc/init");
  33. 835 run_init_process("/bin/init");
  34. 836 run_init_process("/bin/sh");
  35. 837
  36. 838 panic("No init found.  Try passing init= option to kernel. "
  37. 839       "See Linux Documentation/init.txt for guidance.");
  38. 840}
[plain] view plaincopy
  1. 794static void run_init_process(const char *init_filename)
  2. 795{
  3. 796 argv_init[0] = init_filename;
  4. 797 kernel_execve(init_filename, argv_init, envp_init);
  5. 798}

二、Android关机流程简介

看这个看完这篇博客关机流程分析,我们基本上对关机流程有一个初步的认识,现在我们往流程中插入shell脚本,使用和开机时候相类似的办法来做。

三、定位到jni层

首先在blog中我们了解到,在关机或者重启的时候最终会分别调用jni层的如下函数,路径为:

frameworks/base/services/jni/com_android_server_power_PowerManagerService.cpp

[plain] view plaincopy
  1. 196static void nativeShutdown(JNIEnv *env, jclass clazz) {
  2. 197    android_reboot(ANDROID_RB_POWEROFF, 0, 0);
  3. 198}
  4. 199
  5. 200static void nativeReboot(JNIEnv *env, jclass clazz, jstring reason) {
  6. 201    if (reason == NULL) {
  7. 202        android_reboot(ANDROID_RB_RESTART, 0, 0);
  8. 203    } else {
  9. 204        const char *chars = env->GetStringUTFChars(reason, NULL);
  10. 205        android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);
  11. 206        env->ReleaseStringUTFChars(reason, chars);  // In case it fails.
  12. 207    }
  13. 208    jniThrowIOException(env, errno);
  14. 209}

在上面代码中,我们发现不管是nativeShutdown 还是nativeReboot函数最终都调用了android_reboot函数。

四、进入android_reboot函数

对应路径:
     system/core/libcutils/android_reboot.c

[plain] view plaincopy
  1. int android_reboot(int cmd, int flags, char *arg)
  2. 105{
  3. 106    int ret;
  4. 107
  5. 108    if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
  6. 109        sync();
  7. 110
  8. 111    if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
  9. 112        remount_ro();
  10. 113
  11. 114    switch (cmd) {
  12. 115        case ANDROID_RB_RESTART:
  13. 116            ret = reboot(RB_AUTOBOOT);
  14. 117            break;
  15. 118
  16. 119        case ANDROID_RB_POWEROFF:
  17. 120            ret = reboot(RB_POWER_OFF);
  18. 121            break;
  19. 122
  20. 123        case ANDROID_RB_RESTART2:
  21. 124            ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
  22. 125                           LINUX_REBOOT_CMD_RESTART2, arg);
  23. 126            break;
  24. 127
  25. 128        default:
  26. 129            ret = -1;
  27. 130    }
  28. 131
  29. 132    return ret;
  30. 133}

在这个函数中,重启或者关机都进入这里,当然细心的童鞋,应该已经发现了,在这里面,switch对应的所有分支选择也都将进入reboot函数,reboot函数非常简单,如下所示路径:bionic/libc/unistd/reboot.c

[plain] view plaincopy
  1. 28#include <unistd.h>
  2. 29#include <sys/reboot.h>
  3. 30
  4. 31int reboot (int  mode)
  5. 32{
  6. 33    return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );
  7. 34}

因此,我们想要关机时候插入脚本的话,就可以选择在android_reboot函数或者在reboot函数中做一些愉快的操作。

五、插入脚本

1.需要点的技能点
          需要一些小知识如下:fork,execl族,shell脚本和.bin文件,相信大家的技能树上都有的。。。。

2.准备工作

(1)首先需要一个测试的脚本,名称为myclose:

[plain] view plaincopy
  1. #!/bin/sh
  2. echo "I am myclose.sh open"
  3. ./system/bin/vibrator_test
  4. echo "I am myclose.sh close"

(2)然后加入一个.bin文件,该文件的作用也就是控制震动马达震动10S,vibrator_test:

[plain] view plaincopy
  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #include <errno.h>
  12. int main()
  13. {
  14. int fd;
  15. int ret;
  16. char data[1];
  17. if((fd=open("/sys/class/timed_output/vibrator/vibr_on",O_WRONLY))==-1){
  18. printf("open memdev WRONG!\n");
  19. perror("open");
  20. }
  21. else
  22. printf("open memdev SUCCESS!\n");
  23. data[0] = '1';
  24. write(fd, &data,sizeof(data));
  25. sleep(10);
  26. data[0] = '0';
  27. write(fd, &data,sizeof(data));
  28. close(fd);
  29. return 0;
  30. }

3.修改android_reboot

对它的修改很简单,也就是首先使用fork生成一个子进程,然后用execl族取代子进程,运行myclose的脚本文件,父进程等待子进程执行完了之后,在继续剩下的关机流程,
注:不要使用vfork,这样会导致android_reboot传进来的参数cmd自己就发生变化,就算不操作cmd,求大神指导原因。。。。
修改后的android_reboot函数如下:

[plain] view plaincopy
  1. int android_reboot(int cmd, int flags, char *arg)
  2. {
  3. int ret;
  4. SLOGD("yulinghan i am here!!!!,cmd = %d",cmd);
  5. pid_t pc,pid;
  6. pid = getpid();
  7. pc = fork();
  8. if(pc<0){
  9. exit(1);
  10. }
  11. else if(pc == 0){
  12. SLOGD("yulinghan Child ID is %d,father id is %d,cmd = %d",getpid(),getppid(),cmd);
  13. execl("/system/bin/sh","sh","/system/bin/myclose",NULL);
  14. exit(0);
  15. }
  16. else{
  17. pid = waitpid(pc, NULL, 0);
  18. SLOGD("yulinghan I am father,my id is %d,cmd = %d",getpid(),cmd);
  19. if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
  20. sync();
  21. if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
  22. remount_ro();
  23. switch (cmd) {
  24. case ANDROID_RB_RESTART:
  25. SLOGD("yulinghan ANDROID_RB_RESTART");
  26. ret = reboot(RB_AUTOBOOT);
  27. break;
  28. case ANDROID_RB_POWEROFF:
  29. SLOGD("yulinghan ANDROID_RB_POWEROFF");
  30. ret = reboot(RB_POWER_OFF);
  31. break;
  32. case ANDROID_RB_RESTART2:
  33. SLOGD("yulinghan ANDROID_RB_RESTART2");
  34. ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
  35. LINUX_REBOOT_CMD_RESTART2, arg);
  36. break;
  37. default:
  38. SLOGD("yulinghan default\n");
  39. ret = -1;
  40. }
  41. return ret;
  42. }
  43. }

4.结果测试

(1)修改android_reboot之后重新编译,编译成库,push进手机或者直接编译系统都行。。
      (2)adb push 将脚本myclose和执行文件vibrator_test放到/system/bin/ 目录下,注意修改他们的执行权限。
      ( 3)执行reboot,测试效果如下:

(4)输入reboot命令之后,首先打印了 "I am myclose.sh open"
           然后开始执行 ./system/bin/vibrator_test
          手机在震动了10s之后,再打印了 "I am myclose.sh close",之后才重启。
   5.j结束语
        在加入了这个myclose脚本之后,如果想在关机流程中加入想执行的操作,直接将该操作加在myclose上面就好,相当的美妙。。

在Android关机中插入脚本相关推荐

  1. Android EditText中插入图片并响应点击事件

    EditText中插入图片基本就是两种方法: 1,通过Html.fromHtml(..)来实现[mw_shl_code=java,true]eText.append(Html.fromHtml(&qu ...

  2. 【android-tips】如何在android应用中插入百度广告(附源码)

    (转载请注明出处:http://blog.csdn.net/buptgshengod) 1.介绍    现在游戏中的广告基本上已经成为了游戏创作者的一个重要的收入来源.其实插入广告还是挺简单的,本文选 ...

  3. android应用中插入admob广告

    Step One  登陆admob,注册用户 直接登陆http://www.admob.com/,用google的账号登陆 Step Two 登陆admob后,在站点和应用程序选项中 选择并添加and ...

  4. 【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 拷贝 lib7zr.so 动态库头文件到 Android 工程中 | 配置 CMakeLists.txt 构建脚本 )

    文章目录 一.拷贝 p7zip 源码中的头文件到 Android Studio 项目中 二.配置 CMakeLists.txt 构建脚本 1.导入动态库 2.导入头文件 三.完整 CMakeLists ...

  5. Android插u盘自动执行,android tv box ---- 插入u盘直接播放指定文件夹中的视频

    android tv box ---- 插入u盘直接播放指定文件夹中的视频思路: 1.监听u盘插入广播 2.遍历指定目录下的所有文件,找到视频文件 3.将符合条件的文件加入播放集合中 4.循环播放 n ...

  6. Android对话框的高级设置《一》设置对话框按钮的图像和在内容文本中插入图像

    我们知道Android系统提供的对话框样式实在有些简陋,如果你的应用程序很华丽,再配上一个简陋的对话框,显得格格不入. SO.............我们可以通过反射技术来阻止对话框的关闭:设置对话框 ...

  7. android su 没有权限,android - 无法在需要SU权限的Termux中执行脚本 - 堆栈内存溢出...

    因此,我通常不发布信息,而是花费数小时在论坛上拖网寻找答案-但我完全不知所措. 我想做的事: 真的很简单,我想要一个可以自动更改OnePlus 5上MAC地址的脚本,我已经拥有执行此命令所需的所有命令 ...

  8. android编辑word,如何在Microsoft Word for Android中插入和编辑表 | MOS86

    虽然复杂的计算任务,图表创建和财务分析需要像Excel这样功能齐全的电子表格应用程序,但许多文本文档需要表格才能充分构建和显示数据.不用担心,Android用户:Microsoft Word在您最喜欢 ...

  9. u盘里android文件夹作用,Android应用开发android tv box ---- 插入u盘直接播放指定文件夹中的视频...

    本文将带你了解Android应用开发android tv box ---- 插入u盘直接播放指定文件夹中的视频,希望本文对大家学Android有所帮助. android tv box ---- 插入u ...

最新文章

  1. 工作project里的Verilog记录
  2. xss实例-输出在script/script之间的情况
  3. 学长毕业日记 :本科毕业论文写成博士论文的神操作20170411
  4. sql查询百分之20到百分之40的数据_数据库基础学习——SQL语言知识总结(6)
  5. mysql单单写join_MySQL系列之Join大法
  6. ASP.NET2.0导出Word文档(C#导出DOC)
  7. EasyDSS RTMP流媒体解决方案之直播录像自动清理方案
  8. Mybatis的resultMap自定义映射
  9. 网页中插入当前时间和实时天气
  10. 园区人工智能开启双创模式,“1+N”创新型组织发展成效初显
  11. java 退格符,Java退格键
  12. PC端工具 WP7 PC端截图工具WP7 Screen recorder 发布 附使用教程
  13. MLCC(贴片)电容啸叫分析
  14. 零基础小白怎么自学UI设计?自学UI设计有什么方法?
  15. 如何实时抓取动态网页数据?
  16. Photoshop文字特效——炫彩效果文字
  17. EFR32MG21 with ADXL346
  18. 网赚最忌讳的行为5个行为,新人必读!
  19. COSCon'22 论坛集锦 1+16个论坛就等你了!
  20. 词云中去重复的词_如何用精准蓝海词做新品标题,上架即上首页!

热门文章

  1. 开源经济模型 MAKRO
  2. JavaScript开发环境Aptana
  3. mysql 自定义函数教程_Mysql 自定义函数
  4. Linux学习笔记 -- 日志管理
  5. 深度学习 --- 优化入门一(梯度下降所面临的问题)
  6. 同一个事务里面对同一条数据做2次修改_MySQL事务与MVCC如何实现的隔离级别
  7. java获取反射机制的三种方式
  8. 小程序正式发布后,打开白屏(已解决)
  9. pythongui界面实例_wxPython:python首选的GUI库实例分享(5)
  10. jvisualvm/Jconsole监控WAS(WebSphere)中间件