• Android 14.0 系统强制app横屏显示功能实现


    1.概述

    在14.0系统产品rom定制化开发中,对于处理屏幕旋转方向,首先有kernel底层处理,从底层驱动gsensor 中获取数据,从而判断屏幕方向的,
    然后事件上报后 最后由WMS就是WindowManagerService 来处理旋转的相关事件,接下来看下强制app横屏显示功能如何实现

    2.系统强制app横屏显示功能实现的核心类

    framework/base/services/java/com/android/server/wm/DisplayRotation.java

    3.系统强制app横屏显示功能实现的核心功能分析和处理

    在系统中wms主要是处理屏幕相关的核心类,WMS中在处理屏幕自动旋转,主要是调用
    DisplayRotation的freezeRotation方法锁定用户指定的屏幕方向,调用thawRotation方法,解锁用户固定屏幕,
    恢复屏幕自动旋转。最后调用updateRotationUnchecked,发送新的Configuration变化,
    以及如果布局发生变化,也会重新计算布局。

    通过上述源码分析,在系统中关于处理屏幕方法的系统中就是DisplayRotation.java 里负责处理的,这里根据系统当前的旋转方向
    具体需要看源码然后分析具体的旋转功能

    1. int rotationForOrientation(@ScreenOrientation int orientation,
    2. @Surface.Rotation int lastRotation) {
    3. if (isFixedToUserRotation()) {
    4. return mUserRotation;
    5. }
    6. int sensorRotation = mOrientationListener != null
    7. ? mOrientationListener.getProposedRotation() // may be -1
    8. : -1;
    9. if (sensorRotation < 0) {
    10. sensorRotation = lastRotation;
    11. }
    12. final int lidState = mDisplayPolicy.getLidState();
    13. final int dockMode = mDisplayPolicy.getDockMode();
    14. final boolean hdmiPlugged = mDisplayPolicy.isHdmiPlugged();
    15. final boolean carDockEnablesAccelerometer =
    16. mDisplayPolicy.isCarDockEnablesAccelerometer();
    17. final boolean deskDockEnablesAccelerometer =
    18. mDisplayPolicy.isDeskDockEnablesAccelerometer();
    19. final int preferredRotation;
    20. if (!isDefaultDisplay) {
    21. preferredRotation = mUserRotation;
    22. } else if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
    23. preferredRotation = mLidOpenRotation;
    24. } else if (dockMode == Intent.EXTRA_DOCK_STATE_CAR
    25. && (carDockEnablesAccelerometer || mCarDockRotation >= 0)) {
    26. preferredRotation = carDockEnablesAccelerometer ? sensorRotation : mCarDockRotation;
    27. } else if ((dockMode == Intent.EXTRA_DOCK_STATE_DESK
    28. || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
    29. || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
    30. && (deskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
    31. preferredRotation = deskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation;
    32. } else if (hdmiPlugged && mDemoHdmiRotationLock) {
    33. preferredRotation = mDemoHdmiRotation;
    34. } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
    35. && mUndockedHdmiRotation >= 0) {
    36. preferredRotation = mUndockedHdmiRotation;
    37. } else if (mDemoRotationLock) {
    38. preferredRotation = mDemoRotation;
    39. } else if (mDisplayPolicy.isPersistentVrModeEnabled()) {
    40. preferredRotation = mPortraitRotation;
    41. } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
    42. preferredRotation = lastRotation;
    43. } else if (!mSupportAutoRotation) {
    44. preferredRotation = -1;
    45. } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
    46. && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
    47. || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
    48. || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
    49. || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
    50. || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
    51. || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
    52. || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
    53. || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
    54. || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
    55. if (mAllowAllRotations == ALLOW_ALL_ROTATIONS_UNDEFINED) {
    56. mAllowAllRotations = mContext.getResources().getBoolean(
    57. R.bool.config_allowAllRotations)
    58. ? ALLOW_ALL_ROTATIONS_ENABLED
    59. : ALLOW_ALL_ROTATIONS_DISABLED;
    60. }
    61. if (sensorRotation != Surface.ROTATION_180
    62. || mAllowAllRotations == ALLOW_ALL_ROTATIONS_ENABLED
    63. || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
    64. || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
    65. preferredRotation = sensorRotation;
    66. } else {
    67. preferredRotation = lastRotation;
    68. }
    69. } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
    70. && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
    71. && orientation != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
    72. && orientation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    73. && orientation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
    74. && orientation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) {
    75. preferredRotation = mUserRotation;
    76. } else {
    77. // No overriding preference.
    78. // We will do exactly what the application asked us to do.
    79. preferredRotation = -1;
    80. }
    81. switch (orientation) {
    82. case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
    83. // Return portrait unless overridden.
    84. if (isAnyPortrait(preferredRotation)) {
    85. return preferredRotation;
    86. }
    87. return mPortraitRotation;
    88. case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
    89. // Return landscape unless overridden.
    90. if (isLandscapeOrSeascape(preferredRotation)) {
    91. return preferredRotation;
    92. }
    93. return mLandscapeRotation;
    94. case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
    95. // Return reverse portrait unless overridden.
    96. if (isAnyPortrait(preferredRotation)) {
    97. return preferredRotation;
    98. }
    99. return mUpsideDownRotation;
    100. case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
    101. // Return seascape unless overridden.
    102. if (isLandscapeOrSeascape(preferredRotation)) {
    103. return preferredRotation;
    104. }
    105. return mSeascapeRotation;
    106. case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
    107. case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
    108. // Return either landscape rotation.
    109. if (isLandscapeOrSeascape(preferredRotation)) {
    110. return preferredRotation;
    111. }
    112. if (isLandscapeOrSeascape(lastRotation)) {
    113. return lastRotation;
    114. }
    115. return mLandscapeRotation;
    116. case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
    117. case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
    118. // Return either portrait rotation.
    119. if (isAnyPortrait(preferredRotation)) {
    120. return preferredRotation;
    121. }
    122. if (isAnyPortrait(lastRotation)) {
    123. return lastRotation;
    124. }
    125. return mPortraitRotation;
    126. default:
    127. if (preferredRotation >= 0) {
    128. return preferredRotation;
    129. }
    130. return Surface.ROTATION_0;
    131. }
    132. }

    在上述的DisplayRotation.java的相关源码中分析得知,系统在开机过程中,首选在wms中先调用rotationForOrientation函数来获取rotation,来获取当前屏幕的旋转方向,获取当前的屏幕方向后,在根据当前屏幕方向来进行具体的系统方向旋转,最终会调用到
    rotationForOrientation(int orientation, int lastRotation) 来获取屏幕的方向值,在具体负责处理app具体的方向旋转当app进入
    到activity后由rotationForOrientation()来判断屏幕需要显示的方向,最后处理屏幕的具体旋转方向
    具体是在

    1. switch (orientation) {
    2. case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
    3. // Return portrait unless overridden.
    4. if (isAnyPortrait(preferredRotation)) {
    5. return preferredRotation;
    6. }
    7. - return mPortraitRotation;
    8. + return Surface.ROTATION_90;
    9. case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
    10. // Return landscape unless overridden.
    11. if (isLandscapeOrSeascape(preferredRotation)) {
    12. return preferredRotation;
    13. }
    14. return mLandscapeRotation;
    15. case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
    16. // Return reverse portrait unless overridden.
    17. if (isAnyPortrait(preferredRotation)) {
    18. return preferredRotation;
    19. }
    20. return mUpsideDownRotation;
    21. case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
    22. // Return seascape unless overridden.
    23. if (isLandscapeOrSeascape(preferredRotation)) {
    24. return preferredRotation;
    25. }
    26. return mSeascapeRotation;

    在上述的DisplayRotation.java的相关源码中分析得知,系统判定屏幕旋转方向具体是在rotationForOrientation(int orientation, int lastRotation) 中
    当处理屏幕旋转方向时,根据当前屏幕旋转的方向,需要处理是根据
    case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT的时候,判断当前需要旋转到什么方向,
    这时候系统在进入app的时候当设置屏幕方向的时候,如果需要横屏显示这时候就需要设置方向旋转90度,所以在上面判断如果当前是竖屏,在这里设置旋转90的屏幕方向就可以了从而实现功能

  • 相关阅读:
    Docker 安装 Nginx 容器 (完整详细版)
    使用 Docker Compose V2 快速搭建日志分析平台 ELK (Elasticsearch、Logstash 和 Kibana)
    Mybatis - Spring整合后一级缓存失效了
    AGV小车、机械臂协同作业实战06-任务分配算法(图解蚁群算法)代码示例java
    Linux命令基础
    云原生消息流系统 Apache RocketMQ 在腾讯云的大规模生产实践
    [激光原理与应用-21]:《激光原理与技术》-7- 激光技术大汇总与总体概述
    【SpringBoot3.x教程03】SpringBoot自动配置详解
    FPGA----ZCU106基于axi-hp通道的pl与ps数据交互(全网唯一最详)
    【无标Spring Boot (十五): Spring Boot + Jpa + Thymeleaf 增删改查示例题】
  • 原文地址:https://blog.csdn.net/baidu_41666295/article/details/136390017