当前位置:   article > 正文

OpenHarmony系统解决方案 - 锁屏引起的卡开机动画_openharmny 关闭锁屏

openharmny 关闭锁屏

问题描述

问题环境

系统版本:OpenHarmony-3.2-Release

问题现象

设备接通电源,开机动画正常播放结束,长时间静止在开机动画结束界面,无法正常进入系统。

问题原因

  • 设备性能导致的锁屏应用未在锁屏服务检测监听事件的时间段内启动完成,导致无法触发关闭开机动画。
  • 系统不需要锁屏应用,把锁屏应用删除后,未移除锁屏服务(theme_screenlock_mgr)导致无法触发关闭开机动画。

解决方案

针对设备性能问题的解决方案

调整锁屏检测次数,增加锁屏检测的时间,保证可以在锁屏应用启动后正常设置系统参数bootevent.lockscreen.readytrue

根据设备性能调整OnSystemReady函数的tryTime变量数值,服务会间隔1S执行检测锁屏应用是否成功注册监听,并执行回调。如果超过检测次数,则会一直处于开机动画界面。

  1. // base/theme/screenlock_mgr/services/src/screenlock_system_ability.cpp
  2. void ScreenLockSystemAbility::OnSystemReady()
  3. {
  4. SCLOCK_HILOGI("ScreenLockSystemAbility OnSystemReady started.");
  5. bool isExitFlag = false;
  6. int tryTime = 20; // 根据设备性能调整此处尝试次数
  7. int minTryTime = 0;
  8. while (!isExitFlag && (tryTime > minTryTime)) {
  9. if (systemEventListener_ != nullptr) {
  10. SCLOCK_HILOGI("ScreenLockSystemAbility OnSystemReady started1.");
  11. std::lock_guard<std::mutex> lck(listenerMutex_);
  12. SystemEvent systemEvent(SYSTEM_READY);
  13. systemEventListener_->OnCallBack(systemEvent);
  14. isExitFlag = true;
  15. } else {
  16. SCLOCK_HILOGE("ScreenLockSystemAbility OnSystemReady type not found., flag_ = %{public}d", flag_);
  17. sleep(1);
  18. }
  19. --tryTime;
  20. }
  21. }

针对删除锁屏应用的解决方案

移除锁屏服务(screenlock_mgr)组件,以RK3568编译配置为例。需在编译配置文件productdefine/common/inherit/rich.json中删除screenlock_mgr组件的编译配置。以下为删除后的theme编译配置。

  1. {
  2. "version": "3.0",
  3. "subsystems": [
  4. ···
  5. {
  6. "subsystem": "theme",
  7. "components": [
  8. {
  9. "component": "wallpaper_mgr",
  10. "features": []
  11. }
  12. ]
  13. },
  14. ···
  15. ]
  16. }

如果需要保留锁屏服务,则需删除锁屏服务开机检测项bootevents,配置项位于base/theme/screenlock_mgr/etc/init/screenlockservice.cfg

定位过程

1. 开机动画退出逻辑,当开机动画获取到bootevent.boot.completed属性为true时,退出开机动画。

  1. // foundation/graphic/graphic_2d/frameworks/bootanimation/src/boot_animation.cpp
  2. void BootAnimation::CheckExitAnimation()
  3. {
  4. LOGI("CheckExitAnimation enter");
  5. if (!setBootEvent_) {
  6. LOGI("CheckExitAnimation set bootevent parameter");
  7. system::SetParameter("bootevent.bootanimation.started", "true");
  8. setBootEvent_ = true;
  9. }
  10. std::string windowInit = system::GetParameter("bootevent.boot.completed", "false");
  11. if (windowInit == "true") {
  12. PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
  13. LOGI("CheckExitAnimation read windowInit is true");
  14. return;
  15. }
  16. }

2. 开机启动服务组件会收集设备服务开机配置信息中的bootevents配置,并统计数量后赋值变量g_bootEventNum。当系统参数被设置时,过滤bootevent字段,调用下方函数进行g_bootEventNum--。当数量变为0时则将bootevent.bootanimation.started设置为true

  1. // base/startup/init/services/modules/bootevent.c
  2. #define BOOT_EVENT_BOOT_COMPLETED "bootevent.boot.completed"
  3. static void BootEventParaFireByName(const char *paramName){
  4. ListNode *found = NULL;
  5. char *bootEventValue = strrchr(paramName, '.');
  6. if (bootEventValue == NULL) {
  7. return;
  8. }
  9. bootEventValue[0] = '\0';
  10. found = OH_ListFind(&bootEventList, (void *)paramName, BootEventParaListCompareProc);
  11. if (found == NULL) {
  12. return;
  13. }
  14. if (((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY].tv_sec != 0) {
  15. return;
  16. }
  17. INIT_CHECK_ONLY_RETURN(clock_gettime(CLOCK_MONOTONIC,
  18. &(((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY])) == 0);
  19. g_bootEventNum--;
  20. // Check if all boot event params are fired
  21. if (g_bootEventNum > 0) {
  22. return;
  23. }
  24. // All parameters are fired, set boot completed now ...
  25. INIT_LOGI("All boot events are fired, boot complete now ...");
  26. SystemWriteParam(BOOT_EVENT_BOOT_COMPLETED, "true"); // 设置 bootevent.boot.completed 参数为 true
  27. g_bootEventEnable = BOOT_EVENT_FINISH;
  28. SaveServiceBootEvent();
  29. const char *clearBootEventArgv[] = {"bootevent"};
  30. // clear servie extra data
  31. PluginExecCmd("clear", ARRAY_LENGTH(clearBootEventArgv), clearBootEventArgv);
  32. return;
  33. }

3. 查看锁屏服务开机配置,存在bootevents配置项。

  1. // base/theme/screenlock_mgr/etc/init/screenlockservice.cfg
  2. {
  3. ···
  4. "services" : [{
  5. ···
  6. "bootevents" : ["bootevent.lockscreen.ready"]
  7. }
  8. ]
  9. }

4. 通过shell查看系统中的参数。发现bootevent.lockscreen.ready参数未被设置。

param get | grep bootevent

5. 尝试手动添加参数,判断是否为此问题。如果可以正常退出开机动画,则确定是由于锁屏参数未设置导致的此问题。

param set bootevent.lockscreen.ready true

6. 查看锁屏应用源码,应用启动后会注册ScreenLockMar.onSystemEvent事件。事件注册后,当触发systemReady设置时,会将bootevent.lockscreen.ready参数设置为true

  1. // applications/standard/screenlock/features/screenlock/src/main/ets/com/ohos/model/screenLockModel.ts
  2. export default class ScreenLockModel {
  3. @SysFaultLogger({FAULT_ID: FaultID.SCREEN_LOCK_MANAGER, MSG: "call func on failed"})
  4. eventListener(callback: Callback<String>) {
  5. let isSuccess = ScreenLockMar.onSystemEvent((err, event) => {
  6. Log.showInfo(TAG, `eventListener:callback:${event.eventType}`)
  7. callback(event.eventType);
  8. if (err) {
  9. Log.showError(TAG, `on callback error -> ${JSON.stringify(err)}`);
  10. }
  11. });
  12. if (!isSuccess) {
  13. callback('serviceRestart');
  14. }
  15. }
  16. ···
  17. }
  18. // applications/standard/screenlock/features/screenlock/src/main/ets/com/ohos/model/screenLockService.ts
  19. const EVENT_SYSTEM_READY: string = 'systemReady'
  20. ···
  21. export class ScreenLockService {
  22. monitorEvents() {
  23. ···
  24. this.screenLockModel.eventListener((typeName: String) => {
  25. switch (typeName) {
  26. // System ready on device boot
  27. case EVENT_SYSTEM_READY:
  28. Log.showInfo(TAG, `EVENT_SYSTEM_READY event`);
  29. this.lockScreen();
  30. break;
  31. })
  32. ···
  33. }
  34. lockScreen() {
  35. ···
  36. this.screenLockModel.showScreenLockWindow(() => {
  37. ···
  38. if (this.currentLockStatus == ScreenLockStatus.Locking) {
  39. Log.showInfo(TAG, `had locked, no need to publish lock_screen`);
  40. } else {
  41. this.notifyLockScreenResult(LockResult.Success)
  42. this.publishByUser("common.event.LOCK_SCREEN", this.accountModel.getCurrentUserId());
  43. setTimeout(() => {
  44. systemParameter.set('bootevent.lockscreen.ready','true')
  45. }, 1000);
  46. this.currentLockStatus = ScreenLockStatus.Locking;
  47. }
  48. });
  49. }
  50. }

7. 在锁屏服务中遍历判断是否有systemEventListener_的监听,如果有systemReady事件将被触发。而systemEventListener_则是由步骤6中锁屏应用设置,形成闭环。

  1. // base/theme/screenlock_mgr/services/src/screenlock_system_ability.cpp
  2. void ScreenLockSystemAbility::OnSystemReady()
  3. {
  4. SCLOCK_HILOGI("ScreenLockSystemAbility OnSystemReady started.");
  5. bool isExitFlag = false;
  6. int tryTime = 20;
  7. int minTryTime = 0;
  8. while (!isExitFlag && (tryTime > minTryTime)) {
  9. if (systemEventListener_ != nullptr) {
  10. SCLOCK_HILOGI("ScreenLockSystemAbility OnSystemReady started1.");
  11. std::lock_guard<std::mutex> lck(listenerMutex_);
  12. SystemEvent systemEvent(SYSTEM_READY);
  13. systemEventListener_->OnCallBack(systemEvent);
  14. isExitFlag = true;
  15. } else {
  16. SCLOCK_HILOGE("ScreenLockSystemAbility OnSystemReady type not found., flag_ = %{public}d", flag_);
  17. sleep(1);
  18. }
  19. --tryTime;
  20. }
  21. }

8. 落盘开机Log查看日志ScreenLockSystemAbility OnSystemReady type not found., flag_ = %{public}d日志的打印数量,如果为20条则确定是由于锁屏应用未在检测结束前注册监听导致。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/287188
推荐阅读
相关标签
  

闽ICP备14008679号