背景

项目中需要处理Android的原生开机动画,一定条件下还需要做到静默重启(android系统启动进入到桌面前,屏幕保持完全没有亮度的状态)。因为项目使用的rom是MTK平台支持,一开始并不知道Android 的QUIESCENT_REBOOT模式,所以自己想办法实现了此功能,详细见博客:基于Q的Android开机动画。因为后续Linux启用了SELinux增强了权限限制,原有的方案因为权限限制了文件的执行和读写,需要进行比较大的变动。后来,学习了下Android 的QUIESCENT_REBOOT模式,并把它用到了项目中解决了问题。这里介绍下QUIESCENT_REBOOT模式原理。

Android Quiescent的原理和流程

一、powerManager.reboot(PowerManager.REBOOT_QUIESCENT) 来静默重启(本地测试可以通过命令行触发svc power reboot quiescent)

1、代码:frameworks/base/core/java/android/os/PowerManager.java

public void reboot(String reason) {try {// mService是PowerManagerServicemService.reboot(false, reason, true);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}
}

2、代码frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

// True if the lights should stay off until an explicit user action.
// 这个标记记录是否静默重启
private static boolean sQuiescent;@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);......final long ident = Binder.clearCallingIdentity();try {shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);} finally {Binder.restoreCallingIdentity(ident);}
}private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,final String reason, boolean wait) {// lowLevelReboot会去解析reason并存储到SystemPropertiesif (mHandler == null || !mSystemReady) {if (RescueParty.isAttemptingFactoryReset()) {// If we're stuck in a really low-level reboot loop, and a// rescue party is trying to prompt the user for a factory data// reset, we must GET TO DA CHOPPA!PowerManagerService.lowLevelReboot(reason);} else {throw new IllegalStateException("Too early to call shutdown() or reboot()");}}// 调用ShutdownThread重启Runnable runnable = new Runnable() {@Overridepublic void run() {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);}}}};......
}public static void lowLevelReboot(String reason) {if (reason == null) {reason = "";}// If the reason is "quiescent", it means that the boot process should proceed// without turning on the screen/lights.// The "quiescent" property is sticky, meaning that any number// of subsequent reboots should honor the property until it is reset.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 (sQuiescent) {// Pass the optional "quiescent" argument to the bootloader to let it know// that it should not turn the screen/lights on.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!");
}

sQuiescent记录是否静默重启,lowLevelReboot会去解析reason并设置sQuiescent为true,同时把reason存储到SystemProperties,最后调用ShutdownThread带着reason传参。

3、代码frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
这个类中主要是根据一些条件做了一些单独处理,例如recovery等可能还会展示弹窗,这里有兴趣的可以根据代码路径自行观看,静默重启这个类中没有用到。

4、前边说到了SystemProperties.set(“sys.powerctl”, “reboot,” + reason),这里很重要。静默重启会把这个值存储到内核特定的启动参数,这个启动参数在下次重启时会被系统拿到。这里内部就涉及SystemProperties原理和源代码了,不特意分析,知道大概用做啥。

5、同时,内核还会解析reason,存储另一个SystemProperties;大概的流程是lk 中读到 rtc 的 Quiescent 标志位,则不显示开机logo,并且在 cmdline 中添加 androidboot.quiescent=1;lk -> kernel -> init,init 会解析 cmdline,并把其中的 androidboot.quiescent=1 解析出来,并设置成 ro.boot.quiescent=1,这样后续 Android 所有地方都能知道此次是 quiescent 开机。

6、bootanimation (frameworks/base/cmds/bootanimation) 中,读到 ro.boot.quiescent=1,则不显示开机动画
代码:frameworks/base/cmds/bootanimation/BootAnimationUtil.cpp

    bool bootAnimationDisabled() {45    char value[PROPERTY_VALUE_MAX];
46    property_get("debug.sf.nobootanimation", value, "0");
47    if (atoi(value) > 0) {48        return true;
49    }
50
51    property_get("ro.boot.quiescent", value, "0");
52    return atoi(value) > 0;
53}

代码:frameworks/base/cmds/bootanimation/bootanimation_main.cpp

36int main()
37{38    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
39    // 如果noBootAnimation,不展示开机动画
40    bool noBootAnimation = bootAnimationDisabled();
41    ALOGI_IF(noBootAnimation,  "boot animation disabled");
42    if (!noBootAnimation) {43
44        sp<ProcessState> proc(ProcessState::self());
45        ProcessState::self()->startThreadPool();
46
47        // create the boot animation object (may take up to 200ms for 2MB zip)
48        sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());
49
50        waitForSurfaceFlinger();
51
52        boot->run("BootAnimation", PRIORITY_DISPLAY);
53
54        ALOGV("Boot animation set up. Joining pool.");
55
56        IPCThreadState::self()->joinThreadPool();
57    }
58    return 0;
59}

7、这里还会涉及开机log的隐藏,在kernal层根据存储在内核的启动参数作为判断,隐藏logo或者亮度。这里大概属于猜测,具体有兴趣的可以自己深入研究。

解决项目中问题

项目中除了要隐藏开机动画,还需要把亮度调为最低。
1、需要把开机默认设置调度的代码给屏蔽掉
代码:frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java

    @VisibleForTestingDisplayManagerService(Context context, Injector injector) {super(context);......PowerManager pm = mContext.getSystemService(PowerManager.class);// 注释掉的为源代码,这里会取一个默认160的亮度并设置//mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();// 这里根据静默的参数,增加判断if (SystemProperties.getInt("ro.boot.quiescent", 0) == 0) {mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();}......}

2、因为除了这个地方会设置默认亮度,系统起来后还会被android层重新设置亮度,就恢复到正常亮度了。

android 静默重启 QUIESCENT REBOOT相关推荐

  1. android 系统重启关机 方法 非常好的一篇文章

    1.5 android 系统重启关机流程分析 1.5.1 c语言中调用 reboot 函数  HAL层中重启系统的方法 bionic/libc/unistd/reboot.c:33: 使用需要的头文件 ...

  2. android关机重启流程代码

    android关机重启流程,不能完全说是原创,只是自己一步步跟下来的学习总结. 1. frameworks/base/core/java/android/os/PowerManager.java pu ...

  3. android开关机日志_(android 关机/重启)Android关机/重启流程解析

    --------------------------------Introduction-------------------------- 1. 在PowerManager的API文档中,给出了一个 ...

  4. 轻松简单实现Android设备重启的两种方式

    " 须知少时凌云志,曾许人间第一流 " 在<风犬少年的天空>中刘闻钦下线时,嘴里念叨的就是这句,我们何尝不是这样的人呢,年轻时的凌云大志,曾决心要做人间第一流的人物,干 ...

  5. Android 添加重启菜单,修改关机菜单加入重启、重启至Recovery和重启至Bootloader

    invoke-static {v0, v2, v1}, Lcom/android/internal/app/ShutdownThread;->reboot(Landroid/content/Co ...

  6. android实现后台静默安装,Android 静默安装实现方法

    Android静默安装的方法,静默安装就是绕过安装程序时的提示窗口,直接在后台安装. 注意:静默安装的前提是设备有ROOT权限. 代码如下: /** * 静默安装 * @param file * @r ...

  7. android开发 重启app

    android开发 重启app 我们在android开发的过程中,可能遇到过这样的情况,当数据加载完成,或者从服务器下载文件完成,需要重启 app才会生效. 实现这个功能很简单,只需在需要重启的地方加 ...

  8. android 代码重启app

    android 代码重启app 方法 完事 方法 /*** 重启app* @param context*/public static void restartApp(Context context) ...

  9. android 自动重启测试,检测Android系统重启并生成测试用例的方法与流程

    本发明涉及软件技术领域,特别是一种检测Android系统重启并生成测试用例的方法. 背景技术: 目前安卓智能设备的功能越来越多,例如安卓智能电视或安卓智能盒子等,而在不同功能间交叉操作有概率触发And ...

最新文章

  1. MySQL半同步安装以及参数
  2. 材料成型计算机模拟第三版,材料成型计算机模拟考试复习资料.doc
  3. 转载 干货 | 1400篇机器学习的文章中,这10篇是最棒的!
  4. 干货|吴恩达Coursera课程教你学习神经网络二!
  5. [Leetcode][第112题][JAVA][路径总和][递归][队列]
  6. django 1.8 官方文档翻译:7-3 Django管理文档生成器
  7. arm 饱和指令_ARM Neon 指令 解释
  8. AntDesign前端分页
  9. 欢迎西南大学人工智能学院加入RICAI !!
  10. 栅格数据灰度化并前端转换展示
  11. IOS开发学习--(3)摇骰子APP
  12. *TEST 4 for NOIP 谨慎打表
  13. 大学生python心得1000字_大学生心得体会1000字
  14. Canvas 从 0 到 1 -- 开发 2D 游戏《保卫家园》-- 【上篇】
  15. uni保存canvas图片_UniApp 用canvas生成图片保存本地
  16. 【洛谷P3386】【模板】二分图匹配【网络流】
  17. php地铁,php 抓取自如友家首页的区域和地铁数据
  18. 【PhD Debate —11】矛与盾的对决——神经网络后门攻防
  19. firewall 防火墙
  20. 一位 40 岁“老程序员”的经历,给你们说一些我的真实想法!

热门文章

  1. 轻薄本市场已成PC新战场:新玩家的“杀入”与老玩家的“救赎”
  2. 利用路由器实现DHCP中继
  3. 怎么进行固态硬盘对拷?看看这里
  4. jpcsp java_【图片】【求助】安装java出现问题,运行jpcsp出现同样问题(看过置顶)【psp模拟器吧】_百度贴吧...
  5. 什么比国内现货白银更有优势?
  6. 计算机二级选择题与答案解析,计算机二级选择题及答案
  7. 易语言到字节集c,易语言自内存读写文本、字节集
  8. 《超级快速阅读》读后感
  9. 从入门到专家需要多久_行业入门-从专家的口中
  10. 软件安全测试最新2020,安全教育平台2020