App啓動過程導圖
- 點擊桌面App圖標,Launcher進程採用Binder IPC向system_server進程發起startActivity請求
- system_server進程接收到請求後,向zygote進程發送創建進程的請求
- Zygote進程fork出新的子進程,即App進程
- App進程,通過Binder IPC向sytem_server進程發起attachApplication請求
- system_server進程在收到請求後,進行一系列準備工作後,再通過binder IPC向App進程發送scheduleLaunchActivity請求
- App進程的binder線程(ApplicationThread)在收到請求後,通過handler向主線程發送LAUNCH_ACTIVITY消息
- 主線程在收到Message後,通過發射機制創建目標Activity,並回調Activity.onCreate()等方法
- App便正式啓動,開始進入Activity生命週期,執行完onCreate/onStart/onResume方法,UI渲染結束後便可以看到App的主界面
Android開機流程導圖
BootLoader引導
當按開機鍵的時候,引導芯片開始從固化在ROM的預設代碼開始執行,然後加載引導程序到RAM
BootLoader,又稱爲引導程序。它是在操作系統運行之前運行的一段程序
BootLoader負責初始化軟件運行所需要的最小硬件環境,最後加載內核到內存
啓動Kernel
這個入口的函數是start_kernel函數
start_kernel函數執行到最後調用了reset_init函數進行後續的初始化
start_kernel最終啓動用戶空間的init程序
啓動Android
當初始化內核之後,init進程負責解析init.rc配置文件, 就會啓動一個相當重要的祖先進程,也就是init進程,在Linux中所有的進程都是由init進程直接或間接fork出來的
* /system/bin/app_process_Zygote服務啓動的進程名
* --start-system-server 表明Zygote啓動完成後,需要啓動System_Server進程
* socket zygote stream 666在Zygote啓動時,創建一個權限爲666的socket。此socket用來請求zygote創建新進程
* socket的fd保存在名稱爲"ANDROID_SOCKET_zygote"的環境變量中
init進程負責創建系統中最關鍵的幾個核心daemon(守護)進程,尤其是zygote和System_Server進程
1. zygote進程 android啓動的第一個Dalvik 虛擬機,它將負責啓動Java世界的進程
2. zygote虛擬機啓動子進程system_server,同時也可以看出zygote中定義了一個Socket,綁定666端口,用於接收ActivityManagerService啓動應用程序的請求
3. System_Server進程 Binder通信的基礎,它還提供了property service(屬性服務),類似於windows系統的註冊表服務
4. 系統裏面重要的服務都是在這個進程裏面開啓的,例如AMS, WindowsManager, PackageManagerService等等都是由這個System_Server fork出來的
5. 在System_Server進程開啓的時候,就會初始化ActivityManagerService 。同時,會加載本地系統的服務庫,調用createSystemContext()創建系統上下文,創建ActivityThread及開啓各種服務等等
6. system_server中開啓了核心系統服務,並將系統服務添加到ServiceManager中,然後系統進入SystemReady狀態
啓動Home Activity
- 在systemReady狀態,ActivityManagerService會與zygote的Socket通信,請求啓動Home
- zygote收到AMS的連接請求後,執行runSelectLoopMode處理請求
- zygote處理請求會通過forkAndSpecialize啓動新的應用進程,並最終啓動Home
概況
1. 系統加電,執行bootloader。Bootloader負責初始化軟件運行的最小硬件環境,最後加載內核到內存
2. 內核加載到內存後,進入內核引導階段,在內核引導的最後,調用start_kernel進入內核啓動階段。start_kernel最終啓動用戶空間的init程序
3. init負責解析init.rc配置文件,開啓系統守護進程。2個最重要的守護進程是zygote進程和serverManager進程。zygote是android啓動的第一個Dalvik虛擬機,ServiceManager服務是Binder通信的基礎
4. zygote虛擬機啓動子進程system_server,在system_server中啓動了核心系統服務,並將系統服務添加到ServiceManager中,然後系統進入SystemReady狀態
5. 在SystemReady狀態,ActivityManagerService與zygote中的socket通信,通過zygote啓動home應用,進入系統界面
* 從步驟3開始, init啓動後,上層的實現
1. init啓動的核心Daemon服務包括Android的第一個Dalvik虛擬機Zygote
2. zygote定義一個socket,用於接受ActivityManangerService啓動應用的請求
3. zygote通過fork系統調用創建system_server進程
4. 在system_server進程中,將會啓動系統核心服務以及其他服務
5. 系統服務啓動後會註冊到ServiceManager中,用於Binder通信
6. ActivityManagerService進入systemReady狀態
7. 在systemReady狀態,ActivityManangerService會與zygote的Socket通信,請求啓動Home
8. zygote收到AMS的連接請求後,執行runSelectLoopMode處理請求
9. zygote處理請求會通過forkAndSpecialize啓動新的應用進程,並最終啓動Home
Handler機制與底層實現原理
概念:
Message - Message代表一個行爲what或者一串動作Runnable, 每一個消息在加入消息隊列時,都有明確的目標Handler
ThreadLocal - 線程本地存儲區(Thread Local Storage,簡稱爲TLS),每個線程都有自己的私有的本地存儲區域,不同線程之間彼此不能訪問對方的TLS區域。ThreadLocal的作用是提供線程內的局部變量TLS,這種變量在線程的生命週期內起作用,每一個線程有他自己所屬的值(線程隔離)
MessageQueue (C層與Java層都有實現) - 以隊列的形式對外提供插入和刪除的工作, 其內部結構是以雙向鏈表的形式存儲消息的
Looper (C層與Java層都有實現) - Looper是循環的意思,它負責從消息隊列中循環的取出消息然後把消息交給Handler處理
Handler - 消息的真正處理者, 具備獲取消息、發送消息、處理消息、移除消息等功能
普通的線程是沒有looper的,如果需要looper對象,那麼必須要先調用Looper.prepare方法,而且一個線程只能有一個looper
Handler是如何完成跨線程通信的
* Android中採用的是Linux中的管道通信
* 關於管道,簡單來說,管道就是一個文件
* 在管道的兩端,分別是兩個打開文件文件描述符,這兩個打開文件描述符都是對應同一個文件,其中一個是用來讀的,別一個是用來寫的
* 消息隊列創建時,會調用JNI函數,初始化NativeMessageQueue對象。NativeMessageQueue則會初始化Looper對象
* Looper的作用就是,當Java層的消息隊列中沒有消息時,就使Android應用程序主線程進入等待狀態,而當Java層的消息隊列中來了新的消息後,就喚醒Android應用程序的主線程來處理這個消息
整個消息機制流程
Handler通過sendMessage()發送Message到MessageQueue隊列
Looper通過loop(),不斷提取出達到觸發條件的Message,並將Message交給target來處理
經過dispatchMessage()後,交回給Handler的handleMessage()來進行相應地處理
將Message加入MessageQueue時,處往管道寫入字符,可以會喚醒loop線程;如果MessageQueue中沒有Message,並處於Idle狀態,則會執行IdelHandler接口中的方法,往往用於做一些清理性地工作
ContentProvider原理
Android繪製原理
Activity的window組成,Activity內部有個Window成員,它的實例爲PhoneWindow,PhoneWindow有個內部類是DecorView,這個DecorView就是存放佈局文件的,裏面有TitleActionBar和我們setContentView傳入進去的layout佈局文件
- Window類時一個抽象類,提供繪製窗口的API
- PhoneWindow是繼承Window的一個具體的類,該類內部包含了一個DecorView對象,該DectorView對象是所有應用窗口(Activity界面)的根View
- DecorView繼承FrameLayout,裏面id=content的就是我們傳入的佈局視圖
- ContentView必須是一個ViewGroup
- ViewGroup 開始遞歸執行以下邏輯進行繪製
+ measure, 遞歸測量view的大小。有3種測量模式
- MeasureSpec.EXACTLY表示確定大小
- MeasureSpec.AT_MOST表示最大大小
- MeasureSpec.UNSPECIFIED不確定
+ layout,遞歸佈局view的位置
+ draw,遞歸繪製view
- ViewRootImpl中的代碼會創建一個Canvas對象,然後調用View的draw()方法來執行具體的繪製
AsyncTask源碼分析
Binder機制及底層實現
進程空間分配
- 進程間,用戶空間的數據不可共享,所以用戶空間 = 不可共享空間
- 進程間,內核空間的數據可共享,所以內核空間 = 可共享空間
- 進程內用戶與內核進行交互稱爲系統調用
Binder跨進程通信(IPC)的原理
- 先通過進程間的內核空間進行數據交互
- 再通過進程內的用戶空間&內核空間進行數據交互,從而實現進程間的用戶空間的數據交互
- 而Binder,就是充當連接兩個進程(內核空間)的通道
使用步驟:
註冊服務
* Server進程向Binder驅動發起服務註冊請求
* Binder驅動將註冊請求轉發給ServiceManager進程
* ServiceManager進程添加該服務
* 此時ServiceManager進程擁有該服務信息
獲取服務
* Client向Binder驅動發起獲取服務的請求,傳遞要獲取的服務名稱(service name)
* Binder驅動將該請求轉發給ServiceManager進程
* ServiceManager查找到Client需要的Server對應的服務信息
* 通過Binder驅動將上述服務信息返回給Client進程
* 此時client進程與server進程已經建立了連接
使用服務
* Client進程將參數數據發到Server進程
1. client 進程將需要的傳送的數據放到client進程的共享內存;(當前線程被掛起)
2. Binder驅動從client的共享內存中讀取數據,並根據ServiceManager進程裏面的Server信息找到對應的Server進程
3. Binder驅動將數據copy到Server進程的共享內存裏,並通知Server進程解包
* Server進程根據Client進程要求,調用目標方法
1. 接到Binder驅動通知後,Server進程從線程池中取出線程,進行數據解包和調用目標方法
2. 將最終方法結果寫到自己的共享內存
* Server進程將目標方法的結果,返回給Client進程
1. Binder驅動程序將Server進程的共享內存裏面的數據(方法執行結果) copy 到client進程的共享內存
2. 通知client進程獲得返回結果(此時client進程之前被掛起的線程被重新喚醒)
Client進程、Server進程 & Service Manager 進程之間的交互 都必須通過Binder驅動(使用 open 和 ioctl文件操作函數),而非直接交互
Client進程、Server進程 & Service Manager進程屬於進程空間的用戶空間,不可進行進程間交互
Binder驅動 屬於 進程空間的 內核空間,可進行進程間 & 進程內交互
Binder驅動 & Service Manager進程 屬於 Android基礎架構(即系統已經實現好了);而Client 進程 和 Server 進程 屬於Android應用層(需要開發者自己實現)
ActivityThread工作原理
Window 、WMS的工作原理
ThreadLocal原理,實現及如何保證Local屬性
每個Thread維護一個ThreadLocalMap映射表,這個映射表的key是ThreadLocal實例本身,value是真正需要存儲的Object
Android線程有沒有上限
android本身就是linux系統 所以查看命令和linux一樣
Android內存限制
dalvik.vm.heapstartsize 表示 初始內存大小是8m
dalvik.vm.heapgrowthlimit 表示標準內存大小是96m 一般應用都是這麼大
dalvik.vm.heapsize 表示 在manifest配置文件中application標籤下配置 android:largeHeap="true"時的內存大小
Android apk大小限制
apk安裝包大小理論上沒有限制。但是各個應用商店爲了有大小限制google play 要求小於50M , 擴展包可以擴展到2g
壓測: 800M的apk是沒問題的只是安裝的時間比較長。1.6G的apk包則把手機弄死機
線程池有沒有上限
ThreadPoolExecutor構造函數的maximumPoolSize決定
AndroidToast原理分析
Art和Dalvik對比
ART 的機制與 Dalvik 不同。在Dalvik下,應用每次運行的時候,字節碼都需要通過即時編譯器(just in time ,JIT)轉換爲機器碼,這會拖慢應用的運行效率,而在ART 環境中,應用在第一次安裝的時候,字節碼就會預先編譯成機器碼,使其成爲真正的本地應用。這個過程叫做預編譯(AOT,Ahead-Of-Time)。這樣的話,應用的啓動(首次)和執行都會變得更加快速。
BlockCanaryEx原理
即整個應用的主線程,只有這一個looper,不管有多少handler,最後都會回到這裏
public static void loop() {
...
for (;;) {
...
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
...
}
}
設置Printer對象,判斷是否超過預期時間,notifyLog