正常关机流程

来源:互联网 发布:淘宝免费代收货服务 编辑:程序博客网 时间:2024/05/01 22:56
/****************************************************************************************/
1.]从long power key到出现关机界面
/****************************************************************************************/
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
            case KeyEvent.KEYCODE_POWER: {
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = false; // wake-up will be handled separately
                if (down) {
                    interceptPowerKeyDown(event, interactive);
                } else {
                    interceptPowerKeyUp(event, interactive, canceled);
                }
                break;
            }
    }


    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
          Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
          msg.setAsynchronous(true);
          mHandler.sendMessageDelayed(msg, ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
    }


    private class PolicyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_POWER_LONG_PRESS:
                    powerLongPress();
                    break;
   }
}


    private void powerLongPress() {
        final int behavior = getResolvedLongPressOnPowerBehavior();
        switch (behavior) {
        case LONG_PRESS_POWER_GLOBAL_ACTIONS:
            mPowerKeyHandled = true;
            if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
                performAuditoryFeedbackForAccessibilityIfNeed();
            }
            showGlobalActionsInternal();
            break;
}
    }


    void showGlobalActionsInternal() {
        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
        if (mGlobalActions == null) {
            mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
        }
        final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
        mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
        if (keyguardShowing) {
            // since it took two seconds of long press to bring this up,
            // poke the wake lock so they have some time to see the dialog.
            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
        }
    }


/****************************************************************************************/
2.]按下reboot 按键
调用powermanagerservice的reboot 接口
/****************************************************************************************/
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
        /**
         * Reboots the device.
         *
         * @param confirm If true, shows a reboot confirmation dialog.
         * @param reason The reason for the reboot, or null if none.
         * @param wait If true, this call waits for the reboot to complete and does not return.
         */
        @Override // Binder call
        public void reboot(boolean confirm, String reason, boolean wait) {
            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
            if (PowerManager.REBOOT_RECOVERY.equals(reason)) {
                mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
            }


            final long ident = Binder.clearCallingIdentity();
            try {
                shutdownOrRebootInternal(false, confirm, reason, wait);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }


    private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
            final String reason, boolean wait) {
        if (mHandler == null || !mSystemReady) {
            throw new IllegalStateException("Too early to call shutdown() or reboot()");
        }


        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    if (shutdown) {
                        ShutdownThread.shutdown(mContext, confirm);
                    } else {
                        ShutdownThread.reboot(mContext, reason, confirm);
                    }
                }
            }
        };


/****************************************************************************************/
3.]从powermanagerservice到shutdown thread
/****************************************************************************************/
frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java:
    /**
     * Request a clean shutdown, waiting for subsystems to clean up their
     * state etc.  Must be called from a Looper thread in which its UI
     * is shown.
     *
     * @param context Context used to display the shutdown progress dialog.
     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
     * @param confirm true if user confirmation is needed before shutting down.
     */
    public static void reboot(final Context context, String reason, boolean confirm) {
        mReboot = true;
        mRebootSafeMode = false;
        mRebootUpdate = false;
        mRebootReason = reason;
        shutdownInner(context, confirm);
    }
08-15 16:55:49.358   554  2615 W System.err: java.lang.Exception: ShutdownThread: reboot
08-15 16:55:49.359   554  2615 W System.err: at com.android.server.power.ShutdownThread.reboot(ShutdownThread.java:228)
08-15 16:55:49.359   554  2615 W System.err: at com.android.server.power.PowerManagerService$3.run(PowerManagerService.java:2329)
08-15 16:55:49.359   554  2615 W System.err: at android.os.Handler.handleCallback(Handler.java:739)
08-15 16:55:49.359   554  2615 W System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
08-15 16:55:49.359   554  2615 W System.err: at android.os.Looper.loop(Looper.java:148)
08-15 16:55:49.359   554  2615 W System.err: at android.os.HandlerThread.run(HandlerThread.java:61)
08-15 16:55:49.359   554  2615 W System.err: at com.android.server.ServiceThread.run(ServiceThread.java:46)
08-15 16:55:49.360   554  2615 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1


然后调进了shutdownThread的run函数,栈并没有显示怎样调进去的。


08-15 16:55:49.360   554  2615 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1
08-15 16:55:49.403   554  2615 D InputDispatcher: channel 'fa020be  (server)' ~ registerInputChannel - monitor=false
08-15 16:55:49.403   554  2615 D InputDispatcher: setInputWindows
08-15 16:55:49.403   554  2615 D InputDispatcher: Focus left window: Window{8e3e186 u0 GlobalActions}
08-15 16:55:49.403   554  2615 D InputDispatcher: Focus entered window: Window{fa020be u0 android}
08-15 16:55:49.408   554  5868 W System.err: java.lang.Exception: shutdownThread: run
08-15 16:55:49.408   554  5868 W System.err: at com.android.server.power.ShutdownThread.run(ShutdownThread.java:384)


/****************************************************************************************/
4.]从shutdown thread再到powermanager service的lowlevel
/****************************************************************************************/
run -> rebootOrShutdown(mContext, mReboot, mRebootReason);
    public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
        deviceRebootOrShutdown(reboot, reason);
        if (reboot) {
            Log.i(TAG, "Rebooting, reason: " + reason);
            PowerManagerService.lowLevelReboot(reason);
            Log.e(TAG, "Reboot failed, will attempt shutdown instead");
}
        // Shutdown power
        Log.i(TAG, "Performing low-level shutdown...");
        PowerManagerService.lowLevelShutdown();
    }
这里又调入:PowerManagerService
    public static void lowLevelReboot(String reason) {
        if (reason == null) {
            reason = "";
        }
        if (reason.equals(PowerManager.REBOOT_RECOVERY)) {
            // If we are rebooting to go into recovery, instead of
            // setting sys.powerctl directly we'll start the
            // pre-recovery service which will do some preparation for
            // recovery and then reboot for us.
            SystemProperties.set("ctl.start", "pre-recovery");
        } else {
            SystemProperties.set("sys.powerctl", "reboot," + reason);
        }
    }


/****************************************************************************************/
5.]触发property:sys.powerctl改变对应的处理函数
/****************************************************************************************/
SystemProperties.set(sys.powerctl, xxx);


sys.powerctl属性触发开关在init.rc定义
on property:sys.powerctl=* powerctl ${sys.powerctl}


我们来解读这句话,on property:sys.powerctl=*表示当属性sys.powerctl设置为任何值是都会跑到这里,
触发动作是powerctl ${sys.powerctl},这个动作的意思是调用powerctl指令,并把sys.powerctl的值传给它。
powerctl指令在init进程会执行。
从下面的表可知,powerctl对应的操作是do_powerctl
[system/core/init/keywords.h]
KEYWORD(powerctl, COMMAND, 1, do_powerctl)


do_powerctl的实现
代码如下:
[system/core/init/builtins.c]
int do_powerctl(int nargs, char **args) { ....  return android_reboot(cmd, 0, reboot_target); }


它调用android_reboot()函数,实现如下:
[system/core/libcutils/android_reboot.c]
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 山药皮过敏很痒怎么办 貔貅被家人摸了怎么办? 摸了山药很痒怎么办 山药搞得皮肤痒怎么办 手上弄了山药痒怎么办 老板就是个富二代怎么办 中考准考证密码忘了怎么办 准考证号和密码忘了怎么办 安运继续教育考试不及格怎么办 微信的视频打不开怎么办 公众号被取消了怎么办 合同上不写工资怎么办 已经上班了想考个大专文凭怎么办 微信小程序违规暂停服务怎么办 程序锁密码忘了怎么办 忘了应用锁密码怎么办 毕业后发现论文有错误怎么办 柯丽尔打胶片时胶片卡住了怎么办 闽教英语要收费怎么办 高一学生英语差怎么办 高一英语基础差怎么办 老师教育学生学生跑出教室怎么办 研究生课题难出论文怎么办 一审过了上诉期怎么办 民事判决赔偿不给钱怎么办 民事申诉期过了怎么办 过了两年申诉期怎么办 微快递下单不能定位怎么办 网上打字兼职被骗了怎么办 微信银行卡转错怎么办 在支付宝被诈骗怎么办 发现被骗了报警不理怎么办 投稿投错了网站怎么办 六个月宝宝吃辅食便秘怎么办 六个月宝宝加辅食后便秘怎么办 婴儿6个月便秘怎么办 7个月的孩子便秘怎么办 四个月宝宝喜欢吃手怎么办 博瑞智教育是上当了怎么办 我43岁记忆力差怎么办 艾灸灸出的湿疹怎么办