打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android 长按电源键关机整个流程小学习

Android 长按电源键关机整个流程小学习

最近研究了一下android关机跟重新启动功能,看了一些长按电源键到弹出关机对话框,到真正关机的一系列处理过程。

首先还是来看看这个长按电源键都干了些什么吧?一般来说,电源键都是接到PMU上的,PMU来判断是长按还短按,当有按键消息产生的时候,系统会有中断,然后去读PMU的状态就可以知道是什么了。笔者以全志平台的AXP209小议一下,先贴上关键代码:

static int axp_battery_event(struct notifier_block *nb, unsigned long event, void *data){ struct axp_charger *charger = container_of(nb, struct axp_charger, nb); uint8_t w[9]; w[0] = (uint8_t) ((event) & 0xFF); w[1] = POWER20_INTSTS2; w[2] = (uint8_t) ((event >> 8) & 0xFF); w[3] = POWER20_INTSTS3; w[4] = (uint8_t) ((event >> 16) & 0xFF); w[5] = POWER20_INTSTS4; w[6] = (uint8_t) ((event >> 24) & 0xFF); w[7] = POWER20_INTSTS5; w[8] = (uint8_t) (((uint64_t) event >> 32) & 0xFF); if(event & (AXP20_IRQ_BATIN|AXP20_IRQ_BATRE)) { axp_capchange(charger); } if(event & (AXP20_IRQ_ACIN|AXP20_IRQ_USBIN|AXP20_IRQ_ACOV|AXP20_IRQ_USBOV|AXP20_IRQ_CHAOV |AXP20_IRQ_CHAST|AXP20_IRQ_TEMOV|AXP20_IRQ_TEMLO)) { axp_change(charger); } if(event & (AXP20_IRQ_ACRE|AXP20_IRQ_USBRE)) { axp_change(charger); } if(event & AXP20_IRQ_PEKLO) { axp_presslong(charger); } if(event & AXP20_IRQ_PEKSH) { axp_pressshort(charger); } DBG_PSY_MSG('event = 0x%x\n',(int) event); axp_writes(charger->master,POWER20_INTSTS1,9,w); return 0;}

短按跟长按具体也就是上报的延时区别,如下:

static void axp_presslong(struct axp_charger *charger){ DBG_PSY_MSG('press long\n'); input_report_key(powerkeydev, KEY_POWER, 1); input_sync(powerkeydev); ssleep(2); DBG_PSY_MSG('press long up\n'); input_report_key(powerkeydev, KEY_POWER, 0); input_sync(powerkeydev);}static void axp_pressshort(struct axp_charger *charger){ DBG_PSY_MSG('press short\n'); input_report_key(powerkeydev, KEY_POWER, 1); input_sync(powerkeydev); msleep(100); input_report_key(powerkeydev, KEY_POWER, 0); input_sync(powerkeydev);}

在inputmanager里面再解析出是长按还是短按,来做相应处理。如果是长按,就弹出对话框,在弹出对话框之前,有几次传递,还是activitymanger跟Windowsmanagerservice做宏观调控,最终把消息传到苦逼的ShutdownThread,不过ShutdownThread也不难弄。/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/sundesheng125原创,转载请注明出处,谢谢!
/*****************************************************************************************************/

首先来看一下,在ShutdownThread里面有一个CloseDialogReceiver来关注Intent.ACTION_CLOSE_SYSTEM_DIALOGS,它收到这个消息就会关闭这个对话框。对话框怎么起来的呢?请看下面的源码

if (confirm) { final CloseDialogReceiver closer = new CloseDialogReceiver(context); final AlertDialog dialog = new AlertDialog.Builder(context) .setTitle(com.android.internal.R.string.power_off) .setMessage(resourceId) .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { beginShutdownSequence(context); } }) .setNegativeButton(com.android.internal.R.string.no, null) .create(); closer.dialog = dialog; dialog.setOnDismissListener(closer); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); dialog.show(); } else { beginShutdownSequence(context); }

其实就是一个AlertDialog,也没什么新鲜的,只是在setPositiveButton的时候注册了clicklistener来监听你是否按下了,按下了就直接执行beginShutdownSequence。在beginShutdownSequence还会弹出一个进度的对话框,代码如下:

ProgressDialog pd = new ProgressDialog(context); pd.setTitle(context.getText(com.android.internal.R.string.power_off)); pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); pd.setIndeterminate(true); pd.setCancelable(false); pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); pd.show();

在里面还会调用两个非常重要的Power.shutdown()跟Power.reboot(reason),看你是重启还是关机了。

/** * Low-level function turn the device off immediately, without trying * to be clean. Most people should use * {@link android.internal.app.ShutdownThread} for a clean shutdown. * * @deprecated * @hide */ @Deprecated public static native void shutdown(); /** * Reboot the device. * @param reason code to pass to the kernel (e.g. 'recovery'), or null. * * @throws IOException if reboot fails for some reason (eg, lack of * permission) */ public static void reboot(String reason) throws IOException { rebootNative(reason); } private static native void rebootNative(String reason) throws IOException ;

再往下跟,

static void android_os_Power_shutdown(JNIEnv *env, jobject clazz){ android_reboot(ANDROID_RB_POWEROFF, 0, 0);}extern int go_recovery(void);static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason){ if (reason == NULL) { android_reboot(ANDROID_RB_RESTART, 0, 0); } else { const char *chars = env->GetStringUTFChars(reason, NULL); //android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars); go_recovery(); android_reboot(ANDROID_RB_RESTART, 0, 0); env->ReleaseStringUTFChars(reason, chars); // In case it fails. } jniThrowIOException(env, errno);}

所以,整个流程都是好的,学习理了一下流程,大部分都是源码,把它搞清楚也是有好处的。



本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
设备驱动
android 电容屏(三):驱动调试之驱动程序分析篇
sunxi gpio pinctrl的使用demo | 知识总结
不懂记, 如何利用Activity的Dialog风格完成弹出框设计——day6
android 悬浮球的实现
Android init进程中鲜为人知的charger mode 模式
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服