Android是支持屏幕進行旋轉的,經過旋轉使得屏幕呈現出豎屏或者橫屏的佈局。有時咱們在使用的時候會發現,旋轉時會有動畫。這是由於,爲了使用戶在使用轉屏旋轉過程當中提高體驗,系統會對屏幕截屏,使用截屏獲取的圖片進行旋轉動畫,指導完成旋轉,咱們所看到的旋轉動畫實際上是,旋轉開始時系統所截屏幕所作的動畫。java
手機是否支持轉屏能夠在Setting設定,對於Setting中有關是否自動轉屏,PhoneWindowManager中的init()函數中建立了SettingsObserver對象,其observe()方法將監聽Settings.System.USER_ROTATION的值。若是設置中打開auto-rotation,會觸發以下流程。android
下面對該流程中涉及到的代碼進行分析:函數
1、AccessibilitySettings類是各手機廠商本身的setting模塊中的一個類,該類的命名和方法可能不一樣,詳細代碼見下。oop
2、handleLockScreenRotationPreferenceClick()也是AccessibilitySettings.java的方法。在該方法中調用RotationPolicy類的setRotationLockedForAccessbility(),其實就是用戶在settings界面點擊auto-Rotation傳入對應的值。佈局
3、下面的各種及方法爲android中源碼。enable爲是否容許自動旋轉的使能位。動畫
4、在setRotationLock()方法中,根據enable的值,分別執行wms的不容許轉屏和容許轉屏。spa
5、freezeRotation()不容許轉屏,thawRotation()容許轉屏。這裏咱們分析轉屏的流程,所以順着thawRotation()的流程分析。線程
6、PhoneWindowManager.java中setUserRotationMode。該方法會在Settings.System中寫入值。3d
7、PhoneWindowManager中的init()函數中建立了SettingsObserver對象,其observe()方法將監server
聽Settings.System.USER_ROTATION的值,監聽到該值後調用onChange。
8、該方法是wms在調用freezeRotation()或thawRotation()後調用的。
9、這裏會觸發SettingsObserver.onChange(),其中主要調用了updateSettings()和updateRotation()兩個函數。其主要的工做是根據須要監聽傳感器數據,據此判斷是否要轉屏,若是傳感器傳回的值改變,則對configuration的各類更新。函數updateSettings()如它的名字主要更新設置信息。若是UserRotation(朝向信息,如Surface.ROTATION_0)和UserRotationMode(USER_ROTATION_FREE vs. USER_ROTATION_LOCKED)有更新,就設置標記updateRotation爲true表示接下去須要更新rotation相關信息。
10、若是UserRotationMode的配置有變,因爲須要傳感器信息的配合,還需調用updateOrientationListenerLp()來設置或取消監聽傳感器。
11、假設手機設置爲自動旋轉,那麼PhoneWindowManager會經過MyOrientationListener來監聽傳感器信息。MyOrientationListener是WindowOrientationListener的繼承類,WindowOrientationListener的enable()函數中調用SensorManager提供的registerListener()接口來設置Sensor信息的listener。
12、接下來咱們重點分析有關傳感器部分的流程。
調用SensorManager提供的registerListener()接口設置Sensor信息的listener。
調用SystemSensorManager,registerListenerImpl註冊監聽器,當Sensor數據有改變的時候將會回調SensorEventListener的onSensorChanged方法。
手機開機後會建立SystemSensorManager的實例,在其構造函數中,主要作了四件事情:
(1)初始化JNI:調用JNI函數nativeClassInit()進行初始化。
(2)初始化Sensor列表:調用JNI函數sensors_module_init,對Sensor模塊進行初始化,建立了native層SensorManager的實例。
(3)獲取Sensor列表:調用JNI函數sensors_module_get_next_sensor()獲取Sensor,並存在sHandleToSensor列表中
(4)構造SensorThread類:構造線程的類函數,並無啓動線程,當有應用註冊的時候纔會啓動線程。
當有應用程序調用registerListenerImpl()方法註冊監聽的時候,會調用SensorThread.startLoacked()啓動線程。線程只會啓動一次,並調用enableSensorLocked()接口對指定的sensor使能,並設置採樣時間。SensorThreadRunnable實現了Runnable接口,在SensorThread類中被啓動。
首先,registerListenerImpl()中建立SensorEventQueue對象(基類爲BaseEventQueue),它是傳感器事件的隊列,記錄須要監聽哪些傳感器信息。同時也負責與SensorService的鏈接和通訊,能夠說是SensorEventListener與SensorService間的橋樑。SensorEventListener和SensorEventQueue之間是1:1的關係,它們的映射關係保存在成員mSensorListeners中。若是這裏註冊的SensorEventListener尚未相應的SensorEventQueue,則新建一個,而後經過addSensor()方法將要關注的傳感器進行註冊。這個過程當中addSensor()調用了enableSensor(),它最終是經過SensorService的enableDisable()方法來完成註冊工做的。這樣,SensorService就開始監聽該Sensor,當底層有傳感器數據來時,SensorService主線程中會調用相應SensorEventConnection的sendEvents()將底層傳感器傳回的數據發給對應的Client。前面初始化SensorEventQueue時會建立Receiver,它是一個Looper的回調對象,在Client端收到從SensorService來的數據後被回調。當有數據收到時Receiver的handleEvent()被調用,繼而經過JNI調用到SystemSensorManager::dispatchSensorEvent()。接着就調到了WindowOrientationListener的onSensorChanged()函數。該函數將計算是否須要轉屏。若是須要轉屏,將計算結果傳給MyOrientationListener的onProposedRotationChanged()。
13、回到PhoneWindowManager的updateSettings()流程。最後若是檢測到UserRotation或UserRotationMode有更新,會調用updateRotation(),繼而調用WMS的updateRotation()保證當前的屏幕方向是一致的。
若是手機如今轉了屏幕,指望轉屏事件發生。如前面所說,onProposedRotationChanged()被調用,其中調用updateRotation()函數,隨之的updateRotationUncheckedLocked()就是真正執行轉屏的地方了。固然除了上面這條種狀況會進行轉屏,還有其它狀況可能會觸發轉屏,好比應用請求轉屏。例如須要橫屏的遊戲(經過updateOrientationFromAppTokensLocked()方法)。updateRotation()中主要是執行兩個函數:updateRotationUncheckedLocked()和sendNewConfiguration()。前者執行轉屏動做,包含轉屏動畫等。後者使AMS獲取當前新的configuration,而且廣播該事件給全部相應的listener。