一、基本概念

重启一般分为是通过按键触发和非按键触发

  • 按键触发
    是通过按键触发中断,linux kernel层给Android framework层返回按键事件,然后进入到framework层,再从framework层进入kernel层执行关机任务
  • 非按键触发
    系统异常导致重启,或直接调用PowerManger的reboot()方法重启

二、关机流程(Framework层)

在PowerManager的文档中给出了关机/重启的方法 reboot,描述很简单就是重启设备,并且重启成功,将没有返回值。相应的需要打开Manifest.permission.REBOOT权限。方法也只有一个参数reason代表特定的重启模式,例如recovery又或者为null。

也不拐弯抹角,直接从PowerManager开始看

PowerManger.reboot

[frameworks/base/core/java/android/os/PowerManager.java]
@RequiresPermission(permission.REBOOT)
    public void reboot(@Nullable String reason) {
        if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) {
            throw new UnsupportedOperationException(
                    "Attempted userspace reboot on a device that doesn't support it");
        }
        try {
            mService.reboot(false, reason, true); 
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
  • mServiceIPowerManger的binder接口服务
  • 通过binder调到PowerMangerService的reboot函数

PowerManagerService

[frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java]
@Override // Binder call
        public void reboot(boolean confirm, @Nullable String reason, boolean wait) {
            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
            if (PowerManager.REBOOT_RECOVERY.equals(reason)
                    || PowerManager.REBOOT_RECOVERY_UPDATE.equals(reason)) {
                mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
            }

            final long ident = Binder.clearCallingIdentity();
            try {
                shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
  • 通过调用shutdownOrRebootInternal来实现关机或者重启
  • 其中shutdownOrRebootInterna的四个参数分别为 HALT_MODE_REBOOT, confirm, reason, wait
  • HALT_MODE_REBOOT=1 代表重启
  • confirm=false 代表直接重启,不需要提示对话框
  • wait=false 代表阻塞等待重启操作

shutdownOrRebootInternal

[frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java]
private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,
            @Nullable final String reason, boolean wait) {
       
        if (PowerManager.REBOOT_USERSPACE.equals(reason)) {
            if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
                throw new UnsupportedOperationException(
                        "Attempted userspace reboot on a device that doesn't support it");
            }
            UserspaceRebootLogger.noteUserspaceRebootWasRequested();
        }
        //判断是否PM.Handler初始化和判断系统是否启动成功
        if (mHandler == null || !mSystemReady) {
            if (RescueParty.isAttemptingFactoryReset()) {
                //如果陷入底层重启的循环,并且RescueParty正在恢复出厂设置
                PowerManagerService.lowLevelReboot(reason);
            } else {
                throw new IllegalStateException("Too early to call shutdown() or reboot()");
            }
        }

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                //根据HALT的类型来执行不同的操作
                synchronized (this) {
                    if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
                        ShutdownThread.rebootSafeMode(getUiContext(), confirm);
                    } else if (haltMode == HALT_MODE_REBOOT) {
                        //重启流程
                        ShutdownThread.reboot(getUiContext(), reason, confirm);
                    } else {
                       //关机流程
                        ShutdownThread.shutdown(getUiContext(), reason, confirm);
                    }
                }
            }
        };

        // 处理关机的线程必须运行在一个有UI界面上的looper
        Message msg = Message.obtain(UiThread.getHandler(), runnable);
        msg.setAsynchronous(true);
        UiThread.getHandler().sendMessage(msg);

        //因为reboot没有返回值,因此只能阻塞等待shutdownThread完成
        if (wait) {
            synchronized (runnable) {
                while (true) {
                    try {
                        runnable.wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }
  • 通过PowerManager.isRebootingUserspaceSupportedImpl检查设备是否支持重新启用用户空间
  • 判断PM.Handle是否初始化和系统是否启动
  • 根据HAL的不同类型执行相应的操作
  • 将shutdownThread运行在UI界面的Looper上
  • 等待shutdownThread完成

ShutdownThread.root

[frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java ]
public static void reboot(final Context context, String reason, boolean confirm) {
        mReboot = true;
        mRebootSafeMode = false;
        mRebootHasProgressBar = false;
        mReason = reason;
        shutdownInner(context, confirm);
    }
  • 这个方法的说明就是 需要重启且不用开启安全模式,不用显示进度条。重启参数为传递下来的reson。shutdownInner的confirm为是否需要显示确认对话框,因为是通过reboot重启的,所以这里为false。

shutdownInner

private static void shutdownInner(final Context context, boolean confirm) {
   
        //因为ShutdownThread在很多地方调用,所以就先检查一下传入context
        context.assertRuntimeOverlayThemable();

       //确保只有一个线程来试图关闭电源,其他的额外的调用均会被返回
        synchronized (sIsStartedGuard) {
            if (sIsStarted) {
                Log.d(TAG, "Request to shutdown already running, returning.");
                return;
            }
        }

        final int longPressBehavior = context.getResources().getInteger(
                        com.android.internal.R.integer.config_longPressOnPowerBehavior);
        final int resourceId = mRebootSafeMode
                ? com.android.internal.R.string.reboot_safemode_confirm
                : (longPressBehavior == 2
                        ? com.android.internal.R.string.shutdown_confirm_question
                        : com.android.internal.R.string.shutdown_confirm);

        Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
        
        if (confirm) {
            final CloseDialogReceiver closer = new CloseDialogReceiver(context);
            if (sConfirmDialog != null) {
                sConfirmDialog.dismiss();
            }
            sConfirmDialog = new AlertDialog.Builder(context)
                    .setTitle(mRebootSafeMode
                            ? com.android.internal.R.string.reboot_safemode_title
                            : 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 = sConfirmDialog;
            sConfirmDialog.setOnDismissListener(closer);
            sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
            sConfirmDialog.show();
        } else {
            beginShutdownSequence(context);
        }
    }
  • 主要还是通过Confirm来判断是否需要确认对话框,如果为真则通过AlertDialog创建一个对话框,之后通过setPositiveButton为对话框设置确定按钮的点击事件。通过setNegativeButton来设置取消按钮的点击事件。
  • 不论是Confirm是否为真,都调用beginShutdownSequence

beginShutdownSequence

[frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java]
private static void beginShutdownSequence(Context context) {
        
        //同上,还是确保在只有一个线程进行操作
        synchronized (sIsStartedGuard) {
            if (sIsStarted) {
                Log.d(TAG, "Shutdown sequence already running, returning.");
                return;
            }
            sIsStarted = true;
        }
        //通过showShutdownDialog根据context创建对话框
        sInstance.mProgressDialog = showShutdownDialog(context);
        sInstance.mContext = context;
        sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);

        // 使用唤醒锁确保不会睡眠
        sInstance.mCpuWakeLock = null;
        try {
            sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
                    PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
            sInstance.mCpuWakeLock.setReferenceCounted(false);
            sInstance.mCpuWakeLock.acquire();
        } catch (SecurityException e) {
            Log.w(TAG, "No permission to acquire wake lock", e);
            sInstance.mCpuWakeLock = null;
        }

        // 当处理亮屏状态,则获取亮屏锁,提供用户体验
        sInstance.mScreenWakeLock = null;
        if (sInstance.mPowerManager.isScreenOn()) {
            try {
                sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
                        PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
                sInstance.mScreenWakeLock.setReferenceCounted(false);
                sInstance.mScreenWakeLock.acquire();
            } catch (SecurityException e) {
                Log.w(TAG, "No permission to acquire wake lock", e);
                sInstance.mScreenWakeLock = null;
            }
        }

        if (SecurityLog.isLoggingEnabled()) {
            SecurityLog.writeEvent(SecurityLog.TAG_OS_SHUTDOWN);
        }

        // 启动关机流程
        sInstance.mHandler = new Handler() {
        };
        sInstance.start();
    }

showShutdownDialog

[frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java]
private static ProgressDialog showShutdownDialog(Context context) {
        
        //创建系统对话框来表示设备正在重启/关机
        ProgressDialog pd = new ProgressDialog(context);


        //如果重启原因是 "recovery-update"或者"recovery-update,quiescent"
        if (mReason != null && mReason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
           
            mRebootHasProgressBar = RecoverySystem.UNCRYPT_PACKAGE_FILE.exists()
                    && !(RecoverySystem.BLOCK_MAP_FILE.exists());
            pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
            if (mRebootHasProgressBar) {
                pd.setMax(100);
                pd.setProgress(0);
                pd.setIndeterminate(false);
                pd.setProgressNumberFormat(null);
                pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                pd.setMessage(context.getText(
                            com.android.internal.R.string.reboot_to_update_prepare));
            } else {
                if (showSysuiReboot()) {
                    return null;
                }
                pd.setIndeterminate(true);
                pd.setMessage(context.getText(
                            com.android.internal.R.string.reboot_to_update_reboot));
            }
        } else if (mReason != null && mReason.equals(PowerManager.REBOOT_RECOVERY)) {
            if (RescueParty.isAttemptingFactoryReset()) {
            
                //实际上在这里我们并没有恢复出厂设置,而是生成一个对话框来询问用户是否重置
                //给他们一个相对友好的消息。
                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);
            } else {
            
                //恢复出厂设置路径,并设置对应的对话框消息
                pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
                pd.setMessage(context.getText(
                            com.android.internal.R.string.reboot_to_reset_message));
                pd.setIndeterminate(true);
            }
        } else {
            //正常重启、关机进这个分支
            if (showSysuiReboot()) {
                return null;
            }
            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();
        return pd;
    }

此处 ProgressDialog()会根据不同的重启原因显示不同的UI界面

  • 重启到recovery模式,并安装更新
  • Condition: mReason startswith REBOOT_RECOVERY_UPDATE
  • 检查/cache/recovery/uncrypt_file文件是否存在,存在,mRebootHasProgressBar == True
  • UI:显示进度条
  • 重启到recovery模式,并恢复出厂设置
  • Condition:mReason == REBOOT_RECOVERY
  • UI:不显示进度条,只显示spinning circle
  • 正常关机重启
  • Condition:Otherwise
  • UI:不显示进度条,只显示spinning circle

ShutdownThread.run

public void run() {
        TimingsTraceLog shutdownTimingLog = newTimingsLog();
        shutdownTimingLog.traceBegin("SystemServerShutdown");
        metricShutdownStart();
        metricStarted(METRIC_SYSTEM_SERVER);

        BroadcastReceiver br = new BroadcastReceiver() {
            @Override public void onReceive(Context context, Intent intent) {
               // 接收到该广播,则唤醒wait()操作
                actionDone();
            }
        };

            //设置属性"sys.shutdown.requested"的值为reason
        {
            String reason = (mReboot ? "1" : "0") + (mReason != null ? mReason : "");
            SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
        }
           
            //如果需要重启进入安全模式,则设置"persist.sys.safemode"=1
        if (mRebootSafeMode) {
            SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
        }

        shutdownTimingLog.traceBegin("DumpPreRebootInfo");
        try {
            Slog.i(TAG, "Logging pre-reboot information...");
            PreRebootLogger.log(mContext);
        } catch (Exception e) {
            Slog.e(TAG, "Failed to log pre-reboot information", e);
        }
        shutdownTimingLog.traceEnd(); // DumpPreRebootInfo

        metricStarted(METRIC_SEND_BROADCAST);
        shutdownTimingLog.traceBegin("SendShutdownBroadcast");
        Log.i(TAG, "Sending shutdown broadcast...");

        //首先发送关机广播
        mActionDone = false;
        Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        mContext.sendOrderedBroadcastAsUser(intent,
                UserHandle.ALL, null, br, mHandler, 0, null, null);

        final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
        //MAX_BROADCAST_TIME=10S
        synchronized (mActionDoneSync) {
           //循环等待
            while (!mActionDone) {
                long delay = endTime - SystemClock.elapsedRealtime();
                if (delay <= 0) {
                    //超时退出
                    Log.w(TAG, "Shutdown broadcast timed out");
                    break;
                } else if (mRebootHasProgressBar) {
                    int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
                            BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
                    sInstance.setRebootProgress(status, null);
                }
                try {
                    //等待500s
                    mActionDoneSync.wait(Math.min(delay, ACTION_DONE_POLL_WAIT_MS));
                } catch (InterruptedException e) {
                }
            }
        }
        if (mRebootHasProgressBar) {
            sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
        }
        shutdownTimingLog.traceEnd(); // SendShutdownBroadcast
        metricEnded(METRIC_SEND_BROADCAST);

        Log.i(TAG, "Shutting down activity manager...");
        shutdownTimingLog.traceBegin("ShutdownActivityManager");
        metricStarted(METRIC_AM);
        //关闭AMS
        final IActivityManager am =
                IActivityManager.Stub.asInterface(ServiceManager.checkService("activity"));
        if (am != null) {
            try {
                am.shutdown(MAX_BROADCAST_TIME);
            } catch (RemoteException e) {
            }
        }
        if (mRebootHasProgressBar) {
            sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
        }
        shutdownTimingLog.traceEnd();// ShutdownActivityManager
        metricEnded(METRIC_AM);

        Log.i(TAG, "Shutting down package manager...");
        shutdownTimingLog.traceBegin("ShutdownPackageManager");
        metricStarted(METRIC_PM);

        final PackageManagerService pm = (PackageManagerService)
            ServiceManager.getService("package");
            //关闭PMS
        if (pm != null) {
            pm.shutdown();
        }
        if (mRebootHasProgressBar) {
            sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
        }
        shutdownTimingLog.traceEnd(); // ShutdownPackageManager
        metricEnded(METRIC_PM);

        // 关闭 radios.
        shutdownTimingLog.traceBegin("ShutdownRadios");
        metricStarted(METRIC_RADIOS);
        shutdownRadios(MAX_RADIO_WAIT_TIME);
        if (mRebootHasProgressBar) {
            sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
        }
        shutdownTimingLog.traceEnd(); // ShutdownRadios
        metricEnded(METRIC_RADIOS);

        if (mRebootHasProgressBar) {
            sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);

           //如果需要安装升级且没有触发过uncrypt方法,则立即触发
            uncrypt();
        }

        shutdownTimingLog.traceEnd(); // SystemServerShutdown
        metricEnded(METRIC_SYSTEM_SERVER);
        saveMetrics(mReboot, mReason);
        // Remaining work will be done by init, including vold shutdown
        //其余的剩下工作交给init进程完成
        rebootOrShutdown(mContext, mReboot, mReason);
    }

AMS.shutdown 关闭AMS

[frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java]

public boolean shutdown(int timeout) {
        //权限检查 检查
        if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires permission "
                    + android.Manifest.permission.SHUTDOWN);
        }

        final boolean timedout = mAtmInternal.shuttingDown(mBooted, timeout);

        mAppOpsService.shutdown();
        if (mUsageStatsService != null) {
            mUsageStatsService.prepareShutdown();
        }
        mBatteryStatsService.shutdown();
        synchronized (this) {
            mProcessStats.shutdownLocked();
        }

        return timedout;
    }

shuttingDown

[frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java]
public boolean shuttingDown(boolean booted, int timeout) {
            synchronized (mGlobalLock) {
                mShuttingDown = true;
                mRootActivityContainer.prepareForShutdown();
                //禁止WMS处理event
                updateEventDispatchingLocked(booted);
                //将最近任务写入磁盘,等待开机挂起
                notifyTaskPersisterLocked(null, true);
                //调用ASS处理shutdown
                return mStackSupervisor.shutdownLocked(timeout);
            }
        }

PMS.shutdown 关闭PMS

[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
public void shutdown() {
        mPackageUsage.writeNow(mPackages);
        mCompilerStats.writeNow();
        mDexManager.writePackageDexUsageNow();
        PackageWatchdog.getInstance(mContext).writeNow();

        // 将没有存盘的的限制配置进行存盘操作
        synchronized (mPackages) {
            if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
                mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
                for (int userId : mDirtyUsers) {
                    mSettings.writePackageRestrictionsLPr(userId);
                }
                mDirtyUsers.clear();
            }
        }
    }

shutdownRadios

[frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java]
private void shutdownRadios(final int timeout) {
        
        //如果radio被截断,关闭它可能会阻塞,所以选用另一个线程来处理
        final long endTime = SystemClock.elapsedRealtime() + timeout;
        final boolean[] done = new boolean[1];
        Thread t = new Thread() {
            public void run() {
                TimingsTraceLog shutdownTimingsTraceLog = newTimingsLog();
                boolean radioOff;

                TelephonyManager telephonyManager = mContext.getSystemService(
                        TelephonyManager.class);

                radioOff = telephonyManager == null
                        || !telephonyManager.isAnyRadioPoweredOn();
                if (!radioOff) {
                    Log.w(TAG, "Turning off cellular radios...");
                    metricStarted(METRIC_RADIO);
                    telephonyManager.shutdownAllRadios(); //关闭所有radio
                }

                Log.i(TAG, "Waiting for Radio...");

                //等待 NFC Bluetooth radio
                long delay = endTime - SystemClock.elapsedRealtime();
                while (delay > 0) {
                    if (mRebootHasProgressBar) {
                        int status = (int)((timeout - delay) * 1.0 *
                                (RADIO_STOP_PERCENT - PACKAGE_MANAGER_STOP_PERCENT) / timeout);
                        status += PACKAGE_MANAGER_STOP_PERCENT;
                        sInstance.setRebootProgress(status, null);
                    }

                    if (!radioOff) {
                        radioOff = !telephonyManager.isAnyRadioPoweredOn();
                        if (radioOff) {
                            Log.i(TAG, "Radio turned off.");
                            metricEnded(METRIC_RADIO);
                            shutdownTimingsTraceLog
                                    .logDuration("ShutdownRadio", TRON_METRICS.get(METRIC_RADIO));
                        }
                    }

                    if (radioOff) {
                        Log.i(TAG, "Radio shutdown complete.");
                        done[0] = true;
                        break;
                    }
                    //每间隔100ms,check一次,直到nfc、bluetooth、radio全部关闭或者超时才会退出循环
                    SystemClock.sleep(RADIOS_STATE_POLL_SLEEP_MS);
                    delay = endTime - SystemClock.elapsedRealtime();
                }
            }
        };

        t.start();
        try {
            t.join(timeout);
        } catch (InterruptedException ex) {
        }
        if (!done[0]) {
            Log.w(TAG, "Timed out waiting for Radio shutdown.");
        }
    }

rebootOrShutdown

[frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java]
public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
        if (reboot) {
            Log.i(TAG, "Rebooting, reason: " + reason);
            PowerManagerService.lowLevelReboot(reason);
            Log.e(TAG, "Reboot failed, will attempt shutdown instead");
            reason = null;
        } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
            //关机前先震动
            Vibrator vibrator = new SystemVibrator(context);
            try {
                vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
            } catch (Exception e) {
                // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
                //振动失败不应中断关机。 只需要记录下log。
                Log.w(TAG, "Failed to vibrate during shutdown.", e);
            }

            // 震动器是异步的,我们只需要等待以避免过早的关闭
            try {
                Thread.sleep(SHUTDOWN_VIBRATE_MS);
            } catch (InterruptedException unused) {
            }
        }
        // 关机方法
        Log.i(TAG, "Performing low-level shutdown...");
        PowerManagerService.lowLevelShutdown(reason);
    }
  • reboot 为true则重启为false则关机
  • 对于重启原因 logcat会直接输出"Rebooting, reason: "
  • 如果重启失败,输出Reboot failed, will attempt shutdown instead(重启失败,尝试关机)
  • SHUTDOWN_VIBRATE_MS表示关机前震动的时间为500ms

lowLevelReboot

public static void lowLevelReboot(String reason) {
        if (reason == null) {
            reason = "";
        }

        
        if (reason.equals(PowerManager.REBOOT_QUIESCENT)) {
            sQuiescent = true;
            reason = "";
        } else if (reason.endsWith("," + PowerManager.REBOOT_QUIESCENT)) {
            sQuiescent = true;
            reason = reason.substring(0,
                    reason.length() - PowerManager.REBOOT_QUIESCENT.length() - 1);
        }

        if (reason.equals(PowerManager.REBOOT_RECOVERY)
                || reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) {
            reason = "recovery";
        }

        if (sQuiescent) {
            reason = reason + ",quiescent";
        }

        SystemProperties.set("sys.powerctl", "reboot," + reason);
        try {
            Thread.sleep(20 * 1000L);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        Slog.wtf(TAG, "Unexpected return from lowLevelReboot!");
    }

lowLevelShutdown

public static void lowLevelShutdown(String reason) {
        if (reason == null) {
            reason = "";
        }
        //这里其实相当于在命令行输入 adb shell setprop sys.powerctl reboot
        SystemProperties.set("sys.powerctl", "shutdown," + reason);
    }
  • 至此framework层的重启流程就结束了,接下来就是设置 sys.powerctl =root 然后进入native层
  • 其实最核心重启方法等价于调用 SystemProperties.set("sys.powerctl", "shutdown," + reason)也就是说
    在命令行输入 adb shell setprop sys.powerctl reboot也是可以完成关机操作

进入Native层