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