Android long press the power key to shut down the entire process to learn
I recently studied the android shutdown and restart functions, and read a series of processing processes from long-pressing power keys to the pop-up shutdown dialog box and real shutdown.
First, let's take a look at what this long-pressed power button has done? Generally, power keys are connected to PMU, and PMU determines that the power keys are long-pressed and Short-pressed. When a key message is generated, the system will be interrupted, then read the PMU status to know what it is. I will discuss it with the AXP209 OF THE quanzhi platform and paste the key code first:
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;}
The difference between short and long presses is the latency of reporting, as follows:
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);}
In inputmanager, analyze whether the long or short press is used for processing. If it is a long press, a dialog box will pop up. Before the dialog box is displayed, there will be several transfers, or activitymanger and Windowsmanagerservice will perform macro-control, and finally pass the message to the hard-pressed ShutdownThread, however, ShutdownThread is not difficult. /*************************************** **************************************** **********************/
Statement: the content of this blog is created at http://blog.csdn.net/sundesheng125. please refer to it for help. Thank you!
/*************************************** **************************************** **********************/
First, there is a CloseDialogReceiver in ShutdownThread to follow Intent. ACTION_CLOSE_SYSTEM_DIALOGS. When it receives this message, it closes this dialog box. How does the dialog box get up? See the following source code:
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); }
It is actually an AlertDialog, and there is nothing new, just register the clicklistener when setPositiveButton to monitor whether you have pressed it. When you press it, You can directly execute beginShutdownSequence. In beginShutdownSequence, a progress dialog box is displayed. The Code is as follows:
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();
It also calls two very important Power. shutdown () and Power. reboot (reason), to see if you have restarted or shut down.
/** * 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 ;
Follow up,
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);}
Therefore, the entire process is good. After learning the process, most of them are source code. It is also good to clarify it.