客户提出去除Safe Mode需求,这个是在长按Power键跳出Power off按钮,再长按Power off后会弹出Safe Mode 进入提示框,然后点击之后就会重启进入Safe Mode模式。
长按到界面出现Poweroff 弹窗逻辑梳理
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
void showGlobalActionsInternal() {
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
}
final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
// 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);
}
GlobalActionsImpl实现GlobalActions接口
重写showGlobalActions方法,弹窗GlobalActionsDialog,弹窗中包含了Power off 控制开关
vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\globalactions\GlobalActionsImpl.java
public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks {
@Override
public void showGlobalActions(GlobalActionsManager manager) {
if (mDisabled) return;
mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
mDeviceProvisionedController.isDeviceProvisioned(),
mWalletPluginProvider.get());
Dependency.get(KeyguardUpdateMonitor.class).requestFaceAuth();
}
Power off button点击逻辑
vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\globalactions\GlobalActionsDialog.java
final class ShutDownAction extends SinglePressAction implements LongPressAction {
private ShutDownAction() {
super(R.drawable.ic_lock_power_off,
R.string.global_action_power_off);
}
//长按回调
@Override
public boolean onLongPress() {
Log.i("Xxxx", "111 GlobalActionsDialog.java onLongPress");
/**if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
mWindowManagerFuncs.reboot(true);
return true;
}**/
去掉走reboot(true),直接调用shutdown()方法,实现去除safemode模式需求
mWindowManagerFuncs.shutdown();
return true;
}
//点击回调
@Override
public void onPress() {
Log.i("Xxxx", "GlobalActionsDialog.java onPress");
// shutdown by making sure radio and power are handled accordingly.
mWindowManagerFuncs.shutdown();
}
}
调用的private final GlobalActionsManager mWindowManagerFuncs; 对象的方法
GlobalActionsManager 定义在GlobalActions.java 中,是一个接口
vendor\mediatek\proprietary\packages\apps\SystemUI\plugin\src\com\android\systemui\plugins\GlobalActions.java
public interface GlobalActions extends Plugin {
String ACTION = "com.android.systemui.action.PLUGIN_GLOBAL_ACTIONS";
int VERSION = 1;
void showGlobalActions(GlobalActionsManager manager);
default void showShutdownUi(boolean isReboot, String reason) {
}
default void destroy() {
}
@ProvidesInterface(version = GlobalActionsManager.VERSION)
public interface GlobalActionsManager {
int VERSION = 1;
void onGlobalActionsShown();
void onGlobalActionsHidden();
void shutdown();
void reboot(boolean safeMode);
}
}
vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\globalactions\GlobalActionsComponent.java
public class GlobalActionsComponent extends SystemUI implements Callbacks, GlobalActionsManager {
GlobalActionsComponent实现GlobalActionsManager接口,回调到GlobalActionsComponent的reboot和shutdown方法
@Override
public void shutdown() {
try {
mBarService.shutdown();
} catch (RemoteException e) {
}
}
@Override
public void reboot(boolean safeMode) {
try {
mBarService.reboot(safeMode);
} catch (RemoteException e) {
}
}
通过private IStatusBarService mBarService;调用StatusBarManagerService服务
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
调用到StatusBarManagerService的reboot和shutdown
@Override
public void shutdown() {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.prepareForPossibleShutdown();
// ShutdownThread displays UI, so give it a UI context.
mHandler.post(() ->
ShutdownThread.shutdown(getUiContext(),
PowerManager.SHUTDOWN_USER_REQUESTED, false));
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void reboot(boolean safeMode) {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.prepareForPossibleShutdown();
mHandler.post(() -> {
// ShutdownThread displays UI, so give it a UI context.
if (safeMode) {
ShutdownThread.rebootSafeMode(getUiContext(), true);
} else {
ShutdownThread.reboot(getUiContext(),
PowerManager.SHUTDOWN_USER_REQUESTED, false);
}
});
} finally {
Binder.restoreCallingIdentity(identity);
}
}
调用到ShutdownThread的实现方法,长按Power off传入的safeMode值为true,执行rebootSafeMode方法;最终都调用的是ShutdownThread的shutdownInner方法,若是safemode则进行弹窗提示。
public static void rebootSafeMode(final Context context, boolean confirm) {
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
if (um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
return;
}
mReboot = true;
mRebootSafeMode = true;
mRebootHasProgressBar = false;
mReason = null;
shutdownInner(context, confirm);
}