搜索
您的当前位置:首页正文

MTK平台关机流程和原因(二)

来源:筏尚旅游网

(1)ShutdownThread

从上一篇可以看到,最终会调用此类的shutdown以及reboot等函数,我们来看一下这些函数的实现。

(A)被调用函数

//frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java

public static void shutdown(final Context context, String reason, boolean confirm) {
        mReboot = false;
        mRebootSafeMode = false;
        mReason = reason;
        shutdownInner(context, confirm);
    }

public static void reboot(final Context context, String reason, boolean confirm) {
        mReboot = true;
        mRebootSafeMode = false;
        mRebootHasProgressBar = false;
        mReason = reason;
        shutdownInner(context, confirm);
    }

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);
    }

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) {
            // vibrate before shutting down
            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.w(TAG, "Failed to vibrate during shutdown.", e);
            }

            // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
            try {
                Thread.sleep(SHUTDOWN_VIBRATE_MS);
            } catch (InterruptedException unused) {
            }
        }

        ///M: added for shutdown Enhancement@{
        sInstance.mLowLevelShutdownSeq(context);
        /// @}
        // Shutdown power
        Log.i(TAG, "Performing low-level shutdown...");
        PowerManagerService.lowLevelShutdown(reason);
    }

(B)shutdownInner函数实现

接下来看一下shutdownInner内部实现。

private static void shutdownInner(final Context context, boolean confirm) {
        // ShutdownThread is called from many places, so best to verify here that the context passed
        // in is themed.
        context.assertRuntimeOverlayThemable();
        //xinghui add.avoid shutdown when monkey test.
        if (ActivityManager.isUserAMonkey()) {
            Log.d(TAG, "Cannot request to shutdown when Monkey is 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();

            if (mReboot && !mRebootSafeMode) {
                sConfirmDialog.setTitle(com.android.internal.R.string.global_action_restart);
                sConfirmDialog.setMessage(context.getText(com.android.internal.R.string.reboot_confirm_question));
            }

            closer.dialog = sConfirmDialog;
            sConfirmDialog.setOnDismissListener(closer);
            sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
            sConfirmDialog.show();
        } else {
            beginShutdownSequence(context);
        }
    }

由于这段代码融合了phone,TV,tablet等平台,所以字符串有不同的区分。

<string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"您的平板电脑会关闭。"</string>
<string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"您的 Android TV 设备将关闭。"</string>
<string name="shutdown_confirm" product="watch" msgid="2977299851200240146">"您的手表即将关机。"</string>
<string name="shutdown_confirm" product="default" msgid="136816458966692315">"您的手机将会关机。"</string>
<string name="shutdown_confirm_question" msgid="796151167261608447">"您要关机吗?"</string>

而具体是如何区分phone,TV,tablet等平台的,因为会根据系统的如下属性。

PRODUCT_CHARACTERISTICS := nosdcard
PRODUCT_CHARACTERISTICS := tv

ifndef PRODUCT_CHARACTERISTICS
   TARGET_AAPT_CHARACTERISTICS := default
 else
   TARGET_AAPT_CHARACTERISTICS := $(PRODUCT_CHARACTERISTICS)
 endif

ADDITIONAL_PRODUCT_PROPERTIES += ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)

(C)MTK重载的部分关机流程函数

这里要提一下,MTK平台有自定义部分关机流程函数,我们可以同步了解一下。

public class ShutdownThread extends Thread {

    protected boolean mIsShowShutdownSysui() {
        return true;
    }

    protected boolean mIsShowShutdownDialog(Context c) {
        return true;
    }
    //add by fenghuan for 开关机动画 end

    protected boolean mStartShutdownSeq(Context c, boolean IsReboot) {
        return true;
    }

    protected void mShutdownSeqFinish(Context c) {
        return;
    }

    protected void mLowLevelShutdownSeq(Context c) {
        return;
    }
}

(D)beginShutdownSequence函数实现

private static void beginShutdownSequence(Context context) {

        synchronized (sIsStartedGuard) {
            if (sIsStarted) {
                Log.d(TAG, "Shutdown sequence already running, returning.");
                return;
            }
            sIsStarted = true;
        }

        sInstance.mProgressDialog = showShutdownDialog(context);
        sInstance.mContext = context;
        sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);

        //...

        // start the thread that initiates shutdown
        sInstance.mHandler = new Handler() {
        };
        ///M: added for Shutdown Enhancement @{
        if(sInstance.mStartShutdownSeq(context, mReboot)) {
            sInstance.start();
        }
    }

(2)MtkShutdownThread

//vendor/mediatek/proprietary/frameworks/base/services/core/java/com/mediatek/server/MtkShutdownThread.java

public class MtkShutdownThread extends ShutdownThread {

	@Override
    protected boolean mIsShowShutdownSysui() {
        //...
        return true;
    }

    @Override
    protected boolean mIsShowShutdownDialog(Context context) {
        //...
        return true;
    }

    @Override
    protected boolean mStartShutdownSeq(Context context, boolean isReboot) {
        //...
        return true;
    }

    @Override
    protected void mShutdownSeqFinish(Context context) {
        //...
    }

    @Override
    protected void mLowLevelShutdownSeq(Context context) {
        //...
    }
}

(3)关机Log分析

大致关机Log如下:

03-30 07:48:25.865  1342  1342 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1
03-30 07:48:27.303  1342  1342 D ShutdownThread: Attempting to use SysUI shutdown UI
03-30 07:48:27.303  1342  1342 D ShutdownThread: SysUI handling shutdown UI

03-30 07:48:27.311  1342  1342 I MtkShutdownThread: hct screen turn off time shutdown_animation_play_time =6000
03-30 07:48:27.312  1342  1342 I MtkShutdownThread: screen turn off time screenTurnOffTime =6000

03-30 07:48:27.321  1342  7625 I ShutdownThread: Sending shutdown broadcast...
03-30 07:48:27.554  1342  7625 I ShutdownThread: Shutting down activity manager...
03-30 07:48:27.842  1342  7625 I ShutdownThread: Shutting down package manager...
03-30 07:48:27.888  1342  7630 W ShutdownThread: Turning off cellular radios...
03-30 07:48:27.902  1342  7630 I ShutdownThread: Waiting for Radio...
03-30 07:48:28.413  1342  7630 I ShutdownThread: Radio turned off.
03-30 07:48:28.414  1342  7630 I ShutdownThread: Radio shutdown complete.

03-30 07:48:28.415  1342  7625 I MtkShutdownThread: mShutOffAnimation: 1

03-30 07:48:28.418  1342  7625 I ShutdownThread: rebootOrShutdown:goToSleep
03-30 07:48:28.918  1342  7625 I ShutdownThread: Rebooting, reason: user requested

在boot_normal中可以看到开机原因。

//adb reboot
bootstat: Canonical boot reason: reboot,shell
bootstat: Last reboot reason read from /metadata/bootstat/persist.sys.boot.reason : reboot,shell. Last reboot reason read from persist.sys.boot.reason : reboot,shell
bootstat: Normalized last reboot reason : reboot,shell

//adb reboot -p
bootstat: Canonical boot reason: cold,powerkey
bootstat: Last reboot reason read from /metadata/bootstat/persist.sys.boot.reason : shutdown,shell. Last reboot reason read from persist.sys.boot.reason : shutdown,shell
bootstat: Normalized last reboot reason : shutdown,shell

//power键关机
bootstat: Canonical boot reason: cold,powerkey
bootstat: Last reboot reason read from /metadata/bootstat/persist.sys.boot.reason : shutdown,userrequested. Last reboot reason read from persist.sys.boot.reason : shutdown,userrequested
bootstat: Normalized last reboot reason : shutdown,userrequested

//power键重启
bootstat: Canonical boot reason: reboot,userrequested
bootstat: Last reboot reason read from /metadata/bootstat/persist.sys.boot.reason : reboot,userrequested. Last reboot reason read from persist.sys.boot.reason : reboot,userrequested
bootstat: Normalized last reboot reason : reboot,userrequested

因篇幅问题不能全部显示,请点此查看更多更全内容

Top