Android系統自動轉屏流程(源碼分析)

  Android是支持屏幕進行旋轉的,經過旋轉使得屏幕呈現出豎屏或者橫屏的佈局。有時咱們在使用的時候會發現,旋轉時會有動畫。這是由於,爲了使用戶在使用轉屏旋轉過程當中提高體驗,系統會對屏幕截屏,使用截屏獲取的圖片進行旋轉動畫,指導完成旋轉,咱們所看到的旋轉動畫實際上是,旋轉開始時系統所截屏幕所作的動畫。java

  手機是否支持轉屏能夠在Setting設定,對於Setting中有關是否自動轉屏,PhoneWindowManager中的init()函數中建立了SettingsObserver對象,其observe()方法將監聽Settings.System.USER_ROTATION的值。若是設置中打開auto-rotation,會觸發以下流程。android

下面對該流程中涉及到的代碼進行分析:函數

1AccessibilitySettings類是各手機廠商本身的setting模塊中的一個類,該類的命名和方法可能不一樣,詳細代碼見下。oop

2handleLockScreenRotationPreferenceClick()也是AccessibilitySettings.java的方法。在該方法中調用RotationPolicy類的setRotationLockedForAccessbility(),其實就是用戶在settings界面點擊auto-Rotation傳入對應的值。佈局

3、下面的各種及方法爲android中源碼。enable爲是否容許自動旋轉的使能位。動畫

4、在setRotationLock()方法中,根據enable的值,分別執行wms的不容許轉屏和容許轉屏。spa

5freezeRotation()不容許轉屏,thawRotation()容許轉屏。這裏咱們分析轉屏的流程,所以順着thawRotation()的流程分析。線程

6PhoneWindowManager.javasetUserRotationMode。該方法會在Settings.System中寫入值。3d

7PhoneWindowManager中的init()函數中建立了SettingsObserver對象,其observe()方法將監server

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

相關文章
相關標籤/搜索