介绍按住关机按键后到调用系统关机动画之前流程
PhoneWindowManager.java
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
...
switch (keyCode) {
case KeyEvent.KEYCODE_POWER: {
// Any activity on the power button stops the accessibility shortcut
cancelPendingAccessibilityShortcutAction();
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);//1
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
}
}
在1处,调用interceptPowerKeyDown,发送一个延时的message,因为要长按才会弹出关机界面,所以如果在延时结束前就取消了就会停止发送.
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
。。。
if (hasLongPressOnPowerBehavior()) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());//2
}
}
private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;
mScreenshotChordPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
cancelPendingPowerKeyAction();
。。
}
private void cancelPendingPowerKeyAction() {
if (!mPowerKeyHandled) {
mPowerKeyHandled = true;
mHandler.removeMessages(MSG_POWER_LONG_PRESS);//3
}
}
在2处和3处,分别是发送延时关机和取消关机的操作.
private class PolicyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_POWER_LONG_PRESS:
powerLongPress();
break;
}
}
。。。。
}
private void powerLongPress() {
showGlobalActionsInternal();
}
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);
}
}
GlobalActionsclass
implements GlobalActionsListener {
public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {
if (DEBUG) Slog.d(TAG, "showDialog " + keyguardShowing + " " + deviceProvisioned);
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = deviceProvisioned;
mShowing = true;
if (mStatusBarConnected) {
mStatusBarInternal.showGlobalActions();//4
mHandler.postDelayed(mShowTimeout, 5000);//5
} else {
// SysUI isn't alive, show legacy menu.
ensureLegacyCreated();
mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
}
}
@Override
public void onGlobalActionsShown() {
if (DEBUG) Slog.d(TAG, "onGlobalActionsShown");
// SysUI is showing, remove timeout callbacks.
mHandler.removeCallbacks(mShowTimeout);//6
}
}
4处尝试调用的SystemUI的对话框,这个对话框显示关机重启操作按钮供用户选择。如果连接失败,就会失败就会调用系统的对话框,所有在5处会有同一个延时调用系统对话框的messge,如果成功调用SystemUI的对话框,回调会在6处.remove掉.
public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mHandler = new Handler();
mWindowManagerFuncs = windowManagerFuncs;
mStatusBarInternal = LocalServices.getService(StatusBarManagerInternal.class);
// Some form factors do not have a status bar.
if (mStatusBarInternal != null) {
mStatusBarInternal.setGlobalActionsListener(this);
}
}
StatusBarManagerInternal是一个接口,那么获取的上面mStatusBarInternal对象应该是实现了StatusBarManagerInternal接口。
//添加service,与getService对应
public StatusBarManagerService(Context context, WindowManagerService windowManager) {
mContext = context;
mWindowManager = windowManager;
LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
}
/**
* Private API used by NotificationManagerService.
*/
private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() {
private boolean mNotificationLightOn;
。。。
@Override
public void showGlobalActions() {
if (mBar != null) {
try {
mBar.showGlobalActionsMenu();
} catch (RemoteException ex) {}
}
}
。。。
}
这个mBar定义IStatusBar mBar,是一个跨进程的操作,从注解我们可以看出IStatusBar,来源status bar service.
SystemUI实现
CommandQueue.java
@Override
public void showGlobalActionsMenu() {
synchronized (mLock) {
mHandler.removeMessages(MSG_SHOW_GLOBAL_ACTIONS);
mHandler.obtainMessage(MSG_SHOW_GLOBAL_ACTIONS).sendToTarget();
}
}
GlobalActionsComponent.java
public class GlobalActionsComponent extends SystemUI implements Callbacks, GlobalActionsManager {
private Extension mExtension;
private IStatusBarService mBarService;
@Override
public void start() {
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mExtension = Dependency.get(ExtensionController.class).newExtension(GlobalActions.class)
.withPlugin(GlobalActions.class)
.withDefault(() -> new GlobalActionsImpl(mContext))
.build();
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
}
@Override
public void handleShowGlobalActionsMenu() {
mExtension.get().showGlobalActions(this);
}
}
最终:
public class GlobalActionsImpl implements GlobalActions {
private final Context mContext;
private final KeyguardMonitor mKeyguardMonitor;
private final DeviceProvisionedController mDeviceProvisionedController;
private GlobalActionsDialog mGlobalActions;
public GlobalActionsImpl(Context context) {
mContext = context;
mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
}
@Override
public void showGlobalActions(GlobalActionsManager manager) {
if (mGlobalActions == null) {
final ContextThemeWrapper context = new ContextThemeWrapper(mContext,
android.R.style.Theme_Material_Light);
mGlobalActions = new GlobalActionsDialog(context, manager);
}
mGlobalActions.showDialog(mKeyguardMonitor.isShowing(),
mDeviceProvisionedController.isDeviceProvisioned());
}
}
GlobalActionsDialog负责显示关机,重启的对话框,在这里我们可以自定义关机对话框。
这里面对于关机,重启,安全模式是调用系统api完成的
//关机
mWindowManagerFuncs.shutdown();
//以安全模式重启
mWindowManagerFuncs.reboot(true);
//重启
mWindowManagerFuncs.reboot(false);
具体重启是如何操作,再看mWindowManagerFuncs对象的实现类GlobalActionsComponent。
GlobalActionsComponent.java
@Override
public void reboot(boolean safeMode) {
try {
mBarService.reboot(safeMode);
} catch (RemoteException e) {
}
}
mBarService的实现类
StatusBarManagerService.java
*/
@Override
public void reboot(boolean safeMode) {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
mHandler.post(() -> {
// ShutdownThread displays UI, so give it a UI context.
// TINNO START
// Modified by Jameson.xu on 20171114 for VBNLITEIA-1113,device reset exception
if (safeMode) {
//ShutdownThread.rebootSafeMode(getUiContext(), false);
//safe reboot,should show dialog for user(CTS 3PL(windware) need);for safemode function,CDAAOB-224,DATE20180825
ShutdownThread.rebootSafeMode(getUiContext(), true);
} else {
ShutdownThread.reboot(getUiContext(),
PowerManager.SHUTDOWN_USER_REQUESTED, true);
}
// TINNO END
});
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/**
* Allows the status bar to shutdown the device.
*/
@Override
public void shutdown() {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
// ShutdownThread displays UI, so give it a UI context.
// TINNO START
// Modified by Jameson.xu on 20171114 for VBNLITEIA-1113,device reset exception
mHandler.post(() ->
ShutdownThread.shutdown(getUiContext(),
PowerManager.SHUTDOWN_USER_REQUESTED, true));
// TINNO END
} finally {
Binder.restoreCallingIdentity(identity);
}
}
最终在ShutdownThread.java处理