第一部分:关机事件的捕获
1,PhoneWindowManager捕获POWER按键
publicintinterceptKeyBeforeQueueing(KeyEventevent,intpolicyFlags){
...
caseKeyEvent.KEYCODE_POWER:{
...
result&=~ACTION_PASS_TO_USER;
isWakeKey=false;// wake-up will be handled separately
if(down){
interceptPowerKeyDown(event,interactive);
}else{
time_record=time_now;//Letv-U4 UFO-2382 :20160812
interceptPowerKeyUp(event,interactive,canceled);
}
break;
}
...
2,进入interceptPowerKeyDown处理,进入interactive mode
...
if(hasLongPressOnPowerBehavior()){
Messagemsg=mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
...
MSG_POWER_LONG_PRESS MESSAGE,通过mHandler将由另外一个线程处理,mHandler是PolicyHandler的实例。来看mHandler的handleMessager怎么处理。
caseMSG_POWER_LONG_PRESS:
powerLongPress();
break;
3,进入powerLongPress,
privatevoidpowerLongPress(){
finalintbehavior=getResolvedLongPressOnPowerBehavior();
switch(behavior){
...
caseLONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
mPowerKeyHandled=true;
performHapticFeedbackLw(null,HapticFeedbackConstants.LONG_PRESS,false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);//关掉系统对话框
mWindowManagerFuncs.shutdown(behavior==LONG_PRESS_POWER_SHUT_OFF);
break;
}
}
从xml config可知,behavior为3,即LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM
./core/res/res/values/config.xml:721: 3
这里的mWindowManagerFuncs是在PhoneWindowManager的init()处赋值的
publicvoidinit(Contextcontext,IWindowManagerwindowManager,
WindowManagerFuncswindowManagerFuncs){
mContext=context;
mWindowManager=windowManager;
mWindowManagerFuncs=windowManagerFuncs;
...
到底谁调用了?
在WindowManagerService的构造函数中,调用initPolicy(),这里调用PhoneWindowManager的init
privatevoidinitPolicy(){
UiThread.getHandler().runWithScissors(newRunnable(){
@Override
publicvoidrun(){
WindowManagerPolicyThread.set(Thread.currentThread(),Looper.myLooper());
mPolicy.init(mContext,WindowManagerService.this,WindowManagerService.this);
}
},0);
}
由此可知,mWindowManagerFuncs.shutdown即为WindowManagerService.shutdown
即:
// Called by window manager policy. Not exposed externally.
@Override
publicvoidshutdown(booleanconfirm){
ShutdownThread.shutdown(mContext,confirm);
}
即进入,ShutdownThread这里面集中处理关机流程。
第二部分:ShutdownThread的处理
1,先看整体的关机流程
2,没什么太大疑问,主要分析MountService的关机流程。即上面流程的第9步流程
2.1,new出一个IMountShutdownObserver observer,等会mountService调用shutdown需要用到
2.2,mount.shutdown(observer);
进入mountService
@Override
publicvoidshutdown(finalIMountShutdownObserverobserver){
Slog.i(TAG,"Shutting down");
mHandler.obtainMessage(H_SHUTDOWN,observer).sendToTarget();
}
2.3,交由MountService的MountServiceHanler处理
caseH_SHUTDOWN:{
finalIMountShutdownObserverobs=(IMountShutdownObserver)msg.obj;
booleansuccess=false;
try{
success=mConnector.execute("volume","shutdown").isClassOk();
}catch(NativeDaemonConnectorExceptionignored){
}
if(obs!=null){
try{
obs.onShutDownComplete(success?0:-1);
}catch(RemoteExceptionignored){
}
}
break;
}
obs就是ShutdownThread传过来的。调用onShutDownComplete反馈状态给ShutdownThread,如果successful,打印如下:
W/ShutdownThread( 3630): Result code 0 from MountService.shutdown
这个返回值是底层执行”volume” “shutdown”的结果。关机超时,有时候是mount Service执行volume shutdown超时,此时可以跟踪Connector的打印
}
03-15 09:52:28.681 E/VoldConnector( 3630): NDC Command {8 volume shutdown} took too long (11412ms)
2.4,再回到ShutdownThread,执行到MountService的shutdown会回调observer的onShutdownComplete函数,会调用actionDone(),这是用于线程同步用的
voidactionDone(){
synchronized(mActionDoneSync){
mActionDone=true;
mActionDoneSync.notifyAll();
}
}
mActionDoneSync就是一个Object, private final Object mActionDoneSync = new Object();
调用到actionDone时,所有wait在这个变量上的进程,都继续执行。