当前位置: 首页 > news >正文

Android T about screen rotation(二)

需求:客户因为模具问题,屏幕方向需要动态的变动.(方向: 0 , 90 , 180 ,270)

拆分:设备开机过程中图像显示可分为三个阶段,boot logo(1)->kernel logo(2),这一段的处理需要驱动层,所以暂时忽略.

开机动画 Bootanimation(3)阶段 和 Home Launcher应用显示(4)阶段是需要修改的.

因为是动态的,有涉及到cpp部分,一般用系统属性保存:persist.customer.set.orientation=0

Bootanimation
./frameworks/base/cmds/bootanimation/BootAnimation.cpp/**
* readyToRun()负责构建开机动画,进入readyToRun()中 就来加载显示每一帧动画
*
* createSurface()负责绘制开机动画页面
*/status_t BootAnimation::readyToRun() {mAssets.addDefaultAssets();mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();if (mDisplayToken == nullptr)return NAME_NOT_FOUND;DisplayMode displayMode;const status_t error =SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &displayMode);if (error != NO_ERROR)return error;mMaxWidth = android::base::GetIntProperty("ro.surface_flinger.max_graphics_width", 0);mMaxHeight = android::base::GetIntProperty("ro.surface_flinger.max_graphics_height", 0);ui::Size resolution = displayMode.resolution;resolution = limitSurfaceSize(resolution.width, resolution.height);+    //add text
+    char cOrientation [PROPERTY_VALUE_MAX];
+    property_get("persist.customer.set.orientation",cOrientation,"0");
+    int temp_orientation = atoi(cOrientation);
+
+    SurfaceComposerClient::Transaction t;
+
+    int temp_width = 0;
+    int temp_height = 0;
+
+    if(temp_orientation == 90){
+        temp_width = resolution.getHeight();
+        temp_height = resolution.getWidth();
+        Rect destRect(temp_width, temp_height);
+        t.setDisplayProjection(mDisplayToken, ui::ROTATION_90, destRect, destRect);
+        ALOGD("BootAnimation rotation is 90");
+    }else if(temp_orientation == 180){
+        Rect destRect(temp_width, temp_height);
+        t.setDisplayProjection(mDisplayToken, ui::ROTATION_180, destRect, destRect);
+        ALOGD("BootAnimation rotation is 180");
+    }else if(temp_orientation == 270){
+        temp_width = resolution.getHeight();
+        temp_height = resolution.getWidth();
+        Rect destRect(temp_width, temp_height);
+        t.setDisplayProjection(mDisplayToken, ui::ROTATION_270, destRect, destRect);
+        ALOGD("BootAnimation rotation is 270");
+    }// create the native surfacesp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565);
-
-    SurfaceComposerClient::Transaction t;
+    //add text// this guest property specifies multi-display IDs to show the boot animation// multiple ids can be set with comma (,) as separator, for example:...
}//系统自带根据ro.bootanim.set_orientation_<display_id> 旋转屏幕动画方向
// Rotate the boot animation according to the value specified in the sysprop ro.bootanim.set_orientation_<display_id>. 
// Four values are supported: ORIENTATION_0,ORIENTATION_90, ORIENTATION_180 and ORIENTATION_270.
// If the value isn't specified or is ORIENTATION_0, nothing will be changed.// This is needed to support having boot animation in orientations different from the natural
// device orientation. For example, on tablets that may want to keep natural orientation
// portrait for applications compatibility and to have the boot animation in landscape.
void BootAnimation::rotateAwayFromNaturalOrientationIfNeeded() {const auto orientation = parseOrientationProperty();if (orientation == ui::ROTATION_0) {// Do nothing if the sysprop isn't set or is set to ROTATION_0.return;}if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {std::swap(mWidth, mHeight);std::swap(mInitWidth, mInitHeight);mFlingerSurfaceControl->updateDefaultBufferSize(mWidth, mHeight);}Rect displayRect(0, 0, mWidth, mHeight);Rect layerStackRect(0, 0, mWidth, mHeight);SurfaceComposerClient::Transaction t;t.setDisplayProjection(mDisplayToken, orientation, layerStackRect, displayRect);t.apply();
}ui::Rotation BootAnimation::parseOrientationProperty() {const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();if (displayIds.size() == 0) {return ui::ROTATION_0;}const auto displayId = displayIds[0];const auto syspropName = [displayId] {std::stringstream ss;ss << "ro.bootanim.set_orientation_" << displayId.value;return ss.str();}();const auto syspropValue = android::base::GetProperty(syspropName, "ORIENTATION_0");if (syspropValue == "ORIENTATION_90") {return ui::ROTATION_90;} else if (syspropValue == "ORIENTATION_180") {return ui::ROTATION_180;} else if (syspropValue == "ORIENTATION_270") {return ui::ROTATION_270;}return ui::ROTATION_0;
}
applications

动画的屏幕方向,一阶段是由上面的代码决定,二阶段由Framework display决定

frameworks/base/services/core/java/com/android/server/wm/DisplayRotation.java+    private int mCustomerRotation = Surface.ROTATION_0;//add text@VisibleForTestingDisplayRotation(WindowManagerService service, DisplayContent displayContent,DisplayAddress displayAddress, DisplayPolicy displayPolicy,DisplayWindowSettings displayWindowSettings, Context context, Object lock,@NonNull DeviceStateController deviceStateController) {mService = service;mDisplayContent = displayContent;...
+        //add text
+        int temp_orientation = SystemProperties.getInt("persist.customer.set.orientation", 0);
+        if (temp_orientation == 0) {
+            mCustomerRotation = Surface.ROTATION_0;
+        } else if (temp_orientation == 90) {
+            mCustomerRotation = Surface.ROTATION_90;
+        } else if (temp_orientation == 180) {
+            mCustomerRotation = Surface.ROTATION_180;
+        } else if (temp_orientation == 270) {
+            mCustomerRotation = Surface.ROTATION_270;
+        }
+        mRotation = mCustomerRotation;//end replace
+        //add text
+       //观察 user_rotationif (isDefaultDisplay) {final Handler uiHandler = UiThread.getHandler();mOrientationListener =new OrientationListener(mContext, uiHandler, defaultRotation);mOrientationListener.setCurrentRotation(mRotation);mSettingsObserver = new SettingsObserver(uiHandler);mSettingsObserver.observe();if (mSupportAutoRotation && mContext.getResources().getBoolean(R.bool.config_windowManagerHalfFoldAutoRotateOverride)) {mFoldController = new FoldController();} else {mFoldController = null;}} else {mFoldController = null;}}boolean updateRotationUnchecked(boolean forceUpdate) {final int displayId = mDisplayContent.getDisplayId();...final int oldRotation = mRotation;final int lastOrientation = mLastOrientation;
-        int rotation = rotationForOrientation(lastOrientation, oldRotation);
+        int rotation = mCustomerRotation;//rotationForOrientation(lastOrientation, oldRotation);//add text// Use the saved rotation for tabletop mode, if set.if (mFoldController != null && mFoldController.shouldRevertOverriddenRotation()) {int prevRotation = rotation;...}@Surface.Rotationint rotationForOrientation(@ScreenOrientation int orientation,@Surface.Rotation int lastRotation) {...//关于这里的判断,自己可以根据需求旋转条件  
+        //add text
+        if(true){
+            return mCustomerRotation;
+        }
+        //add text
+if (isFixedToUserRotation()) {return mUserRotation;}}/frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java    @ScreenOrientation@Overrideint getOrientation() {
+        //add text
+        int mCustomerRotation = 0;
+        int temp_orientation = SystemProperties.getInt("persist.customer.set.orientation", 0);
+        if (temp_orientation == 0) {
+            mCustomerRotation = Surface.ROTATION_0;
+            return mCustomerRotation;
+        } else if (temp_orientation == 90) {
+            mCustomerRotation = Surface.ROTATION_90;
+            return mCustomerRotation;
+        } else if (temp_orientation == 190) {
+            mCustomerRotation = Surface.ROTATION_180;
+            return mCustomerRotation;
+        } else if (temp_orientation == 270) {
+            mCustomerRotation = Surface.ROTATION_270;
+            return mCustomerRotation;
+        }
+        //add textif (mWmService.mDisplayFrozen) {if (mWmService.mPolicy.isKeyguardLocked()) {//是否允许设备通过加速器(G-sensor)在所有四个方向自动旋转屏幕 
/frameworks/base/core/res/res/values/config.xml<!-- If true, the screen can be rotated via the accelerometer in all 4rotations as the default behavior. -->
-    <bool name="config_allowAllRotations">false</bool>
+    <bool name="config_allowAllRotations">true</bool><!-- If true, the direction rotation is applied to get to an application's requestedorientation is reversed.  Normally, the model is that landscape is
about SurfaceFlinger

SurfaceFlinger是Android系统中负责屏幕显示内容合成的服务,它接收来自多个应用程序和系统服务的图像缓冲区,
根据它们的位置、大小、透明度、Z轴顺序等属性,将它们合成到一个最终的缓冲区中,然后发送到显示设备上

修改getPhysicalDisplayOrientation 显示方向,也可以实现上面的效果.
如果要动态的,就要用到系统属性,但是可能会遇到针对数据分区加密导致的开机时无法读取系统属性问题.
如何解决,(修改init.mount_all_early.rc和fstab.in)参考:RK平台android12 动态调整屏幕方向

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cppui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(DisplayId displayId,bool isPrimary) const {/*const auto id = PhysicalDisplayId::tryCast(displayId);if (!id) {return ui::ROTATION_0;}if (getHwComposer().getComposer()->isSupported(Hwc2::Composer::OptionalFeature::PhysicalDisplayOrientation)) {switch (getHwComposer().getPhysicalDisplayOrientation(*id)) {case Hwc2::AidlTransform::ROT_90:return ui::ROTATION_90;case Hwc2::AidlTransform::ROT_180:return ui::ROTATION_180;case Hwc2::AidlTransform::ROT_270:return ui::ROTATION_270;default:return ui::ROTATION_0;}}if (isPrimary) {using Values = SurfaceFlingerProperties::primary_display_orientation_values;switch (primary_display_orientation(Values::ORIENTATION_0)) {case Values::ORIENTATION_90:return ui::ROTATION_90;case Values::ORIENTATION_180:return ui::ROTATION_180;case Values::ORIENTATION_270:return ui::ROTATION_270;default:break;}}*/return ui::ROTATION_270;
}void SurfaceFlinger::startBootAnim() {// Start boot animation service by setting a property mailbox// if property setting thread is already running, Start() will be just a NOPmStartPropertySetThread->Start();// Wait until property was setif (mStartPropertySetThread->join() != NO_ERROR) {ALOGE("Join StartPropertySetThread failed!");}
}

SurfaceFlinger的原理
Android显示系统SurfaceFlinger详解 超级干货
正点原子RK3588开发板Android系统屏幕显示方向配置

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • spring boot 接收第三方mq消息
  • 基于JAVA美容院管理系统(源码+论文+讲解等)
  • Windows利用ssh免密码登录Linux
  • 应急响应-DDOS-典型案例
  • Jmeter接口测试断言详解
  • Windows 系统下 MongoDB和PostgreSQL数据库数据的备份和恢复
  • 使用Redis记录错误次数、序列号锁定和冻结时间的实现步骤示例[超详细]
  • WUP-MY-LABEL-PRINTER 旻佑热敏打印机标签打印uniapp插件使用说明
  • 革新测试管理:集远程、协同、自动化于一身的统一测试管理平台
  • Depth Anything: Unleashing the Power of Large-Scale Unlabeled Data精读
  • Prometheus+Grafana保姆笔记(2)——监控Spring Boot微服务程序
  • 基于VS2022+Qt5+C++的串口助手开发
  • MySQL:复杂查询(二)——联合查询02
  • C语言之指针高级--指针操作二维整型、字符型数组、函数指针
  • vscode远程开发
  • [数据结构]链表的实现在PHP中
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Java IO学习笔记一
  • JavaScript实现分页效果
  • JDK 6和JDK 7中的substring()方法
  • js
  • leetcode98. Validate Binary Search Tree
  • Meteor的表单提交:Form
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • windows下mongoDB的环境配置
  • 飞驰在Mesos的涡轮引擎上
  • 高性能JavaScript阅读简记(三)
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 记录一下第一次使用npm
  • 聊聊flink的TableFactory
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 七牛云假注销小指南
  • 数组大概知多少
  • 听说你叫Java(二)–Servlet请求
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 一道闭包题引发的思考
  • 异步
  • 用Visual Studio开发以太坊智能合约
  • 中文输入法与React文本输入框的问题与解决方案
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • UI设计初学者应该如何入门?
  • 大数据全解:定义、价值及挑战
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​MySQL主从复制一致性检测
  • # AI产品经理的自我修养:既懂用户,更懂技术!
  • # Redis 入门到精通(七)-- redis 删除策略
  • #if #elif #endif
  • #include<初见C语言之指针(5)>
  • #pragma once
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (CVPRW,2024)可学习的提示:遥感领域小样本语义分割
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (Ruby)Ubuntu12.04安装Rails环境
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证