PAD默认屏幕显示方向是竖着显示,改成默认横屏显示需要将屏幕的默认显示方向顺时针旋转90度.

android显示系统的核心是surfaceflinger,它为所有的应用程序提供显示服务,它能够将各种应用程序的2D,3D surface进行组合,合并最终得到的一个main surface数据送入framebuffer,显示的翻转和旋转也是由surfaceflinger完成的,我们大致分析下surfaceflinger的旋转流程:

1.surfaceflinger启动后首先进行初始化操作,设置surfaceflinger的相关属性并创建了DisplayDevice对象

void SurfaceFlinger::init() {
...
#ifdef MTK_AOSP_ENHANCEMENT// make sure 3D init successif (mEGLContext == EGL_NO_CONTEXT){ALOGE("FATAL: couldn't create EGLContext");delete mHwc;eglTerminate(mEGLDisplay);exit(0);}// init properties setting firstsetMTKProperties();   //设置MTK相关属性
#elseLOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,"couldn't create EGLContext");
#endif
...// initialize our non-virtual displaysfor (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);// set-up the displays that are already connectedif (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {// All non-virtual displays are currently considered secure.bool isSecure = true;createBuiltinDisplayLocked(type);wp<IBinder> token = mBuiltinDisplays[i];sp<IGraphicBufferProducer> producer;sp<IGraphicBufferConsumer> consumer;BufferQueue::createBufferQueue(&producer, &consumer,new GraphicBufferAlloc());sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,consumer);int32_t hwcId = allocateHwcDisplayId(type);sp<DisplayDevice> hw = new DisplayDevice(this,  //初始化各个DisplayDevice对象type, hwcId, mHwc->getFormat(hwcId), isSecure, token,fbs, producer,mRenderEngine->getEGLConfig());if (i > DisplayDevice::DISPLAY_PRIMARY) {// FIXME: currently we don't get blank/unblank requests// for displays other than the main display, so we always// assume a connected display is unblanked.ALOGD("marking display %zu as acquired/unblanked", i);hw->setPowerMode(HWC_POWER_MODE_NORMAL);}mDisplays.add(token, hw);}}
}

setMTKProperties()中会设置surfaceflinger的相关属性:

void SurfaceFlinger::setMTKProperties(String8 &result) {
...// get info for panel physical rotationproperty_get("ro.sf.hwrotation", value, "0");sPropertiesState.mHwRotation = atoi(value);snprintf(buffer, sizeof(buffer), "    ro.sf.hwrotation (mHwRotation): %d\n", sPropertiesState.mHwRotation);result.append(buffer);
...
}

此处会读取 ro.sf.hwrotation系统属性,这个系统属性决定了显示屏的初始旋转方向,并保存到全局变量sPropertiesState.mHwRotation中

2.DisplayDevice中会调用显示的旋转函数setProjection()

DisplayDevice::DisplayDevice(const sp<SurfaceFlinger>& flinger,DisplayType type,int32_t hwcId,int format,bool isSecure,const wp<IBinder>& displayToken,const sp<DisplaySurface>& displaySurface,const sp<IGraphicBufferProducer>& producer,EGLConfig config)(
<span style="font-family: Arial, Helvetica, sans-serif;">...
</span><pre code_snippet_id="1939821" snippet_file_name="blog_20161020_4_9852155" name="code" class="cpp">#ifdef MTK_AOSP_ENHANCEMENTmHwOrientation = DisplayState::eOrientationDefault;   //读取默认的显示屏方向// Name the display.  The name will be replaced shortly if the display// was created with createDisplay().switch (mType) {case DISPLAY_PRIMARY:mDisplayName = "Built-in Screen";
#ifdef MTK_AOSP_ENHANCEMENTswitch (mFlinger->sPropertiesState.mHwRotation) {     //读取显示屏初始旋转方向case 90:mHwOrientation = DisplayState::eOrientation90;break;case 180:mHwOrientation = DisplayState::eOrientation180;break;case 270:mHwOrientation = DisplayState::eOrientation270;break;}
#endifbreak;case DISPLAY_EXTERNAL:mDisplayName = "HDMI Screen";break;default:mDisplayName = "Virtual Screen";    // e.g. Overlay #nbreak;}// initialize the display orientation transform.setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);  //设置显示屏初始旋转方向
}
void DisplayDevice::setProjection(int orientation,const Rect& newViewport, const Rect& newFrame) {Rect viewport(newViewport);Rect frame(newFrame);const int w = mDisplayWidth;const int h = mDisplayHeight;Transform R;DisplayDevice::orientationToTransfrom(orientation, w, h, &R);if (!frame.isValid()) {// the destination frame can be invalid if it has never been set,// in that case we assume the whole display frame.frame = Rect(w, h);}if (viewport.isEmpty()) {// viewport can be invalid if it has never been set, in that case// we assume the whole display size.// it's also invalid to have an empty viewport, so we handle that// case in the same way.viewport = Rect(w, h);if (R.getOrientation() & Transform::ROT_90) {// viewport is always specified in the logical orientation// of the display (ie: post-rotation).swap(viewport.right, viewport.bottom);}}dirtyRegion.set(getBounds());#ifdef MTK_AOSP_ENHANCEMENT// for boot animation black screen issueif ((false == mFlinger->getBootFinished()) && (DISPLAY_PRIMARY == mType)) {ALOGI("[%s] clear DisplayDevice(type:%d) dirty region while booting",__FUNCTION__, mType);dirtyRegion.clear();}
#endifTransform TL, TP, S;float src_width  = viewport.width();float src_height = viewport.height();float dst_width  = frame.width();float dst_height = frame.height();if (src_width != dst_width || src_height != dst_height) {float sx = dst_width  / src_width;float sy = dst_height / src_height;S.set(sx, 0, 0, sy);}float src_x = viewport.left;float src_y = viewport.top;float dst_x = frame.left;float dst_y = frame.top;TL.set(-src_x, -src_y);TP.set(dst_x, dst_y);#ifdef MTK_AOSP_ENHANCEMENT// need to take care of HW rotation for mGlobalTransform// for case if the panel is not installed align with device orientationif (DisplayState::eOrientationDefault != mHwOrientation) {    DisplayDevice::orientationToTransfrom((orientation + mHwOrientation) % (DisplayState::eOrientation270 + 1),w, h, &R);}
#endif// The viewport and frame are both in the logical orientation.// Apply the logical translation, scale to physical size, apply the// physical translation and finally rotate to the physical orientation.mGlobalTransform = R * TP * S * TL;const uint8_t type = mGlobalTransform.getType();mNeedsFiltering = (!mGlobalTransform.preserveRects() ||(type >= Transform::SCALE));mScissor = mGlobalTransform.transform(viewport);if (mScissor.isEmpty()) {mScissor = getBounds();}mOrientation = orientation;mViewport = viewport;mFrame = frame;
}

接着调用DisplayDevice类的orientationToTransfrom()方法构造成一个变换矩阵R,然后得到mGlobalTransform这个全局变换矩阵,最后通过mGlobalTransform.transform()这个方法进行显示的旋转

status_t DisplayDevice::orientationToTransfrom(int orientation, int w, int h, Transform* tr)
{uint32_t flags = 0;switch (orientation) {case DisplayState::eOrientationDefault:flags = Transform::ROT_0;break;case DisplayState::eOrientation90:flags = Transform::ROT_90;break;case DisplayState::eOrientation180:flags = Transform::ROT_180;break;case DisplayState::eOrientation270:flags = Transform::ROT_270;break;default:return BAD_VALUE;}tr->set(flags, w, h);return NO_ERROR;
}

这里调用Transform::set()方法设置矩阵,有兴趣可以深入分析

android屏幕旋转显示流程相关推荐

  1. Android屏幕旋转时Activity不重新调用onCreate的方法

    2019独角兽企业重金招聘Python工程师标准>>> android屏幕旋转时Activity不重新调用onCreate的方法 当手机转屏时,Activity的onDestroy和 ...

  2. android 屏幕旋转流程,android自动屏幕旋转流程分析.doc

    android自动屏幕旋转流程分析.doc android自动屏幕旋转流程分析 在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox, 如 ...

  3. Android 屏幕旋转 全解析

    屏幕旋转一般的解决方案 关于屏幕旋转这里,之前一直没太注意,因为根据设备会有指定的屏幕旋转策略如: 开发手机应用时一直使用强制竖屏布局 开发平板设备一直使用横屏布局 开发系统应用,一般给两套即横竖各一 ...

  4. Android屏幕旋转后的变更--ConfigChange

    文章目录 1. Activity生命周期的变化 1.1 正常生命周期 1.2 屏幕旋转后重建Activity 1.3 解决数据丢失问题--onSaveInstanceState和onRestoreIn ...

  5. Android 屏幕旋转时Activity的变化

    Android开发文档上专门有一小节解释这个问题.简单来说,Activity是负责与用户交互的最主要机制,任何"设置"(Configuration)的改变都可能对Activity的 ...

  6. android 屏幕方向监听,android 屏幕旋转问题 - jwzhangjie的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...

    settings设置 在Android的Settings-> Display中有Orientation这一设置项.当选中时,屏幕会随设备旋转. settings设置是在文件SoundAndDis ...

  7. Android屏幕旋转,赶紧学习一下

    ActivityInfo.SCREEN_ORIENTATION_SENSOR //根据传感器设置方向 ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR //根据传 ...

  8. Android 屏幕旋转的处理

    1. 不做任何处理的情况下 如果没有针对性地做任何处理的话,默认情况下,当用户手机的重力感应器打开后,旋转屏幕方向,会导致app的当前activity发生onDestroy-> onCreate ...

  9. android屏幕旋转生命周期,Activity、Fragment生命周期---横竖屏切换的生命周期

    先贴出一张大家众所周知activity流程图 onCreate():创建Activity调用,用于Activity的初始化,还有个Bundle类型的参数,可以访问以前存储的状态.onStart():A ...

最新文章

  1. Hibernate最佳实践
  2. 【转】造成segment fault,产生core dump的可能原因
  3. 第四周实践项目5 猴子选大王(循环链表)
  4. jquery ready方法实现原理
  5. 【LeetCode】拓扑排序
  6. centos7安装telnet服务
  7. loadrunner可用许可证
  8. CCF NOI1044 最近元素
  9. win10 电脑触摸板不能滑动_用好笔记本的触摸板(win10小技巧)
  10. DRILLNET 2.0------第八章 预防碰撞分析模型
  11. bootstrap学习笔记-(1-初识bootstrap)
  12. 小程序 | 如何清除手机上小程序缓存
  13. AgentWeb 更加简洁优秀的webview
  14. CRM 安装不规范,亲人两行泪
  15. 阿里云对象存储OSS中上传的资源在生成URL链接时直接在浏览器中打开而不是下载的问题解决方法
  16. 30天自制操作系统-Hello OS
  17. 中医大2020年7月网考计算机应用基础,2020年7月网络教育统考计算机应用基础模拟题试卷9...
  18. 伍鸣博士受邀出席徐汇区住房租赁市场研讨会
  19. 计算机开关机操作记录,win7电脑操作记录怎么查看|win7查看电脑操作记录的方法...
  20. 1033 旧键盘打字 (20 分)

热门文章

  1. 阿里云短信接口-PHP
  2. Mininet多数据中心网络拓扑流量带宽实验
  3. vSphere Data Protection(VDP)----需求与规划
  4. 【狂神】MyBatisPlus笔记
  5. err_code啥意思?
  6. 机械师曙光 16 Air 锐龙版 评测 怎么样
  7. (状压DP)排兵布阵3
  8. 【Graphics·二】带反射和折射的Fresnel函数
  9. 面试官角度看校招面试之吐槽
  10. Angular2环境配置