11 开机动画和铃声 CTS 测试新增要求如下
google 本身的动画so是包含这块逻辑处理的,但是不能播放 mp3 类型铃声,使用 mtk 框架那套是不完整的
需要我们自己修改一下
软重启相关介绍可以看官方
测试指令
adb shell svc power reboot userspace
修改清单
frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java system/core/rootdir/init.rc vendor/mediatek/proprietary/operator/frameworks/bootanimation/MtkBootanimation/BootAnimation.cpp
增加标识用于关机时判断是否需要播放动画和铃声
frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
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. + if ("userspace".equals(mReason)) { + SystemProperties.set("sys.init.userspace_reboot.start", "1"); + } context.assertRuntimeOverlayThemable(); - + Log.i(TAG, "mReason1="+mReason); // ensure that only one thread is trying to power down. // any additional calls are just returned synchronized (sIsStartedGuard) {
userspace 操作重启成功后清空标识
system/core/rootdir/init.rc
@@ -1101,3 +1101,4 @@ on userspace-reboot-resume on property:sys.boot_completed=1 && property:sys.init.userspace_reboot.in_progress=1 setprop sys.init.userspace_reboot.in_progress "" + setprop sys.init.userspace_reboot.start ""
读取标识判断是否是 userspace 操作,符合则不播放铃声和动画,走默认的 android 字样 shimmer 动画
vendor/mediatek/proprietary/operator/frameworks/bootanimation/MtkBootanimation/BootAnimation.cpp
@@ -1469,6 +1476,14 @@ status_t BootAnimation::TimeCheckThread::readyToRun() { // --------------------------------------------------------------------------- const char* BootAnimation::initAudioPath() { + if (android::base::GetBoolProperty("sys.init.userspace_reboot.in_progress", false) + || android::base::GetBoolProperty("sys.init.userspace_reboot.start", false)) + { + ALOGD("initAudioPath: userspace_reboot no need"); + mZip = NULL; + mZipFileName = ""; + return NULL; + } if (!bPlayMP3) { ALOGD("initAudioPath: DON'T PLAY AUDIO!"); return NULL;
分析过程
先到谷歌原始框架中看看是怎么处理软重启场景动画播放逻辑
frameworks\base\cmds\bootanimation\BootAnimation.cpp
void BootAnimation::findBootAnimationFile() { ..... const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1; static const std::vector<std::string> bootFiles = { APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE, OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE }; static const std::vector<std::string> shutdownFiles = { PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, "" }; static const std::vector<std::string> userspaceRebootFiles = { PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE, OEM_USERSPACE_REBOOT_ANIMATION_FILE, SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE, }; if (android::base::GetBoolProperty("sys.init.userspace_reboot.in_progress", false)) { findBootAnimationFileInternal(userspaceRebootFiles); } else if (mShuttingDown) { findBootAnimationFileInternal(shutdownFiles); } else { findBootAnimationFileInternal(bootFiles); } }
sys.init.userspace_reboot.in_progress 这个值在执行软重启指令后会赋值
在 userspace-reboot-fs-remount 操作结束时,init 会启动 bootanim 服务。
此服务会按以下动画文件列出的顺序查找其是否存在,并播放找到的第一个动画:
/product/media/userspace-reboot.zip
/oem/media/userspace-reboot.zip
/system/media/userspace-reboot.zip
注意:动画文件必须遵循以下格式
如果未指定软重启的专用动画文件,bootanim 会显示默认的 android 动画。
经过搜索找到处理软重启指令入口,reboot.cpp
system\core\init\reboot.cpp
void HandlePowerctlMessage(const std::string& command) { unsigned int cmd = 0; std::vector<std::string> cmd_params = Split(command, ","); std::string reboot_target = ""; bool run_fsck = false; bool command_invalid = false; bool userspace_reboot = false; if (cmd_params[0] == "reboot") { cmd = ANDROID_RB_RESTART2; if (cmd_params.size() >= 2) { reboot_target = cmd_params[1]; if (reboot_target == "userspace") { LOG(INFO) << "Userspace reboot requested"; //软重启 true userspace_reboot = true; } ...... // We do not want to process any messages (queue'ing triggers, shutdown messages, control // messages, etc) from properties during reboot. StopSendingMessages(); if (userspace_reboot) { //处理软重启 HandleUserspaceReboot(); return; } LOG(INFO) << "Clear action queue and start shutdown trigger"; ActionManager::GetInstance().ClearQueue(); // Queue shutdown trigger first ActionManager::GetInstance().QueueEventTrigger("shutdown"); // Queue built-in shutdown_done auto shutdown_handler = [cmd, command, reboot_target, run_fsck](const BuiltinArguments&) { DoReboot(cmd, command, reboot_target, run_fsck); return Result<void>{}; }; ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done"); EnterShutdown(); } static void HandleUserspaceReboot() { if (!android::sysprop::InitProperties::is_userspace_reboot_supported().value_or(false)) { LOG(ERROR) << "Attempted a userspace reboot on a device that doesn't support it"; return; } // Spinnig up a separate thread will fail the setns call later in the boot sequence. // Fork a new process to monitor userspace reboot while we are investigating a better solution. pid_t pid = fork(); if (pid < 0) { PLOG(ERROR) << "Failed to fork process for userspace reboot watchdog. Switching to full " << "reboot"; trigger_shutdown("reboot,userspace_failed,watchdog_fork"); return; } if (pid == 0) { // Child #ifdef MTK_LOG PropSetLogReset(); #endif UserspaceRebootWatchdogThread(); _exit(EXIT_SUCCESS); } LOG(INFO) << "Clearing queue and starting userspace-reboot-requested trigger"; auto& am = ActionManager::GetInstance(); am.ClearQueue(); am.QueueEventTrigger("userspace-reboot-requested"); auto handler = [](const BuiltinArguments&) { return DoUserspaceReboot(); }; am.QueueBuiltinAction(handler, "userspace-reboot"); } //修改 sys.init.userspace_reboot.in_progress 标记同时执行关机 static Result<void> DoUserspaceReboot() { LOG(INFO) << "Userspace reboot initiated"; // An ugly way to pass a more precise reason on why fallback to hard reboot was triggered. std::string sub_reason = ""; auto guard = android::base::make_scope_guard([&sub_reason] { // Leave shutdown so that we can handle a full reboot. LeaveShutdown(); trigger_shutdown("reboot,userspace_failed,shutdown_aborted," + sub_reason); }); // Triggering userspace-reboot-requested will result in a bunch of setprop // actions. We should make sure, that all of them are propagated before // proceeding with userspace reboot. Synchronously setting sys.init.userspace_reboot.in_progress // property is not perfect, but it should do the trick. if (!android::sysprop::InitProperties::userspace_reboot_in_progress(true)) { sub_reason = "setprop"; return Error() << "Failed to set sys.init.userspace_reboot.in_progress property"; } EnterShutdown(); if (!SetProperty("sys.powerctl", "")) { sub_reason = "resetprop"; return Error() << "Failed to reset sys.powerctl property"; }