在Android关机中插入脚本
来源:互联网 发布:centos一键smtp 编辑:程序博客网 时间:2024/05/01 18:51
一、Android开机运行脚本流程
在Android启动的过程中,在kernel/init/main.c中的start_kernel->rest_init->kernel_init->init_post->run_init_process("/sbin/init")中启动了init相关脚本,
- static noinline int init_post(void)
- 804{
- 805 /* need to finish all async __init code before freeing the memory */
- 806 async_synchronize_full();
- 807 free_initmem();
- 808 mark_rodata_ro();
- 809 system_state = SYSTEM_RUNNING;
- 810 numa_default_policy();
- 811
- 812 log_boot("Kernel_init_done");
- 813
- 814 current->signal->flags |= SIGNAL_UNKILLABLE;
- 815
- 816 if (ramdisk_execute_command) {
- 817 run_init_process(ramdisk_execute_command);
- 818 printk(KERN_WARNING "Failed to execute %s\n",
- 819 ramdisk_execute_command);
- 820 }
- 821
- 822 /*
- 823 * We try each of these until one succeeds.
- 824 *
- 825 * The Bourne shell can be used instead of init if we are
- 826 * trying to recover a really broken machine.
- 827 */
- 828 if (execute_command) {
- 829 run_init_process(execute_command);
- 830 printk(KERN_WARNING "Failed to execute %s. Attempting "
- 831 "defaults...\n", execute_command);
- 832 }
- 833 run_init_process("/sbin/init");
- 834 run_init_process("/etc/init");
- 835 run_init_process("/bin/init");
- 836 run_init_process("/bin/sh");
- 837
- 838 panic("No init found. Try passing init= option to kernel. "
- 839 "See Linux Documentation/init.txt for guidance.");
- 840}
- 794static void run_init_process(const char *init_filename)
- 795{
- 796 argv_init[0] = init_filename;
- 797 kernel_execve(init_filename, argv_init, envp_init);
- 798}
二、Android关机流程简介
看这个看完这篇博客关机流程分析,我们基本上对关机流程有一个初步的认识,现在我们往流程中插入shell脚本,使用和开机时候相类似的办法来做。
三、定位到jni层
首先在blog中我们了解到,在关机或者重启的时候最终会分别调用jni层的如下函数,路径为:
frameworks/base/services/jni/com_android_server_power_PowerManagerService.cpp
- 196static void nativeShutdown(JNIEnv *env, jclass clazz) {
- 197 android_reboot(ANDROID_RB_POWEROFF, 0, 0);
- 198}
- 199
- 200static void nativeReboot(JNIEnv *env, jclass clazz, jstring reason) {
- 201 if (reason == NULL) {
- 202 android_reboot(ANDROID_RB_RESTART, 0, 0);
- 203 } else {
- 204 const char *chars = env->GetStringUTFChars(reason, NULL);
- 205 android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);
- 206 env->ReleaseStringUTFChars(reason, chars); // In case it fails.
- 207 }
- 208 jniThrowIOException(env, errno);
- 209}
四、进入android_reboot函数
对应路径:
system/core/libcutils/android_reboot.c
- int android_reboot(int cmd, int flags, char *arg)
- 105{
- 106 int ret;
- 107
- 108 if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
- 109 sync();
- 110
- 111 if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
- 112 remount_ro();
- 113
- 114 switch (cmd) {
- 115 case ANDROID_RB_RESTART:
- 116 ret = reboot(RB_AUTOBOOT);
- 117 break;
- 118
- 119 case ANDROID_RB_POWEROFF:
- 120 ret = reboot(RB_POWER_OFF);
- 121 break;
- 122
- 123 case ANDROID_RB_RESTART2:
- 124 ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- 125 LINUX_REBOOT_CMD_RESTART2, arg);
- 126 break;
- 127
- 128 default:
- 129 ret = -1;
- 130 }
- 131
- 132 return ret;
- 133}
在这个函数中,重启或者关机都进入这里,当然细心的童鞋,应该已经发现了,在这里面,switch对应的所有分支选择也都将进入reboot函数,reboot函数非常简单,如下所示路径:bionic/libc/unistd/reboot.c
- 28#include <unistd.h>
- 29#include <sys/reboot.h>
- 30
- 31int reboot (int mode)
- 32{
- 33 return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );
- 34}
五、插入脚本
1.需要点的技能点
需要一些小知识如下:fork,execl族,shell脚本和.bin文件,相信大家的技能树上都有的。。。。
2.准备工作
(1)首先需要一个测试的脚本,名称为myclose:
- #!/bin/sh
- echo "I am myclose.sh open"
- ./system/bin/vibrator_test
- echo "I am myclose.sh close"
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- int main()
- {
- int fd;
- int ret;
- char data[1];
- if((fd=open("/sys/class/timed_output/vibrator/vibr_on",O_WRONLY))==-1){
- printf("open memdev WRONG!\n");
- perror("open");
- }
- else
- printf("open memdev SUCCESS!\n");
- data[0] = '1';
- write(fd, &data,sizeof(data));
- sleep(10);
- data[0] = '0';
- write(fd, &data,sizeof(data));
- close(fd);
- return 0;
- }
对它的修改很简单,也就是首先使用fork生成一个子进程,然后用execl族取代子进程,运行myclose的脚本文件,父进程等待子进程执行完了之后,在继续剩下的关机流程,
注:不要使用vfork,这样会导致android_reboot传进来的参数cmd自己就发生变化,就算不操作cmd,求大神指导原因。。。。
修改后的android_reboot函数如下:
- int android_reboot(int cmd, int flags, char *arg)
- {
- int ret;
- SLOGD("yulinghan i am here!!!!,cmd = %d",cmd);
- pid_t pc,pid;
- pid = getpid();
- pc = fork();
- if(pc<0){
- exit(1);
- }
- else if(pc == 0){
- SLOGD("yulinghan Child ID is %d,father id is %d,cmd = %d",getpid(),getppid(),cmd);
- execl("/system/bin/sh","sh","/system/bin/myclose",NULL);
- exit(0);
- }
- else{
- pid = waitpid(pc, NULL, 0);
- SLOGD("yulinghan I am father,my id is %d,cmd = %d",getpid(),cmd);
- if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
- sync();
- if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
- remount_ro();
- switch (cmd) {
- case ANDROID_RB_RESTART:
- SLOGD("yulinghan ANDROID_RB_RESTART");
- ret = reboot(RB_AUTOBOOT);
- break;
- case ANDROID_RB_POWEROFF:
- SLOGD("yulinghan ANDROID_RB_POWEROFF");
- ret = reboot(RB_POWER_OFF);
- break;
- case ANDROID_RB_RESTART2:
- SLOGD("yulinghan ANDROID_RB_RESTART2");
- ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART2, arg);
- break;
- default:
- SLOGD("yulinghan default\n");
- ret = -1;
- }
- return ret;
- }
- }
(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关机中插入脚本
- 在Android关机中插入脚本
- 在可插入脚本的应用程序中嵌入 Lua
- 关机脚本
- Android 在文字中插入表情图片
- android在EditText 中插入表情图片
- android在EditText中插入表情图片
- 在android编程中怎么插入背景图片
- android在EditText中插入表情图片
- 在android中使用lua脚本
- 在Android app中调用shell脚本
- [11月13日的脚本] 在Windows 8中为开始菜单 创建关机/重启/注销磁贴
- [5月20日的脚本] 在Windows 8的开始菜单中创建关机/重启/注销磁贴 (VBScript)
- LoadRunner中插入javascript脚本
- 在android App中怎样实现对设备重启或者关机功能
- android android 在list view中插入一条广告
- android中在指定的界面中插入引导页
- android中在指定的界面中插入引导页
- Python查找文件的大小删除此文件
- Only the original thread that created a view hierarchy can touch its views. 是怎么产生的
- tools:context="activity name"作用
- mysql5.7 zip 以上版本安装方法
- 【Spring】Spring oxm 入门初尝试
- 在Android关机中插入脚本
- Linux 内核优化
- ANDROID内存优化(大汇总——中)
- IOS开发 视图重叠时设置交互的优先级__userInteractionEnabled用户交互
- tomcat+bean例子
- java Date 显示格式
- java多线程
- 【框架-MFC】MFC 显示和隐藏 星号密码 以及如何预防被查看
- Javascript面向对象编程(二):构造函数的继承