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 里负责处理的,这里根据系统当前的旋转方向

具体需要看源码然后分析具体的旋转功能

    int rotationForOrientation(@ScreenOrientation int orientation,
              @Surface.Rotation int lastRotation) {
  
          if (isFixedToUserRotation()) {
              return mUserRotation;
          }
  
          int sensorRotation = mOrientationListener != null
                  ? mOrientationListener.getProposedRotation() // may be -1
                  : -1;
          if (sensorRotation < 0) {
              sensorRotation = lastRotation;
          }
  
          final int lidState = mDisplayPolicy.getLidState();
          final int dockMode = mDisplayPolicy.getDockMode();
          final boolean hdmiPlugged = mDisplayPolicy.isHdmiPlugged();
          final boolean carDockEnablesAccelerometer =
                  mDisplayPolicy.isCarDockEnablesAccelerometer();
          final boolean deskDockEnablesAccelerometer =
                  mDisplayPolicy.isDeskDockEnablesAccelerometer();
  
          final int preferredRotation;
          if (!isDefaultDisplay) {
              preferredRotation = mUserRotation;
          } else if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
              preferredRotation = mLidOpenRotation;
          } else if (dockMode == Intent.EXTRA_DOCK_STATE_CAR
                  && (carDockEnablesAccelerometer || mCarDockRotation >= 0)) {
              preferredRotation = carDockEnablesAccelerometer ? sensorRotation : mCarDockRotation;
          } else if ((dockMode == Intent.EXTRA_DOCK_STATE_DESK
                  || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
                  || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
                  && (deskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
              preferredRotation = deskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation;
          } else if (hdmiPlugged && mDemoHdmiRotationLock) {
              preferredRotation = mDemoHdmiRotation;
          } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
                  && mUndockedHdmiRotation >= 0) {
              preferredRotation = mUndockedHdmiRotation;
          } else if (mDemoRotationLock) {
              preferredRotation = mDemoRotation;
          } else if (mDisplayPolicy.isPersistentVrModeEnabled()) {
              preferredRotation = mPortraitRotation;
          } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
              preferredRotation = lastRotation;
          } else if (!mSupportAutoRotation) {
              preferredRotation = -1;
          } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
                          && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
                                  || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
                                  || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
                                  || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
                                  || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
                  || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
                  || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
                  || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
                  || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
              if (mAllowAllRotations == ALLOW_ALL_ROTATIONS_UNDEFINED) {
                  mAllowAllRotations = mContext.getResources().getBoolean(
                          R.bool.config_allowAllRotations)
                                  ? ALLOW_ALL_ROTATIONS_ENABLED
                                  : ALLOW_ALL_ROTATIONS_DISABLED;
              }
              if (sensorRotation != Surface.ROTATION_180
                      || mAllowAllRotations == ALLOW_ALL_ROTATIONS_ENABLED
                      || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
                      || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
                  preferredRotation = sensorRotation;
              } else {
                  preferredRotation = lastRotation;
              }
          } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
                  && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
                  && orientation != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                  && orientation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
                  && orientation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
                  && orientation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) {
              preferredRotation = mUserRotation;
          } else {
              // No overriding preference.
              // We will do exactly what the application asked us to do.
              preferredRotation = -1;
          }
  
          switch (orientation) {
              case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
                  // Return portrait unless overridden.
                  if (isAnyPortrait(preferredRotation)) {
                      return preferredRotation;
                  }
                  return mPortraitRotation;
  
              case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
                  // Return landscape unless overridden.
                  if (isLandscapeOrSeascape(preferredRotation)) {
                      return preferredRotation;
                  }
                  return mLandscapeRotation;
  
              case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
                  // Return reverse portrait unless overridden.
                  if (isAnyPortrait(preferredRotation)) {
                      return preferredRotation;
                  }
                  return mUpsideDownRotation;
  
              case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
                  // Return seascape unless overridden.
                  if (isLandscapeOrSeascape(preferredRotation)) {
                      return preferredRotation;
                  }
                  return mSeascapeRotation;
  
              case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
              case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
                  // Return either landscape rotation.
                  if (isLandscapeOrSeascape(preferredRotation)) {
                      return preferredRotation;
                  }
                  if (isLandscapeOrSeascape(lastRotation)) {
                      return lastRotation;
                  }
                  return mLandscapeRotation;
  
              case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
              case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
                  // Return either portrait rotation.
                  if (isAnyPortrait(preferredRotation)) {
                      return preferredRotation;
                  }
                  if (isAnyPortrait(lastRotation)) {
                      return lastRotation;
                  }
                  return mPortraitRotation;
  
              default:
                  if (preferredRotation >= 0) {
                      return preferredRotation;
                  }
                  return Surface.ROTATION_0;
          }
      }

在上述的DisplayRotation.java的相关源码中分析得知,系统在开机过程中,首选在wms中先调用rotationForOrientation函数来获取rotation,来获取当前屏幕的旋转方向,获取当前的屏幕方向后,在根据当前屏幕方向来进行具体的系统方向旋转,最终会调用到

rotationForOrientation(int orientation, int lastRotation) 来获取屏幕的方向值,在具体负责处理app具体的方向旋转当app进入

到activity后由rotationForOrientation()来判断屏幕需要显示的方向,最后处理屏幕的具体旋转方向

具体是在

            switch (orientation) {
                  case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
                      // Return portrait unless overridden.
                      if (isAnyPortrait(preferredRotation)) {
                          return preferredRotation;
                      }
                 -     return mPortraitRotation;
                 +     return Surface.ROTATION_90;
      
                  case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
                      // Return landscape unless overridden.
                      if (isLandscapeOrSeascape(preferredRotation)) {
                          return preferredRotation;
                      }
                      return mLandscapeRotation;
      
                  case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
                      // Return reverse portrait unless overridden.
                      if (isAnyPortrait(preferredRotation)) {
                          return preferredRotation;
                      }
                      return mUpsideDownRotation;
      
                  case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
                      // Return seascape unless overridden.
                      if (isLandscapeOrSeascape(preferredRotation)) {
                          return preferredRotation;
                      }
                      return mSeascapeRotation;

在上述的DisplayRotation.java的相关源码中分析得知,系统判定屏幕旋转方向具体是在rotationForOrientation(int orientation, int lastRotation) 中

当处理屏幕旋转方向时,根据当前屏幕旋转的方向,需要处理是根据

case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT的时候,判断当前需要旋转到什么方向,

这时候系统在进入app的时候当设置屏幕方向的时候,如果需要横屏显示这时候就需要设置方向旋转90度,所以在上面判断如果当前是竖屏,在这里设置旋转90的屏幕方向就可以了从而实现功能

相关推荐
GEEKVIP1 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
model20053 小时前
android + tflite 分类APP开发-2
android·分类·tflite
彭于晏6893 小时前
Android广播
android·java·开发语言
与衫4 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql
500了10 小时前
Kotlin基本知识
android·开发语言·kotlin
人工智能的苟富贵11 小时前
Android Debug Bridge(ADB)完全指南
android·adb
小雨cc5566ru16 小时前
uniapp+Android面向网络学习的时间管理工具软件 微信小程序
android·微信小程序·uni-app
bianshaopeng17 小时前
android 原生加载pdf
android·pdf
hhzz17 小时前
Linux Shell编程快速入门以及案例(Linux一键批量启动、停止、重启Jar包Shell脚本)
android·linux·jar
火红的小辣椒18 小时前
XSS基础
android·web安全