Android系统自动转屏流程(源码分析)

  Android是支持屏幕进行旋转的,通过旋转使得屏幕呈现出竖屏或者横屏的布局。有时我们在使用的时候会发现,旋转时会有动画。这是因为,为了使用户在使用转屏旋转过程中提升体验,系统会对屏幕截屏,使用截屏获取的图片进行旋转动画,指导完成旋转,我们所看到的旋转动画其实是,旋转开始时系统所截屏幕所做的动画。

  手机是否支持转屏可以在Setting设定,对于Setting中有关是否自动转屏,PhoneWindowManager中的init()函数中创建了SettingsObserver对象,其observe()方法将监听Settings.System.USER_ROTATION的值。如果设置中打开auto-rotation,会触发如下流程。

下面对该流程中涉及到的代码进行分析:

1AccessibilitySettings类是各手机厂商自己的setting模块中的一个类,该类的命名和方法可能不同,详细代码见下。

2handleLockScreenRotationPreferenceClick()也是AccessibilitySettings.java的方法。在该方法中调用RotationPolicy类的setRotationLockedForAccessbility(),其实就是用户在settings界面点击auto-Rotation传入对应的值。

3、下面的各类及方法为android中源码。enable为是否允许自动旋转的使能位。

4、在setRotationLock()方法中,根据enable的值,分别执行wms的不允许转屏和允许转屏。

5freezeRotation()不允许转屏,thawRotation()允许转屏。这里我们分析转屏的流程,因此顺着thawRotation()的流程分析。

6PhoneWindowManager.javasetUserRotationMode。该方法会在Settings.System中写入值。

7PhoneWindowManager中的init()函数中创建了SettingsObserver对象,其observe()方法将监

Settings.System.USER_ROTATION的值,监听到该值后调用onChange

8该方法是wms在调用freezeRotation()thawRotation()后调用的。

9、这里会触发SettingsObserver.onChange(),其中主要调用了updateSettings()updateRotation()两个函数。其主要的工作是根据需要监听传感器数据,据此判断是否要转屏,如果传感器传回的值改变,则对configuration的各种更新。函数updateSettings()如它的名字主要更新设置信息。如果UserRotation(朝向信息,如Surface.ROTATION_0)和UserRotationModeUSER_ROTATION_FREE vs. USER_ROTATION_LOCKED)有更新,就设置标记updateRotationtrue表示接下去需要更新rotation相关信息。

10、如果UserRotationMode的配置有变,由于需要传感器信息的配合,还需调用updateOrientationListenerLp()来设置或取消监听传感器。

11、假设手机设置为自动旋转,那么PhoneWindowManager会通过MyOrientationListener来监听传感器信息。MyOrientationListenerWindowOrientationListener的继承类,WindowOrientationListenerenable()函数中调用SensorManager提供的registerListener()接口来设置Sensor信息的listener

12、接下来我们重点分析有关传感器部分的流程。

调用SensorManager提供的registerListener()接口设置Sensor信息的listener

调用SystemSensorManagerregisterListenerImpl注册监听器,当Sensor数据有改变的时候将会回调SensorEventListeneronSensorChanged方法

  手机开机后会创建SystemSensorManager的实例,在其构造函数中,主要做了四件事情:

1)初始化JNI:调用JNI函数nativeClassInit()进行初始化。

2)初始化Sensor列表:调用JNI函数sensors_module_init,对Sensor模块进行初始化,创建了nativeSensorManager的实例。

3)获取Sensor列表:调用JNI函数sensors_module_get_next_sensor()获取Sensor,并存在sHandleToSensor列表中

4)构造SensorThread类:构造线程的类函数,并没有启动线程,当有应用注册的时候才会启动线程。

  当有应用程序调用registerListenerImpl()方法注册监听的时候,会调用SensorThread.startLoacked()启动线程。线程只会启动一次,并调用enableSensorLocked()接口对指定的sensor使能,并设置采样时间。SensorThreadRunnable实现了Runnable接口,在SensorThread类中被启动。

 

  首先,registerListenerImpl()中创建SensorEventQueue对象(基类为BaseEventQueue),它是传感器事件的队列,记录需要监听哪些传感器信息。同时也负责与SensorService的连接和通信,可以说是SensorEventListenerSensorService间的桥梁。SensorEventListenerSensorEventQueue之间是1:1的关系,它们的映射关系保存在成员mSensorListeners中。如果这里注册的SensorEventListener还没有相应的SensorEventQueue,则新建一个,然后通过addSensor()方法将要关注的传感器进行注册。这个过程中addSensor()调用了enableSensor(),它最终是通过SensorServiceenableDisable()方法来完成注册工作的。这样,SensorService就开始监听该Sensor,当底层有传感器数据来时,SensorService主线程中会调用相应SensorEventConnectionsendEvents()将底层传感器传回的数据发给对应的Client。前面初始化SensorEventQueue时会创建Receiver,它是一个Looper的回调对象,在Client端收到从SensorService来的数据后被回调。当有数据收到时ReceiverhandleEvent()被调用,继而通过JNI调用到SystemSensorManager::dispatchSensorEvent()。接着就调到了WindowOrientationListeneronSensorChanged()函数。该函数将计算是否需要转屏。如果需要转屏,将计算结果传给MyOrientationListeneronProposedRotationChanged()

13回到PhoneWindowManagerupdateSettings()流程。最后如果检测到UserRotationUserRotationMode有更新,会调用updateRotation(),继而调用WMSupdateRotation()保证当前的屏幕方向是一致的。

  如果手机现在转了屏幕,期望转屏事件发生。如前面所说,onProposedRotationChanged()被调用,其中调用updateRotation()函数,随之的updateRotationUncheckedLocked()就是真正执行转屏的地方了。当然除了上面这条种情况会进行转屏,还有其它情况可能会触发转屏,比如应用请求转屏。例如需要横屏的游戏(通过updateOrientationFromAppTokensLocked()方法)。updateRotation()中主要是执行两个函数:updateRotationUncheckedLocked()sendNewConfiguration()。前者执行转屏动作,包含转屏动画等。后者使AMS获取当前新的configuration,并且广播该事件给所有相应的listener

 

 

转载于:https://www.cnblogs.com/daxingege/p/7182854.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值