1:InputChannel提供函數(shù)創(chuàng)建底層的Pipe對象
2:
1)客戶端需要新建窗口
2)new ViewRoot object
3) call viewRoot.setVIew()? -- Detail: IPC call WmS subclass Session.addWindow()
3.system_server? zygote first process? system_process?
A:Linux 內(nèi)核加載完畢之后,首先啟動(dòng) init 進(jìn)程,然后解析 init.rc,并根據(jù)其內(nèi)容由 init 進(jìn)程裝載 Android 文件系統(tǒng)、創(chuàng)建系統(tǒng)目錄、初始化屬性系統(tǒng)、啟動(dòng)一些守護(hù)進(jìn)程,其中最重要的守護(hù)進(jìn)程就是 Zygote 進(jìn)程。Zygote 進(jìn)程初始化時(shí)會(huì)創(chuàng)建 Dalvik 虛擬機(jī)、預(yù)裝載系統(tǒng)的資源和 Java 類。所有從 Zygote 進(jìn)程 fork 出來的用戶進(jìn)程都將繼承和共享這些預(yù)加載的資源。init 進(jìn)程是 Android 的第一個(gè)進(jìn)程,而 Zygote 進(jìn)程則是所有用戶進(jìn)程的根進(jìn)程。SystemServer 是 Zygote 進(jìn)程 fork 出的第一個(gè)進(jìn)程,也是整個(gè) Android 系統(tǒng)的核心進(jìn)程。
4. c庫:
c coding android api header source -> system/core/include/cutils
system/core/adb/*
bionic/libc/include/sys/*
5. 可用: system/core/include/sysutils/*
FrameworkClient? -> sendMsg
FrameworkCommand -> runCommand
6. system/core/include/usbhost/? -> c/c++方式? 獲取usb信息
7. system/core/include/mincrypt? -> c/c++方式? ? 加密類
8. 禁止串口:? ? platform/build/core/main.mk: ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0
9. c 里運(yùn)行命令:? run_command("cmd", 0);? (refernce device/hisilicon/bigfish/sdk / source/boot/fastboot/common/cmd_bootproc.c)
10. android source include 路徑: system/core/include; frameworks/base/include
11. android c++ sp是模板類, 相當(dāng)于java中softreference, 能夠自動(dòng)釋放內(nèi)存
12. GUI畫圖總結(jié):
1) Surface, 兩種調(diào)用方法, 1] WindowManagerService, 調(diào)用空的surface,之后填充
2] Surface, 第二種構(gòu)造方法出來的
2) 可以用C寫程序自己畫
3) ViewRoot可以調(diào)用畫圖
4) SurfaceFlinger服務(wù),? 底層, 上層接著WmS和其他需要畫圖的.;
1] WmS -> JNI-> SurfaceFlinger客戶端驅(qū)動(dòng)接口->SurfaceFlinger服務(wù)進(jìn)程
APK方面: 從WmS到客戶端的WindowManager類(WindowManager.addView() ->ViewRoot創(chuàng)建空的Surface對象->調(diào)用WmS的IWidnowSession填充Surface)-> Canvas 類-> JNI -> SKia驅(qū)動(dòng)->畫圖
2] C-> 直接調(diào)用SurfaceFlinger函數(shù)直接畫
13. /development/scritps? ? ->? 開發(fā)鏡像之類的
/development/scritps/mkimage.sh
/development/scritps/build_image.sh
14. sed直接修改文件內(nèi)容(行)
15. Skip intent action 在ActivityManagerService
16. cpu load 順序簡介
cpu片上引導(dǎo)程序-> 二次引導(dǎo)程序(fastboot) -> boot分區(qū)(boot.img), linux kernel
(1KB,load fastboot into memory, no driver)(2M ext fs driver support) (8M)
recovery分區(qū)(recovery.img)和boot分區(qū)原始內(nèi)容一樣,可用于覆蓋boot分區(qū).
system分區(qū)(system.img) android內(nèi)核
ramdisk.img? 工具
17. linux init
init 進(jìn)程在linux中pid=1, pid=0(idle).
init進(jìn)程從kernel開始調(diào)用, kernel_thread. 內(nèi)核態(tài)到用戶態(tài), 可查看linux源碼怎么調(diào)用
linux 應(yīng)該都有init進(jìn)程
18. make_ext4fs system目錄轉(zhuǎn)化為system.img
19. init.rc文件中
可以write /proc/apanic_console 1 直接寫內(nèi)容
20. 系統(tǒng)編譯類source還有: /build/core/[main.mk]
21. change BIN name
/device/helios/build/build_factory
/device/helios/build/mstar_funcs
22. Bootloader Control Block(BCB) command:
command=='boot-recovery' 啟動(dòng)recovery.img, recovery模式
command=='update-radio/hboot' 更新firmware
其他, 啟動(dòng)boot.img
/cache/recovery/command: recovery命令, 由主系統(tǒng)寫入.
命令: --send_intent=? ;? --update_package=root:path? ; --wipe_data ;? --wipe_cache
23. ro.helios.sn :? boot-> init進(jìn)程 -> init.rc-> read factory.prop到系統(tǒng)屬性
24. logcat.cpp processBuffer 就是那個(gè)讀取logd日志的function
25. 異步消息處理線程:
線程啟動(dòng)進(jìn)入無限循環(huán), 每次循環(huán)取消息, 回調(diào)相應(yīng)的消息處理函數(shù), 執(zhí)行完繼續(xù)循環(huán);消息為空,線程暫停,直到新消息重新起來.
用于UI接受外部消息情況.
Hanlder類(包含looper)
26. Binder
binder client(Client APK)? ontrasct -> Binder driver -> binder server(normal apk service) ontrasct
binder service (extends Binder) (apk service) receive info from data(param)
bindservice
client apk (bindservice) -> ams -> activity thread -> 回調(diào) onbind -> client apk
27. 包內(nèi)和包外service
bindservice -> return binder object
asInterface(binder object) -> querylocalinterface, check whether it's own process binder[directy Stub function] or ipc binder(Proxy class function), then call -> service function
28. System service
add service to servicemanager.
getSystemService(): ServiceManager.getService(name) return binder[service add to servicemgr before] -> IXXX.Sub.asInterface(binder object) return interface -> new XXXManager(interface) return manager instance.
29. ActivityManager有RecentTaskInfo數(shù)據(jù)類, MemoryInfo數(shù)據(jù)類.
可以比較cat /proc/meminfo
30. System service manager類和service類
client apk -> ServiceManager get binder object ->? use binder create manager -> use manager access remote service (ipc)
intro:
IPC: client apk-> getSysemservice(ipc contained), return manager.
IPC: manager(local) access api.
Manager類是本地的, Service類是遠(yuǎn)程的?!IPC的]
Manager類通常內(nèi)部具有service遠(yuǎn)程類的binder變量.
31. Wms:
KeyQ類: 讀取用戶輸入事件, 點(diǎn)擊,觸摸, 放到消息隊(duì)列QueueEvent. (異步消息處理線程)
InputDispatcherThread類: 讀取QueueEvent發(fā)送給各客戶端程序(異步消息處理線程)[Handler對象調(diào)用相應(yīng)函數(shù)處理消息]
32. Looper Usage:
Refer to ActivityThread main().
Looper.prepareMainLooper();
Looper.loop();
33. Framework中客戶端, 服務(wù)端, 接口.
客戶端中ViewRoot類(重要) 接受服務(wù)端WmS中的IPC調(diào)用轉(zhuǎn)為本地的異步調(diào)用。
ViewRoot 中IPC 來自 內(nèi)部類W類: 繼承Binder類, 接受IPC調(diào)用.
客戶端(奇特吧)中WindowManager 跟客戶端APK打交道, 跟服務(wù)端的WmS打交道, 具體創(chuàng)建窗口等由WmS完成??蛻舳薃PK不能直接與WmS交互.? 應(yīng)該是System service manager類和service類的關(guān)系.
34.包含activity的客戶端apk程序至少包含3個(gè)線程:
1) UI線程, 從ActivityThread的main() Looper.prepareMainLooper()有了MessageQueue, 再有hanler對象。
2) ViewRoot W 類, Binder線程。
3) ApplicatinThread對象, binder線程.
35. linux磁盤命名規(guī)則
IDE, SATA接口 -> hd
scsi接口, u盤? -> sd
36: Context -> 實(shí)現(xiàn): ContextImpl
Activity inherit -> ContextThemeWrapper -> ContextWrapper -> Context
Service inherit -> ContextWrapper -> Context
37: Launcher activity:
Ams -> IPC -> ActivityThread.scheduleLaunchActivty();
38: Ams IPC -> 傳進(jìn)數(shù)據(jù)類PackageInfo: 對Activity是ActivtyInfo;? Application是ApplicationInfo; Service是ServiceInfo;
應(yīng)用程序context個(gè)數(shù): Activty count + Service count + 1(applicationInfo)
39: c 讀取每行文件處理 -> system/core/toolbox/md5.c
40: init的日志輸出設(shè)備為/dev/__kmsg__.
41:? BOOTCHART? -> init.c
service_start 函數(shù)? -> init.c native service 啟動(dòng)
onrestart -> poll,? init.c::main 里面的for(;;)無線循環(huán)等到后重啟進(jìn)程
42: ZygoteInit.java -> startSystemServer
43: Zygote
1) Appruntime start()
2) startVM
3) startReg (register JNI funcs)
4) JNI func : com.android.internal.os.ZygoteInit(class) main() -> java world
5) register zygote socket, preload classes, preload resources
6) startSystemServer -> fork system server
7) runSelectLoopMode (sleep, waitfing for child process request(socket) )
44: startActivity
1) ClassLoader : load class file
2) attach , set internal variables
3) IWindowManager 創(chuàng)建窗口, wm.addView();
3) decor : draw
45. 第一個(gè)activity
framework system server systemReady() -> ActivitymanagerService resumeTopActivty() -> null的話, startHome
startHome: 對于Home程序, system server 發(fā)出category_HOME的intent, 只要能相應(yīng)home的intent, 就是HOME程序,多個(gè)的話讓用戶選擇哪個(gè)為HOME.
46: PmS
/system/etc/permissions
/data/system/packages.xml
/data/drm(/data/app-private) 保存有數(shù)字版權(quán)的數(shù)據(jù)
47: PmS 安裝app:
1) copy to /data/app & get dex to /data/dalvik-cache
2) get info & save to packages.xml & mSettings.mPackages object.
Uninstall:
1) get info & delete packages.xml info & mSettings.mPackages object info
2) delete dex in /data/dalvik-cache , delete /data/app.
intent:? 從數(shù)據(jù)中匹配找到(Activity, Service, Receiver, ContentProvider)
48: add double os support
1) development/scripts/build_image.sh
2) development/scritps/releaseimage.sh
多一個(gè)image
make-fs-partition
release-fs-partition userdata $BOARD_USERDATAIMAGE_PARTITION_SIZE true
change partition size [for double os support]
1) device/helios/helios/BoardConfig.mk
boot + boot1(8M)
tee + tee1(8M)
system + system1(1G)
tvservice + tvservice1(160M)
tvconfig + tvconfig1(10M)
tvcustomer + tvcustomer1(16M)
device/helios/helios/fstablmuji: contains disk info and correspondant partition
49: 三個(gè)部分, 兩個(gè)接口
1)? Main system, 用boot.img啟動(dòng)的linux系統(tǒng)(system.img), android的正常工作模式
2)? Recovery: 用recovery.img啟動(dòng)的linux系統(tǒng), android的recovery模式
3)? Bootloader(mboot, fastboot): 除了加載,啟動(dòng)系統(tǒng), 還會(huì)通過讀取flash的MISC分區(qū)獲得來自mainsystem和recovery的消息, 并以此決定做何種操作。
兩個(gè)通信接口:
1) Recovery通過/cache/recovery里的文件與mainsystem通信: 3個(gè)文件 /cache/recovery/command, /cache/recovery/log, /cache/recovery/intent.
2) BCB(bootloader control block)即bootloader_message
BCB是bootloader與recovery的通信接口, 也是Bootloader與mainsystem的通信接口,存儲(chǔ)在flash中的MISC分區(qū),占用3個(gè)page. (1)command, (2)status, (3)recovery.
50: make_usb_upgrade.sh
腳本接受參數(shù)的例子
51: 獲取mount的設(shè)備路徑
system/core/toolbox/mount.c:? 循環(huán)對比字符串
52: 系統(tǒng)linux內(nèi)核與硬件之間的交互
1) 編寫自己的系統(tǒng)調(diào)用
2) 編寫驅(qū)動(dòng)程序
3) 使用proc文件系統(tǒng)
4) VFS虛擬文件操作系統(tǒng)
5) 內(nèi)存映像 (內(nèi)核中特定部分的內(nèi)存空間映射到用戶級(jí)程序的內(nèi)存空間里,即用戶空間和內(nèi)核空間共享一塊相同的內(nèi)存)
Relay實(shí)現(xiàn)內(nèi)核到用戶空間的數(shù)據(jù)傳輸
53: device/hisilicon/bigfish/sdk / source/boot/fastboot/lib/parse_bootargs.c
分解boot args
device/hisilicon/bigfish/sdk / source/boot/fastboot/common/cmd_bootproc.c
fastboot分析進(jìn)入recovery
54: wakelock 電源管理系統(tǒng)中核心角色? 有它則無法休眠
系統(tǒng)啟動(dòng)完畢會(huì)加main的wakelock, 在early_suspend釋放,然后休眠
55: 對于Android整個(gè)啟動(dòng)過程來說,基本可以劃分成三個(gè)階段:Bootloader引導(dǎo)、Linux kernel啟動(dòng)、Android啟動(dòng)
Uboot是bootloader一種, 其他的bootloader還有Redboot, BLOB, LILO, GRUB, Loadlin, Vivi等
56: linux編譯之后最終會(huì)產(chǎn)生zImage文件,不過為了uboot的要求,會(huì)有做一個(gè)uImage,加head,用于U-boot中檢查. ramdisk 也是, 也加head.
現(xiàn)在的android編譯出來的image名字是boot.img, 是zImage和ramdisk.img合成,還加head.
57: 系統(tǒng)啟動(dòng)時(shí), cpu會(huì)映射flash到它的內(nèi)存空間, 然后執(zhí)行flash上的代碼。
首先, 進(jìn)入cpu/arc600/start.S中的入口_start, 進(jìn)行內(nèi)存初始化,接著把uboot的前0x1800字節(jié)從flash復(fù)制到內(nèi)存的0x40800000處,也就是鏈接時(shí)的地址; 然后對bss段進(jìn)行清零,設(shè)置堆棧指針,為運(yùn)行c函數(shù)做準(zhǔn)備; 下一步,運(yùn)行c函數(shù)檢測在規(guī)定時(shí)間內(nèi)是否有按鍵發(fā)生,如有則加載uboot的后半部分(0x40801800--DATA_END)并啟動(dòng)uboot, 無則加載linux kernel并啟動(dòng)linux kernel(normal mode).? ? 而針對uboot啟動(dòng)的后半部分, 會(huì)進(jìn)行heap, 環(huán)境變量(env)的初始化,PHY驅(qū)動(dòng)的加載等工作,然后進(jìn)入一個(gè)無限循環(huán)開始shell的運(yùn)行?!∑渲校琱eap和stack以此排列在bss段的后面?!uboot中, c程序?yàn)榱藢?shí)現(xiàn)malloc(), 定義了一個(gè)32k的heap區(qū)域,在此區(qū)域的基礎(chǔ)上實(shí)現(xiàn)了簡化版的sbrk(). 在uClib庫中, malloc()是通過sbrk()或者mmap()實(shí)現(xiàn)的]
58: uboot相關(guān)文件
common/env_common.c
供u-boot 調(diào)用的通用函數(shù)接口,它們隱藏了env 的不同實(shí)現(xiàn)方式,比如dataflash, epprom, flash 等
common/env_dataflash.c
env 存儲(chǔ)在dataflash 中的實(shí)現(xiàn)
common/env_epprom.c
env 存儲(chǔ)在epprom 中的實(shí)現(xiàn)
common/env_flash.c
env 存儲(chǔ)在flash 中的實(shí)現(xiàn)
common/env_nand.c
env 存儲(chǔ)在nand 中的實(shí)現(xiàn)
common/env_nvedit.c
實(shí)現(xiàn)u-boot 對環(huán)境變量的操作命令
environment.c
環(huán)境變量以及一些宏定義
env 如果存儲(chǔ)在Flash 中還需要Flash 的支持
59: 簡化的ROM 分配模型里,monitor 占用 Flash 前256KB,env 置于其后,F(xiàn)lash
的最后一部分用來存放壓縮的操作系統(tǒng)內(nèi)核。
60: u-boot 給kernel 傳RAM 參數(shù)
./common/cmd_bootm.c 文件中, bootm 命令對應(yīng)的 do_bootm 函數(shù),當(dāng)分析 uI
mage 中信息發(fā)現(xiàn) OS 是 Linux 時(shí) , 調(diào)用 ./lib_arm/bootm.c 文件中的 do_bootm_lin
ux 函數(shù)來啟動(dòng) Linux kernel.
Kernel 讀取U-boot 傳遞的相關(guān)參數(shù)
61: wifi 系統(tǒng)的結(jié)構(gòu)
從上到下:? Wifi APP (settings)[應(yīng)用層] -> Android.net.wifi(框架類) [Java框架層] -> Wifi JNI, WPA適配器層,? wpa_supplicant守護(hù)進(jìn)程[C框架層] -> Wifi 協(xié)議, Wifi特定驅(qū)動(dòng)[內(nèi)核空間層]
各個(gè)部分路徑:
(1)守護(hù)進(jìn)程wpa_supplicant: /external/wpa_supplicant生成libwpaclient.so和守護(hù)進(jìn)程wpa_supplicant.
(2)適配器庫: /hardware/libhardware_legacy/wifi/.? ? 通過調(diào)用libwpaclient.so成為wpa_supplicant守護(hù)進(jìn)程在android中的客戶端.
(3)JNI部分: frameworks/base/core/jni/android_net_wifi_wifi.cpp.
(4)Java框架: frameworks/base/services/java/com/android/server, frameworks/base/wifi/java/android/net/wifi/(android.net.wifi作為android平臺(tái)api供java應(yīng)用程序?qū)邮褂?/p>
(5)Wifi Settings應(yīng)用程序: packages/apps/Settings/src/com/android/settings/wifi/.
62: 配置Wifi流程
(1) 配置android支持wifi
BoardConfigmk添加:
BOARD_HAVE_WIFI := true
BOARD_WPA_SUPPLICANT_DRIVER := WEXT
文件external/wpa_supplicant/Android.mk設(shè)置:
WPA_BUILD_SUPPLICANT := true
(2) 使wpa_supplicant能夠調(diào)試信息
wpa_supplicant的默認(rèn)設(shè)置是MSG_INFO.為了輸出更多信息, 可進(jìn)行修改:
common.c: wpa_dubug_level = MSG_DEBUG;
#define wpa_printf宏中if((level) >= MSG_INFO)改為if((level) >= MSG_DEBUG).
(3)配置wpa_supplicant.conf
wpa_supplicant是通過wpa_supplicant.conf中的如下語句來指定控制socket的.
ctrl_interface=/var/rum/wpa_supplicant
ctrl_interface---group=wheel
應(yīng)該在AndroidBoard.mk中配置好,然后復(fù)制到$(TARGET_OUT_ETC)/wifi.(即文件/system/etc/wifi/wpa_supplicant.conf),此位置會(huì)在init.rc中再次檢測.
通常將wpa_supplicant.conf進(jìn)行如下配置:
ctrl_intercace=DIR=/data/system/wpa_supplicant GROUP=wifi
update_config=1
fast_reauth=1
有時(shí)需要增加驅(qū)動(dòng):
ap_scan=1
如果遇到AP連接問題,則需要修改ap_scan=0以讓驅(qū)動(dòng)連接來代替wpa_supplicant.
如果要連接到non-WPA or open wireless networks, 則需要添加:
network={
key_mgmt=NONE
}
(4)配置路徑和權(quán)限
Google修改的wpa_supplicant需要運(yùn)行在wifi用戶和組下,具體代碼wpa_supplicant/os_unix.c中的函數(shù)os_program_init(). 另需確認(rèn)init.rc中wifi目錄有相關(guān)權(quán)限.
(5)運(yùn)行wpa_supplicant和dhcpcd.(均在init.rc里有native service)
(6)編譯wifi驅(qū)動(dòng)為module或kernel built in.
*編譯為module
在BoardConfig.mk中:
WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/ar6000.ko"
WIFI_DRIVER_MODULE_ARG := "" #for example nohwcrypt
WIFI_DRIVER_MODULE_NAME := "ar6000" #for example wlan0
WIFI_FIRMEWARE_LOADER := ""
*編譯為kernel built in.
在hardware/libhardware_legacy/wifi/wifi.c, 修改interface名字,然后在init.rc中添加setprop wifi.interface "wlan0", 最后在hardware/libhardwrae_legacy/wifi/wifi.c中, 當(dāng)insmod/rmmod時(shí)直接return 0.
(7)Wifi需要的firmware
Wifi需要的firmware要復(fù)制到/etc/firmware,或復(fù)制到wifi驅(qū)動(dòng)指定的位置,然后wifi驅(qū)動(dòng)會(huì)自動(dòng)加載.
(8)修改wifi驅(qū)動(dòng)適合android(見android底層開發(fā)技術(shù)實(shí)戰(zhàn)詳解17章)
(9)設(shè)置dhcpcd.conf
建議配置/system/etc/dhcpcd/dhcpcd.conf為
interface wlan0
option subnet_mask, routers, domain_name_servers
此時(shí),在android上就可以運(yùn)行wifi系統(tǒng)了.
63: bluetooth系統(tǒng)結(jié)構(gòu)
從上至下: (1) settings等應(yīng)用程序[應(yīng)用層] (2)android.bluetooth包[Java框架層] (3)Bluetooth JNI, Bluz適配層, BlueZ[C框架層] (4)藍(lán)牙協(xié)議層, 藍(lán)牙驅(qū)動(dòng)[內(nèi)核層]
android4.4版本后, BlueZ被替換為BRCM和GOOGLE合作的bluedroid.
位置:
(1)BlueZ
external/bluez/
(2)Bluetooth JNI
frameworks/base/core/jni
(3)Java框架層
frameworks/base/core/java/android/bluetooth 對應(yīng)應(yīng)用程序的API
frameworks/base/core/java/android/Server? 藍(lán)牙的服務(wù)部分
(4)BlueZ適配
system/bluetooth/? (生成libbluedroid.so及相關(guān)工具和庫)
64: envsetup.mk文件主要包含了product_config.mk文件,然后指定了編譯時(shí)要輸出的所有文件的OUT目錄,這些OUT目錄變量依賴于TARGET_DEVICE變量。
65:
接合前面的圖,product_config.mk主要讀取vendor目錄下不同廠商自己定義的AndrodProducts.mk文件(vendor/*/products/AndroidProducts.mk),從該文件里取得所有產(chǎn)品的配置文件,然后再根據(jù)lunch選擇的編譯項(xiàng)TARGET_PRODUCT,找到與之對應(yīng)的配置文件,然后讀取產(chǎn)品配置文件,找到里面的PRODUCT_DEVICE的值,設(shè)置給TARGET_DEVICE變量,用于后續(xù)編譯。
66: make
執(zhí)行目錄下的Makefile文件, 里面是include build/core/main.mk
里面inlcude重要的幾個(gè)mk文件:
include $(BUILD_SYSTEM)/config.mk
include $(BUILD_SYSTEM)/cleanbuild.mk
include $(BUILD_SYSTEM)/definitions.mk
67:
一個(gè)vendor廠商必須要有一個(gè)對應(yīng)的Board配置文件,即:vendor/*/fs100/BoardConfig.mk
68:
build/core/main.mk包含了config.mk,它主要定義了編譯全部代碼的依賴關(guān)系
build/core/config.mk? ? ? ? 定義了大量的編譯腳本命令,編譯時(shí)用到的環(huán)境變量,引入了envsetup.mk 文件,加載board相關(guān)配置文件。
build/core/envsetup.mk? 定義了編譯時(shí)用到的大量OUT輸出目錄,加載product_config.mk文件
build/core/product_config.mk 定義了Vendor目錄下Product相關(guān)配置文件解析腳本,讀取AndrodProducts.mk生成TARGET_DEVICE變量
build/target/product? ? ? ? ? product config
build/target/board? ? ? ? ? ? board config
build/core/combo? ? ? ? ? ? build flags config
用戶也可以通過buildspec.mk來指定你需要編譯進(jìn)系統(tǒng)的模塊.
69: 系統(tǒng)生成類
build/core/Makefile: 定義了生成各種img的方式, 包括ramdisk.img, userdata.img, system.img, update.zip, recovery.img.
TARGET_BUILD_TYPE: 設(shè)置debug還是release版本
70:
PM 的全稱是 Power Manager,PM 的主要作用是實(shí)現(xiàn)待機(jī)過程中的電源管理,在待機(jī)
的時(shí)候,主芯片的大部分 HW 模塊及板子的大部分硬件器件(DDR/Nand/EMMC/Tuner 等),
都處于斷電狀態(tài),以減小待機(jī)功耗。這時(shí)只有主芯片中 PM 這個(gè)小 CPU 模塊還在運(yùn)作,響
應(yīng)一些中斷、ADC、IR 等事件,條件合適的時(shí)候把系統(tǒng)再喚醒。因?yàn)?PM code 是運(yùn)行在芯片內(nèi)部一個(gè) 51 的小 CPU 下,所以 PM 的編譯環(huán)境是 KEIL C,
編譯 PM 前要先安裝好 Keil(版本至少 8.05)。
71:
MBoot 的作用初始化硬件,并引導(dǎo)操作系統(tǒng),從Flash 加載 Linux 內(nèi)核到 DRAM.
sboot 的作用主要是初始化 CPU 以及 hardware registers,它在初始化硬件完成后跳到Uboot 的入口。
Mboot里的uboot 其實(shí)也是 boot loader 的一種,但它在我們的 MBoot 中則相當(dāng)于 boot loader 的
一部分,主要作用用于承接 sboot 和操作系統(tǒng)。在這個(gè)階段里,我們可以初始化硬件設(shè)備,
建立內(nèi)存空間映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個(gè)合適狀態(tài),以便為最終調(diào)用操作系
統(tǒng)內(nèi)核準(zhǔn)備好正確的環(huán)境。
簡單的概括一下:
sboot 主要是負(fù)責(zé)芯片相關(guān)的一些初始化工作,和一些必備的硬件初始化,如初始化DDR 以及 MIU 參數(shù)的設(shè)定等;
uboot 則主要負(fù)責(zé)啟動(dòng)操作系統(tǒng);同時(shí)在啟動(dòng)系統(tǒng)之前做一些客制化功能,初始化外圍的硬件設(shè)備(這些工作都在 MstarProcess 和 MstarToKernel 中完成),例如:
如果你想要在這個(gè)階段顯示開機(jī) Logo,那么就需要初始化 Panel。
如果你想要在這個(gè)階段播放開機(jī)音樂,那么就需要初始化 Amplifier。
72:
開關(guān) STR 的方法
/android/ics/device/mstar/mstareagle/device.mk
mstar.str.enable=1
注意:同時(shí)需要確認(rèn)把/android/ics/out/target/product/mstareagleg/system 下面的 build.prop 刪除
KERNEL 部分也需要配置修改, 去掉enalbe mstar str
mboot部分也需要配置修改, 去掉enalbe mstar str
pm部分修改:
/Zen_refine/Source/config/config.h
#define STR 1=? ? ? ? // STR
Or
/PM/mainline/Zenonia/Project/Mstar/Source/cus_config.c
unsigned char code parseConfig[]=
{
TRUE, // ENABLE_UART
TRUE, // STR
};
73:
內(nèi)存有三部分組成:Kernel bin、Page Mgr 和/proc/meminfo 里面的 MemTotal。
Kernel bin:Kernel 本身的 binary,會(huì)先從總的 memory 里面扣掉;
Page Mgr:Kernel 本身管理 page 所使用的內(nèi)存,大小為 pagenum*sizeof(structpage),
pagenumber= MMAP total Linux MEM/4096
74:
剩余內(nèi)存:MemTotal (525008) - Procrank (210662K )-mali/ump(100M)=200M
可回收的內(nèi)存:200M –MemFree(80224 kB)= 120M
內(nèi)存回收命令:echo 3 > /proc/sys/vm/drop_caches
執(zhí)行內(nèi)存回收命令后:
MemFree:
Active: 203456 kB
150460 kB (Active(file)部分被回收)
Active(anon):
Active(file):
Inactive: 141716 kB
8744 kB
60556 kB (Inactive(file)部分被回收
Inactive(anon):
3112 kB
Inactive(file):
57444 kB
MemFree 就等于剩余的內(nèi)存 200M 了, Active 和 Inactive 的內(nèi)容被回收了,主要是 file 部分
被回收了。
75:
Dalvik 虛擬機(jī)內(nèi)存回收方法
1:程序員顯式的調(diào)用 System.gc (not concurrent)
Dalvik_java_lang_Runtime_gc->dvmCollectGarbage
2:內(nèi)存分配失敗時(shí)
gcForMalloc(not concurrent)
3:如果分配的對象大小超過 384KB,觸發(fā)后臺(tái)進(jìn)程回收
gcDaemonThread(concurrent)
4:signalCatcherThreadStart(not concurrent)
也就是進(jìn)程被 kill 掉后
76:
Apk 內(nèi)存泄露的情況
Java 的四種引用方式,比如強(qiáng)引用,軟引用,弱引用以及虛引用。
1: 強(qiáng)引用:
2: 軟引用:
3: 弱引用:
4: 虛引用:
1)BraodcastReceiver,ContentObserver,FileObserver 在 Activity onDestory 或者某類聲明
周期結(jié)束之后一定要 unregister 掉,否則這個(gè) Activity/類會(huì)被 system 強(qiáng)引用,不會(huì)被內(nèi)存
回收。
2) 不要直接對 Activity、Service 等進(jìn)行直接引用作為成員變量,如果不得不這么做,請用
private WeakReference mActivity 來做
3) 不要在 context-activity 里保存長生命周期的引用,使用 Application context 來代替
context-activity
4) 不要在循環(huán)中創(chuàng)建過多的本地變量
參考Apk oom 例子
77:
在標(biāo)準(zhǔn)的 android 啟動(dòng)流程中, android 可以從 boot 分區(qū)和 recovery 分區(qū)啟動(dòng)。在系統(tǒng)
引導(dǎo)初期,也就是還處于 bootloader 階段的時(shí)候,bootloader 會(huì)去檢查 misc 分區(qū)前面幾個(gè)
字節(jié)的字符串(無論是否需要進(jìn)入 recovery 模式,這一步都會(huì)執(zhí)行)。如果這個(gè)幾個(gè)字符
串是“boot-recovery”的話,android 就會(huì)從 recovery 分區(qū)啟動(dòng)進(jìn)入 recovery 模式。在升級(jí)
成功完成之后,misc 分區(qū)的引導(dǎo)標(biāo)志會(huì)擦除,引導(dǎo)程序就不會(huì)進(jìn)入 recovery 模式從而進(jìn)入
正常的啟動(dòng)流程。如果不是,android 就會(huì)從 boot 分區(qū)啟動(dòng)進(jìn)入正常的啟動(dòng)流程。
78:
獲取ServiceManager(IServiceManager)所有的service:? (reference: dumpsys.cpp)
sp sm = defaultServiceManager();
Vector services = sm->listServices();
79:
dumpsys diskstats
dumpsys中service的dump信息去看目標(biāo)service的重載dump函數(shù)都dump了什么
80:binder通信概述
binder通信是一種client-server的通信結(jié)構(gòu),
1.從表面上來看,是client通過獲得一個(gè)server的代理接口,對server進(jìn)行直接調(diào)用;
2.實(shí)際上,代理接口中定義的方法與server中定義的方法是一一對應(yīng)的;
3.client調(diào)用某個(gè)代理接口中的方法時(shí),代理接口的方法會(huì)將client傳遞的參數(shù)打包成為Parcel對象;
4.代理接口將該P(yáng)arcel發(fā)送給內(nèi)核中的binder driver.
5.server會(huì)讀取binder driver中的請求數(shù)據(jù),如果是發(fā)送給自己的,解包Parcel對象,處理并將結(jié)果返回;
6.整個(gè)的調(diào)用過程是一個(gè)同步過程,在server處理的時(shí)候,client會(huì)block住。
81:
獲取命令參數(shù)是 recovery mode 很關(guān)鍵的一步,獲取命令的準(zhǔn)確性直接會(huì)決定此次升級(jí)操作成敗。
recovery 系統(tǒng)有 3 種命令參數(shù)獲取的方式。在 recovery.c 中,獲取命令參數(shù)是由函數(shù)get_args()完成。
get_args()即recovery的三種方式獲取 recovery 所需的參數(shù):(以下方式為降序排列)
1) 實(shí)際的命令行參數(shù),也就是跟傳統(tǒng) Linux 命令行工具一樣的方式傳入長參數(shù)如:
recovery –wipe_data;
2) 來自 BCB(bootloader control block)數(shù)據(jù)結(jié)構(gòu);
3) 來自 COMMAND_FILE 這個(gè)文件
82:
BCB 數(shù)據(jù)結(jié)構(gòu)的定義位于源碼位置 bootable/recovery/bootloader.h. struct bootloader_message
這個(gè)數(shù)據(jù)塊存放于 misc 分區(qū)。 get_args() 函數(shù)首先調(diào)用 get_bootloader_message()函數(shù)獲取 misc 分區(qū)的 BCB 數(shù)據(jù)塊。接著便解析 BCB 中 recovery 字段來獲取命令行參數(shù)。
83:
finish_recovery 中會(huì)將 misc 分區(qū)的 boot-recovery 標(biāo)志位擦除,系統(tǒng)重啟,隨后會(huì)進(jìn)入正
常模式。
84:
clean-$(LOCAL_MODULE)和clean-$(LOCAL_PACKAGE_NAME) 刪除某給模塊的目標(biāo)文件.
比如: clean-Home刪除Home應(yīng)用
make LOCAL_MODULE: 編譯一個(gè)單獨(dú)的模塊(需要有Android.mk文件存在)
85:
pm dump tv.whaley.bugreport | grep versionName查看bugreport版本
86:
AmS大概流程:
首先AMS的Main函數(shù),穿件AMS實(shí)例,建立Android運(yùn)行環(huán)境,得到一個(gè)ActivityThread和一個(gè)Context對象,
然后調(diào)用AMS的setSystemProcess函數(shù),該函數(shù)注冊AMS和meminfo服務(wù)等到ServiceManager中,另外,為system_server創(chuàng)建一個(gè)ProcessRecord對象。此時(shí),system_server也被AMS所管理。
再然后調(diào)用AMS的installSystemProvider函數(shù),為system_server加載SettingProvider 。
最后調(diào)用AMS的systemReady函數(shù),做系統(tǒng)啟動(dòng)完畢前最后一些掃尾工作,該函數(shù)調(diào)用完畢后,Home將會(huì)出現(xiàn)在用戶面前。
87:
ASM的systemReady分析
systemReady函數(shù)完成了系統(tǒng)就緒的必要工作,然后它將啟動(dòng)Home Activity。至此,Android系統(tǒng)就全部啟動(dòng)了。
1) systemReady第一階段的工作
其主要職責(zé)是發(fā)送并處理與PRE_BOOT_COMPLETED廣播相關(guān)的事情。目前代碼中還沒有接收該廣播的地方,不過從代碼中的注釋中可猜測到,該廣播接收者的工作似乎和系統(tǒng)升級(jí)有關(guān)。
2)systemReady第二階段的工作
殺死那些竟然在AMS還未啟動(dòng)完畢就先啟動(dòng)的應(yīng)用進(jìn)程。注意,這些應(yīng)用進(jìn)程一定是APK所在的Java進(jìn)程,因?yàn)橹挥袘?yīng)用進(jìn)程才會(huì)向AMS注冊,而一般Native(例如mediaserver)進(jìn)程是不會(huì)向AMS注冊的。
·? 從Settings數(shù)據(jù)庫中獲取配置信息,目前只取4個(gè)配置參數(shù),分別是:"debug_app"(設(shè)置需要debug的app的名稱)、"wait_for_debugger"(如果為1,則等待調(diào)試器,否則正常啟debug_app)、"always_finish_activities"(當(dāng)一個(gè)activity不再有地方使用時(shí),是否立即對它執(zhí)行destroy)、"font_scale"(用于控制字體放大倍數(shù),這是Android 4.0新增的功能)。以上配置項(xiàng)由Settings數(shù)據(jù)庫的System表提供。
3)systemReady第三階段的工作
·? 調(diào)用systemReady設(shè)置的回調(diào)對象goingCallback的run函數(shù)。
·? 啟動(dòng)那些聲明了persistent的APK。
·? 啟動(dòng)HOME[resumeTopActivityLocked() -> startHomeActivityLocked()]
·? 啟動(dòng)HOME后,發(fā)送ACTION_BOOT_COMPLETED廣播 [activityIdleInternal() -> finishBooting()(系統(tǒng)設(shè)置屬性sys.boot_complted在這個(gè)函數(shù))]
88:
ActivityManagerNative.getDefault().showBootMessage(context.getResources().getText(com.***), false);
直接彈出正在啟動(dòng)的對話框
89:frameworks-res.apk中除了包含資源文件,還包含一些activity(如關(guān)機(jī)對話框), 這些activity其實(shí)運(yùn)行在system_server進(jìn)程中.還有SettingsProvider.apk也運(yùn)行在system_server進(jìn)程中.
90:對于system_server, 它調(diào)用systemMain函數(shù)來創(chuàng)建android運(yùn)行環(huán)境; 而普通apk,它在進(jìn)程的主線程調(diào)用ActivityThread的main函數(shù)來創(chuàng)建android運(yùn)行環(huán)境.
91: Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
這個(gè)應(yīng)該會(huì)截獲進(jìn)程中所有線程拋出的未處理異常.
92:
android中進(jìn)程的死去應(yīng)該會(huì)促發(fā)binderdied, 會(huì)有相應(yīng)的卜告對象被喚醒,處理接下來的標(biāo)準(zhǔn)流程.
93:
1)RefBase中有一個(gè)隱含的影子對象,該影子對象內(nèi)部有強(qiáng)弱引用計(jì)數(shù)
2)sp化后,強(qiáng)弱引用計(jì)數(shù)各增加1,sp析構(gòu)后,強(qiáng)弱引用計(jì)數(shù)各減1
3)wp化后,弱引用計(jì)數(shù)增加1,wp析構(gòu)后,弱引用計(jì)數(shù)減1
完全徹底消滅RefBase對象,包括讓實(shí)際對象和影子對象滅亡,這些都是由強(qiáng)弱引用計(jì)數(shù)控制的, 另外要考慮flag的取值, 當(dāng)flag=0,強(qiáng)引用為0將導(dǎo)致實(shí)際對象被delete; 弱引用為0將導(dǎo)致影子對象被delete.
promote完成后,相當(dāng)于增加了一個(gè)強(qiáng)引用。由弱生強(qiáng)成功后,強(qiáng)弱引用計(jì)數(shù)均增加1,所以現(xiàn)在影子對象的強(qiáng)引用計(jì)數(shù)為1,弱引用計(jì)數(shù)為2.
94:
mkbootimg程序的各參數(shù)是由INTERNAL_BOOTIMAGE_ARGS和BOARD_MKBOOTIMG_ARGS來指定的。這兩個(gè)變量分別取決于其他makefile中的定義。
如BoardConfig.mk中定義的BOARD_KERNEL_CMDLINE在默認(rèn)情況下會(huì)作為--cmdline參數(shù)傳給mkbootimg.
BORAD_KERNEL_BASE則作為--base參數(shù)傳給mkbootimg.
95: boot.img文件結(jié)構(gòu)
boot header : 1page [4K size]
kernel : n page
ramdisk : m page
second page: o page
96: ramdisk.img是個(gè)CPIO文件
cpio -i -F ramdisk.img就解壓出各種文件和文件夾.常用的system目錄,data目錄, init程序等文件都包含在ramdisk.img中。
ramdisk.img中存放的是root根目錄的鏡像。[編譯后可以在out/target/product/{PRODUCT}/root目錄下找到]
97:system.img包含了設(shè)備/system節(jié)點(diǎn)中的內(nèi)容。
98: 生成兩個(gè)升級(jí)包old_target_file.zip和new_target_file.zip, 放在在同一個(gè)目錄下,調(diào)用ota_from_target_files腳本來生成最終的差分包. [Ref:深入理解android內(nèi)核設(shè)計(jì)思想]
ota_from_target_files在生成完整升級(jí)包和差分包都用到.區(qū)別是差分包用到-i.
ota_from_target_files位于build/tools/releasetools/ota_from_target_files.
eg:
./build/tools/releasetools/ota_from_target_files -i ~/***/old.zip ~/***/new.zip
99:
uboot啟動(dòng)流程[兩個(gè)階段]
1: 第一階段 [Mboot中sboot]
U-boot的第一條指令從cpu/arm920t/start.S文件開始
2: 第二階段 [Mboot中board.c]
第二階段從文件/lib_arm/board.c的start_armboot()函數(shù)開始。
1)env_init
2)main_loop.[Mboot中有函數(shù)board_init_r(gd_t *id, ulong dest_addr), 后轉(zhuǎn)到uboot/common/main.c中main_loop()]
3)do_bootm_linux[U-Boot使用命令bootm來啟動(dòng)已經(jīng)加載到內(nèi)存中的內(nèi)核。而bootm命令實(shí)際上調(diào)用的是do_bootm函數(shù)。對于Linux內(nèi)核,do_bootm函數(shù)會(huì)調(diào)用do_bootm_linux函數(shù)來設(shè)置標(biāo)記列表和啟動(dòng)內(nèi)核。]
4)移交控制權(quán)之后,u-boot的使命就算是完成了.
100:
makefile基本規(guī)則,解析過程步驟:
1)變量復(fù)制,環(huán)境檢測等初始化操作
2)按照規(guī)則生成所有依賴樹
3)根據(jù)用戶選擇的依賴樹,從葉到根逐步生成目標(biāo)文件
101:編譯整個(gè)系統(tǒng)時(shí), droid-> 1)droidcore 2)dist_files
102:main.mk解析
main.mk架構(gòu): 除了構(gòu)建droid等依賴樹外,main.mk有一大半內(nèi)容是完成:
1)對編譯環(huán)境的檢測
2)進(jìn)行一些必要的前期處理
eg:整個(gè)想入工程是否需要先進(jìn)行清理工作,部分工具的安裝等。
3)引用其他makefile文件
處處可見,如引用config.mk, cleanbuild.mk等
4)設(shè)置全局變量
這些全局變量決定了編譯的具體實(shí)現(xiàn)過程.
5)各種函數(shù)的實(shí)現(xiàn)
如my-dir, print-vars.
為android系統(tǒng)添加一款定制設(shè)備需要涉及腳本文件:
1)vendorsetup.sh [envsetup.sh調(diào)用]
2)AndroidProducts.mk
3)BoardConfig.mk
4)Android.mk
103:
u-boot與android,recovery交換信息的3個(gè)途徑: (apollo有不一樣)
1: fts.property: 支持雙向信息交換,u-boot,android都可以讀寫
2: kernel commandline: 單向信息交換,由u-boot向android傳遞消息
3: PM SRAM: 單向信息驕傲換,由android向u-boot傳遞信息
PM SRAM:位于"常供電區(qū)", 在ARM主系統(tǒng)reboot后其中的信息仍可以保留
104: U-boot 傳遞 RAM 和 Linux kernel 讀取 RAM 參數(shù)例子:
1)u-boot 給kernel 傳RAM 參數(shù)
./common/cmd_bootm.c 文件中, bootm 命令對應(yīng)的 do_bootm 函數(shù),當(dāng)分析 uI
mage 中信息發(fā)現(xiàn) OS 是 Linux 時(shí) , 調(diào)用 ./lib_arm/bootm.c 文件中的 do_bootm_lin
ux 函數(shù)來啟動(dòng) Linux kernel 。
在 do_bootm_linux 函數(shù)中:
theKernel (0, machid, bd->bi_boot_params);
// 傳給 Kernel 的參數(shù)= (struct tag *) 型的 bd->bi_boot_params
//bd->bi_boot_params 在 board_init 函數(shù)中初始化如對于 at91rm9200 ,初始化在 at91r
m9200dk.c 的 board_init 中進(jìn)行: bd->bi_boot_params =PHYS_SDRAM + 0x100;
// 這個(gè)地址也是所有 taglist 的首地址,見下面的 setup_start_tag 函數(shù)
2)Kernel 讀取U-boot 傳遞的相關(guān)參數(shù)
對于 Linux Kernel , ARM 平臺(tái)啟動(dòng)時(shí),先執(zhí)行 arch/arm/kernel/head.S ,此文件
會(huì)調(diào)用 arch/arm/kernel/head-common.S 中的函數(shù),并最后調(diào)用 start_kernel.而start_kernel函數(shù)中會(huì)調(diào)用 setup_arch 函數(shù)來處理各種平臺(tái)相關(guān)的動(dòng)作,包括了 u-boot 傳遞過來參數(shù)的分析和保存.具體參見函數(shù)setup_arch(&command_line).
setup_arch(&command_line):
...
parse_cmdline(cmdline_p, from); // 處理編譯內(nèi)核時(shí)指定的 cmdline 或 u-boot 傳遞的 cmdline
...
105:
整個(gè)u-boot 的執(zhí)行就進(jìn)入等待用戶輸入命令,解析并執(zhí)行命令的死循環(huán)中。
引導(dǎo)內(nèi)核其實(shí)就是將內(nèi)核讀取到內(nèi)存中然后再跳到那個(gè)地方引導(dǎo).
106:
uboot空間:
由高到低 : top-->hide mem-->tlb space(16K)-->framebuffer space-->uboot code space-->addr
接著,由高到低 : addr-->malloc len(0x400000)-->bd len-->gd len-->12 byte-->addr_sp(棧往下增長,addr_sp之下空間作為??臻g)
107:
對于最精簡能正常啟動(dòng)的uboot,serial和ddr是必須正常工作的。
108:
kernel的入口函數(shù),在arch/arm/kernel/head.S
109:
uboot利用函數(shù)指針及傳參規(guī)范,它將
R0: 0x0
R1: 機(jī)器號(hào)
R2: 參數(shù)地址
三個(gè)參數(shù)傳遞給內(nèi)核。
其中,R2寄存器傳遞的是一個(gè)指針,這個(gè)指針指向一個(gè)TAG區(qū)域。
UBOOT和Linux內(nèi)核之間正是通過這個(gè)擴(kuò)展了的TAG區(qū)域來進(jìn)行復(fù)雜參數(shù)的傳遞,如 command line,文件系統(tǒng)信息等等,用戶也可以擴(kuò)展這個(gè)TAG來進(jìn)行更多參數(shù)的傳遞。TAG區(qū)域的首地址,正是R2的值。
110:
uboot中env的整個(gè)架構(gòu)可以分為3層:
(1) 命令層,如saveenv,setenv editenv這些命令的實(shí)現(xiàn),還有如啟動(dòng)時(shí)調(diào)用的env_relocate函數(shù)。
(2) 中間封裝層,利用不同靜態(tài)存儲(chǔ)器特性封裝出命令層需要使用的一些通用函數(shù),如env_init,env_relocate_spec,saveenv這些函數(shù)。實(shí)現(xiàn)文件在common/env_xxx.c
(3) 驅(qū)動(dòng)層,實(shí)現(xiàn)不同靜態(tài)存儲(chǔ)器的讀寫擦等操作,這些是uboot下不同子系統(tǒng)都必須的。
111:
android編譯中files:
關(guān)于files的編譯中模塊被分為五部分,最核心的是下面兩種:
1)product_FILES:
編譯該產(chǎn)品涉及的相關(guān)文件。與product_FILES有直接聯(lián)系的是product_MODULES,后者則是基于PRODUCT_PACKAGES的處理結(jié)果。product_FILES是各modules需要安裝文件的列表.
2)tags_to_install對應(yīng)的modules
eng,userdebug,user等tag對應(yīng)的模塊
system.img文件就是通過它來生成的,采用的command是:
$(call build-systemimgage-target, $@)
droidcore負(fù)責(zé)生成系統(tǒng)的所有可運(yùn)行程序包,包括system.img, boot.img, recovery.img等.
112:
編譯整個(gè)android系統(tǒng)時(shí)(即droid), 依賴于droidcore和dist_files.
變量ONE_SHOT_MAKEFILE和編譯選項(xiàng)有關(guān)。如果選擇編譯整個(gè)工程項(xiàng)目,那么這個(gè)變量就是空的;否則如果使用了諸如"make,mm"之類的部分編譯命令時(shí),那么在mm的實(shí)現(xiàn)里會(huì)對ONE_SHOT_MAKEFILE進(jìn)行必要的賦值.
在編譯整個(gè)工程的情況下,系統(tǒng)所找到的所有Android.mk將會(huì)先存入subdir_makefiles變量中,隨后一次性include進(jìn)整個(gè)編譯文件中。
113:
android中, mutex只是基于pthread接口的再封裝.
114:
LowMemoryKiller
兩個(gè)重要數(shù)組(lowmem_adj和lowmem_adj_size), android系統(tǒng)提供了相應(yīng)的文件來供我們修改值。
/sys/module/lowmemorykiller/parameters/adj
/sys/module/lowmemorykiller/parameters/minfree
115:
自己改變進(jìn)程的adj(android中稱為oom_adj):
1) 寫文件
路徑為:
/proc/PID/oom_adj.(eg: init.rc中 on early-init write /proc/1/oom_adj-16
2)android:persistent
AndroidManifest.xml文件中"application"標(biāo)簽中添加"android:persistent=true"屬性. 將應(yīng)用程序設(shè)置為常駐內(nèi)存.
116:
Ashmem:將置頂?shù)奈锢韮?nèi)存分別映射到各個(gè)進(jìn)程自己的虛擬地址空間中,從而便捷的實(shí)現(xiàn)進(jìn)程間的內(nèi)存共享。
Ashmem的實(shí)現(xiàn)依托與/dev/ashmem設(shè)備。
117:
Looper內(nèi)部管理了一個(gè)MessageQueue,它將作為線程的消息存儲(chǔ)倉庫,配合Handler,Looper一起完成一系列操作。
118:
Service Manager在Binder通信過程中的唯一標(biāo)志永遠(yuǎn)都是0.
Parcel, Bundle繼承自Parcelable.
Bundle的最大特點(diǎn)就是采取鍵值對的方式存儲(chǔ)數(shù)據(jù),并在一定程度上優(yōu)化讀取效率。
119:
Binder驅(qū)動(dòng)只用了一次復(fù)制,就實(shí)現(xiàn)了進(jìn)程a和b間的數(shù)據(jù)共享.
BINDER_SET_CONTEXT_MGR: Service Manager專用, 將自己設(shè)置為"Binder大管家"。 系統(tǒng)中只能有一個(gè)Service Manager存在
120:
如果要訪問Service Manager(Binder server)的服務(wù), 流程:
1)打開Binder設(shè)備
2)執(zhí)行mmap
3)通過binder驅(qū)動(dòng)向SM發(fā)送請求(SM的handle為0)
4)獲得結(jié)果
每個(gè)進(jìn)程只允許打開以此Binder設(shè)備, 且只作一次內(nèi)存映射-- 所有需要使用Binder驅(qū)動(dòng)的線程共享這一資源。
121:
klog, printk
內(nèi)核緩沖緩沖區(qū)的大小初始值為 4KB,但是最新的內(nèi)核大小已經(jīng)升級(jí)到 16KB
122:
用戶空間訪問和控制內(nèi)核日志有兩個(gè)接口:
(1)通過glibc的klogctl函數(shù)接口調(diào)用內(nèi)核的syslog系統(tǒng)調(diào)用
(2)通過fs/proc/kmsg.c內(nèi)核模塊中導(dǎo)出的procfs接口:/proc/kmsg文件。
__log_buf就是內(nèi)核日志緩沖區(qū)
他們其實(shí)最終都調(diào)用了/kernel/printk.c中的do_syslog函數(shù),實(shí)現(xiàn)對__log_buf的訪問及相關(guān)變量的修改。
從/proc/kmsg中獲取數(shù)據(jù),那么__log_buf中被讀取過的數(shù)據(jù)就不再保留(也就是會(huì)修改log_start指針), 然而 syslog 系統(tǒng)調(diào)用返回日志數(shù)據(jù)并保留數(shù)據(jù)給其他進(jìn)程
123:
IPCThreadState負(fù)責(zé)與Binder驅(qū)動(dòng)進(jìn)行具體的命令交互 [具體在talkWithDriver函數(shù)里的ioctl]
ProcessState只是負(fù)責(zé)打開了Binder節(jié)點(diǎn)并做mmap.
ProcessState:
保證同一個(gè)進(jìn)程中只有一個(gè)ProcessState實(shí)例存在; 而且只有在ProcessState對象創(chuàng)建時(shí)才打開Binder對象以及做內(nèi)存映射.
向上層提供IPC服務(wù)
與IPCThreadState分工合作,各司其職
IPCThreadState:
需要的時(shí)候才會(huì)創(chuàng)建;ProcessState是進(jìn)程中的單實(shí)例,而IPCThreadState是線程中的單實(shí)例
ServiceManager:
在啟動(dòng)后首先會(huì)進(jìn)行一些列的初始化操作,然后通知Binder驅(qū)動(dòng)它即將進(jìn)入循環(huán)狀態(tài),最后通過一個(gè)for語句不斷解析客戶端的請求。
SM會(huì)通過binder_ioctl讀取到getService()請求,之后會(huì)調(diào)用binder_parse()進(jìn)行解析,最后再次調(diào)用ioctl與驅(qū)動(dòng)交互.
124:
對于APK而言, IBinder的真正持有者與使用者是ServiceManagerProxy - 它是Service Manager在本地的代表。
在getService()這個(gè)場景中,調(diào)用者是從Java層的IBinder.transact()開始,層層往下調(diào)用到IPCThreadState.transact(), 然后通過waitForResponse進(jìn)入主循環(huán) -? 直至收到Service Manager的回復(fù)后才跳出循環(huán),并將結(jié)果再次層層回傳到應(yīng)用層。真正與Binder驅(qū)動(dòng)打交道的地方是talkWithDriver中的ioctl().
ServiceManagerProxy:
當(dāng)某個(gè)Binder Server在啟動(dòng)時(shí),會(huì)把自己的名稱name與對應(yīng)的Binder句柄值保存在ServiceManager中。調(diào)用者通常只知道Binder Server的名稱,所以必須想Service Manager發(fā)起查詢請求,就是getService(name).
而Service Managaer自身也是一個(gè)Server, 只不過它的句柄值是確定的(0),因而任何Binder Client都可以直接通過0這個(gè)Binder句柄創(chuàng)建一個(gè)BpBinder, 再通過Binder驅(qū)動(dòng)去獲取Service Manager的服務(wù)。具體就是調(diào)用BinderInternal.getContextObject()來獲得Service Manager的BpBinder.
Binder驅(qū)動(dòng):
重要函數(shù): binder_ioctl,binder_thread_write, binder_thread_read,binder_transaction.
Binder通過只需要一次復(fù)制就把數(shù)據(jù)從一個(gè)進(jìn)程復(fù)制到另一個(gè)進(jìn)程,來使數(shù)據(jù)的傳遞更加高效。
Binder中還保存著大量的全局以及進(jìn)程相關(guān)的變量,用于管理每個(gè)進(jìn)程/線程的狀態(tài),內(nèi)存申請和待辦事項(xiàng)等一系列復(fù)雜的數(shù)據(jù)信息。正是這些變量的有效協(xié)作,使得整個(gè)Binder通信真正動(dòng)了起來。
Service Manager的實(shí)現(xiàn)
ServiceManager在Android系統(tǒng)啟動(dòng)之后就運(yùn)行起來了, 并通過BINDER_SET_CONTEXT_MGR把自己注冊成Binder“大管家". 它在做完一系列初始化后,在最后一次ioctl的read操作中會(huì)進(jìn)入睡眠等待, 直到有Binder Client發(fā)起服務(wù)請求而被Binder驅(qū)動(dòng)喚醒.
Service Manager喚醒后,程序分為兩條線索:
其一, Service Manager端接著執(zhí)行read操作,把調(diào)用者的具體請求讀取出來, 然后利用binder_parse解析, 再根據(jù)實(shí)際情況填寫transaction信息, 最后把結(jié)果通過BR_REPLY命令(也是ioctl)返回Binder驅(qū)動(dòng)。
其二,發(fā)起getService請求的Binder Client在等待Service Manager回復(fù)的過程中會(huì)進(jìn)入休眠, 直到被Binder驅(qū)動(dòng)再次喚醒 - 它和Service Manager一樣也是在read中睡眠的, 因而醒來后繼續(xù)執(zhí)行讀取操作。 這一次得到的就是Service Manager對請求的執(zhí)行結(jié)果。 程序先把結(jié)果填充到reply這個(gè)Parcel中,然后通過層層返回到ServiceManagerProxy,再利用Parcel.readStrongBinder生成一個(gè)BpBinder,最終經(jīng)過類型轉(zhuǎn)換為IBinder對象后傳給調(diào)用者。
125:
StartActivity, bindService,sendBroadcast等都是IPC.
內(nèi)部:
Application 1 -> ServiceManagerProxy -> ActivityManagerProxy -> ProcessState,IPCThreadState -> /dev/binder[Linux Kernel] -> ActivityManagerService [BinderServer] -> ServiceManager -> Application 2
bindService執(zhí)行完綁定目標(biāo)進(jìn)程的Service后,回調(diào)回發(fā)起請求的應(yīng)用程序 (回調(diào)接口是ServiceConnection).
126:
和ServiceManager一樣, AMS也同樣提供了ActivityManagerNative和ActivityManagerProxy.
ActivityManagerNative的作用之一,就是幫助調(diào)用者方便快速取得一個(gè)AcitivtyManagerProxy.
ActivityManagerNative的另一個(gè)作用,為ActivityManagerService的實(shí)現(xiàn)提供便利。
127:
如何獲得Binder Server的服務(wù)
1:Server在ServiceManager中注冊
參見WmS, AmS.通過ServiceManager.getService(SERVICE_NAME)就可以獲取到Binder Server的本地代理.
2:通過其他Server作為中介
在這種情況下, 中介其實(shí)就扮演著ServiceManager的作用. 參見WindowSession.
128:
一個(gè)Binder Server的實(shí)現(xiàn)類通常繼承自Stub, 而Stub又繼承自Binder并實(shí)現(xiàn)了該Server的IXX接口:
public class WindowManagerService extends IWindowManager.Stub
129:
ServiceManager與Binder驅(qū)動(dòng)進(jìn)行交互:
1:ServiceManager通過死循環(huán)不斷執(zhí)行ioctl來獲取用戶的需求
2:Client在獲取ServiceManager的服務(wù)時(shí),是通過ProcessState和IPCThreadState來處理各種細(xì)節(jié).
130:
WindowManagerService這個(gè)使用AIDL的BInder Server與Binder驅(qū)動(dòng)的交互:
1: ProcessState::self()->startThreadPool();? 2:IPCThreadState::self()->joinThreadPool()
1)有talkWithDriver()
2)有dataAcail()? -- 有沒有刻度數(shù)據(jù)
3)有executeCommand
它們將導(dǎo)致程序進(jìn)入一個(gè)類似于binder_loop的主循環(huán). 因而,在這個(gè)進(jìn)程中的Binder對象都可以不用單獨(dú)與驅(qū)動(dòng)進(jìn)行交互.(system_server進(jìn)程)
131:
如何提供一致的服務(wù)接口
aidl文件會(huì)產(chǎn)生出java接口文件, 包括IWindowMnaager, IWindowManager.Stub. IWidnowManager.Stub.Proxy. 后兩者均繼承于IWindowManger.一個(gè)面向WMS的服務(wù)端, 一個(gè)是面向本地客戶端的代理.這樣就保證client和Server是在完全一致的服務(wù)接口上進(jìn)行通信的.
132:
Client準(zhǔn)確訪問到目標(biāo)進(jìn)程中的Binder Server
有兩種可以讓Binder Server可知, 1是在SM中注冊,就是WMS所屬的情況. 2是匿名Server實(shí)現(xiàn).
第一種的實(shí)名實(shí)現(xiàn)具體細(xì)節(jié):
對于實(shí)名的Server, 當(dāng)它利用addService來把自身注冊到SM中時(shí), 會(huì)過Binder驅(qū)動(dòng),Binder驅(qū)動(dòng)會(huì)把這一Binder對象鏈接到proc->nodes, 以及相關(guān)其他數(shù)據(jù)結(jié)構(gòu)。在這里,proc是系統(tǒng)服務(wù)進(jìn)程, 而target_proc是SM. 也就是說,這里SM擁有了一個(gè)描述WMS的binder_node的引用.這樣當(dāng)一個(gè)Binder Client通過getService向SM發(fā)起查詢時(shí),后者就可以準(zhǔn)確告知WMS節(jié)點(diǎn)所在的位置. 這也是為什么在IPCThread的executeCommand時(shí),Client發(fā)過來的請求中會(huì)記錄著WMS的BBinder對象地址的原因.
133:
雙系統(tǒng)中分區(qū)的識(shí)別:
system/core/init/builtins.c:
修改: fstab->recs[i].blk_device = buf; [buf為原來的sysetm,tvservice,tvconfig更新為system1,tvservice1,tvconfig1]
134:
對于Binder驅(qū)動(dòng),只要是路過它且以前沒有出現(xiàn)過的Binder對象, 都會(huì)被記錄下來.
135:
實(shí)名Binder Server:
通過addService把Server添加到SM時(shí)是它第一次"路過"Binder驅(qū)動(dòng),因而會(huì)被記錄到Binder_node中, 并在SM的進(jìn)程信息中添加binder_ref引用. 這樣后面有客戶端需要查詢時(shí),SM就能準(zhǔn)確得出這一Server所在的binder_node位置。
匿名Binder Server:
這個(gè)場景中, IWindowsSession是靠WMS來傳遞的; 并且要等到Binder Client調(diào)用openSession時(shí)才真正的生成一個(gè)Session對象 - 這個(gè)對象作為reply結(jié)果值時(shí)會(huì)第一次'路過'Binder驅(qū)動(dòng) -? 此時(shí)就會(huì)被記錄到系統(tǒng)服務(wù)進(jìn)程的proc->nodes中[即system_server進(jìn)程], 并且target_proc(也就是ViewRootImpl所在進(jìn)程)會(huì)有一個(gè)binder_ref指向這一binder_node節(jié)點(diǎn).
136:
SystemServer中三個(gè)重要的static函數(shù):
1: main() 主函數(shù)
2: init1()? 這個(gè)native函數(shù)主要完成本地層Service(比如SurfaceFlinger, AudioFlinger等)的啟動(dòng),完成后會(huì)主動(dòng)回調(diào)SystemServer中的init2.
3: init2()? 這是啟動(dòng)Java層各Service的地方. 這個(gè)函數(shù)并沒有在當(dāng)前線程直接start各Java層服務(wù), 而是新建一個(gè)線程ServerThread來完成業(yè)務(wù)。
137:
ActivityManagerService兩個(gè)重要類: ActivityStack和ActivityTask.
1)ActivityStack是AMS管理Activity的"大倉庫"
138:
如果AMS通過Intent匹配到的目標(biāo)對象,其所屬程序包中已經(jīng)有其他元素在運(yùn)行, 意味著該程序進(jìn)程已啟動(dòng).接下來, AMS就會(huì)通知這個(gè)進(jìn)程來加載運(yùn)行我們指定的目標(biāo)Activity.
如果當(dāng)前Acitivty所屬程序沒有進(jìn)程在運(yùn)行, AMS就會(huì)先啟動(dòng)它的一個(gè)實(shí)例,然后讓其運(yùn)行目標(biāo)Activity.
139:
Recovery的main()函數(shù):
1) Recovery是個(gè)科執(zhí)行文件程序. 被調(diào)用的時(shí)候會(huì)傳入?yún)?shù)
2) 獲取command: get_args(*).如果命令行有recovery命令, 有線執(zhí)行命令行的recovery命令; 否則, 往下查找misc分區(qū)中的命令、 /cache/recovery/command文件中的命令
3)獲取默認(rèn)升級(jí)固件名稱和名稱
int property_get(const char *key, char *value, const char *default_value);
包括U盤、SD卡和Flash升級(jí)
4) 解析命令
int getopt_long(int, char * const *, const char *,? const struct option *, int *);
5)升級(jí)、格式化、還原
140:
StartActivity:
1) 如果已有進(jìn)程, next.app.thread.scheduleResumeActivity(next.appToken, mService.isNextTransitionForward());
告知目標(biāo)線程要resume指定的Activity.
2) 如果未有進(jìn)程, 首先調(diào)用startSpecificActivityLocked來啟動(dòng)能承受目標(biāo)Activity的進(jìn)程.startSpecificActivityLocked->startProcessLocked()->startProcessLocked(), 最終調(diào)用Zygote來啟動(dòng)一個(gè)新進(jìn)程.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread", app.processName, uid, uid, gids, debugFlags, app.info.targetSdkVersion, null, null);
因此可以看出,當(dāng)一個(gè)應(yīng)用程序進(jìn)程啟動(dòng)時(shí), 實(shí)際上加載了ActivityThread這一主線程.
141:
進(jìn)程啟動(dòng)后還需要通知AMS,后者才能繼續(xù)執(zhí)行之前未完成的startActivity. AMS預(yù)留了一段時(shí)間來等待這一回調(diào), 在不同的設(shè)備上標(biāo)準(zhǔn)有所差異: 要么是10秒,要么是300秒. 假如被啟動(dòng)的進(jìn)程沒有在指定的時(shí)間內(nèi)完成attachApplication回調(diào),那么AMS就認(rèn)為發(fā)生了異常.如果調(diào)用了,那么AMS就會(huì)判斷當(dāng)前是不是有Activity在等待這個(gè)進(jìn)程的啟動(dòng)。如果是的話,就調(diào)用readStartActivityLocked繼續(xù)之前的任務(wù)。接著就是熟悉的Activity的生命周期:onCreate()->onStart()->onResume()等,并且在WMS與SurfaceFlinger的配合下,目標(biāo)Activity描述的UI界面會(huì)呈現(xiàn)到物理屏幕上 - 整個(gè)startActivity流程完成在這里.
142:
FLAG_ACTIVITY_EXCUDE_FROM_RECENTS
如果設(shè)置了這個(gè)標(biāo)志,則Activity不會(huì)被放在最近啟動(dòng)的Activity列表中.
143:
gralloc擔(dān)負(fù)著圖形緩沖區(qū)的分配和釋放, 所以它提供的兩個(gè)最重要的接口是alloc和free.
144:
OTA對系統(tǒng)切換的相關(guān)流程:
1) Mainsystem 寫B(tài)CB的command域boot-command\(?)? 以進(jìn)入recovery
2) Mainsystem 寫/cache/recovery/command寫具體操作(OTA)
3) 重啟進(jìn)入Recovery后, Recovery會(huì)讀取/cache/recovery/command的命令,并放到BCB的recovery域.
145:
Makefile的規(guī)則如下:
target ... : prerequisites ...
command ... ...
target可以是一個(gè)目標(biāo)文件,也可以是Object File(例如helloworld.obj),也可以是執(zhí)行文件和標(biāo)簽。
prerequisites就是生成target所需要的文件或是目標(biāo)。
command
也就是要達(dá)到target這個(gè)目標(biāo)所需要執(zhí)行的命令。這里沒有說“使用生成target所需要執(zhí)行的命令”,是因?yàn)閠arget可能是標(biāo)簽。需要注意的是
command前面必須是TAB鍵,而不是空格,因此喜歡在編輯器里面將TAB鍵用空格替換的人需要特別小心了。
make將makefile的第一個(gè)target作為作為最終的target,凡是這個(gè)規(guī)則依賴的規(guī)則都將被執(zhí)行,否則就不會(huì)執(zhí)行。所以在執(zhí)行make的時(shí)候,clean這個(gè)規(guī)則就沒有被執(zhí)行。
makefile要做的是根據(jù)規(guī)則生成一個(gè)command執(zhí)行隊(duì)列
146:
當(dāng)一個(gè)Android設(shè)備上電后,正常情況它會(huì)先后顯示最多4個(gè)不同的開機(jī)動(dòng)畫。
1:bootloader (靜態(tài)圖片)
2: kernel (靜態(tài)圖片)
3: android (最多兩個(gè))
靜態(tài) +? 動(dòng)態(tài)(bootanimation.? C++程序,? framework/base/cmds/bootanimation, init腳本中啟動(dòng)?)
147:
ISurfaceComposerClient是應(yīng)用程序與SurfaceFlinger之間的橋梁, 而IgraphicBufferProducer是應(yīng)用程序與BufferQueue之間的傳輸通道. SurfaceFlinger職責(zé)是把系統(tǒng)中所有應(yīng)用程序的最終繪制結(jié)果進(jìn)行"混合",然后統(tǒng)一顯示到物理屏幕上. BufferQueue的職責(zé)是每個(gè)應(yīng)用程序一對一的輔導(dǎo)老師,指導(dǎo)者UI程序的"畫板申請", "作畫流程"等一系列繁瑣的細(xì)節(jié), 它是SurfaceFlinger派出的代表.
148:
Linux 輸入子系統(tǒng)概述
輸入設(shè)備(如按鍵,鍵盤,觸摸屏,鼠標(biāo)等)是典型的字符設(shè)備,其一般的工作機(jī)制是低層在按鍵,觸摸等動(dòng)作發(fā)生時(shí)產(chǎn)生一個(gè)中斷(或驅(qū)動(dòng)通過timer定時(shí)查詢),然后cpu通過SPI,I2C或者外部存儲(chǔ)器總線讀取鍵值,坐標(biāo)等數(shù)據(jù),放一個(gè)緩沖區(qū),字符設(shè)備驅(qū)動(dòng)管理該緩沖區(qū),而驅(qū)動(dòng)的read()接口讓用戶可以讀取鍵值,坐標(biāo)等數(shù)據(jù)。
在Linux中,輸入子系統(tǒng)是由輸入子系統(tǒng)設(shè)備驅(qū)動(dòng)層、輸入子系統(tǒng)核心層(Input Core)和輸入子系統(tǒng)事件處理層(Event Handler)組成。其中設(shè)備驅(qū)動(dòng)層提供對硬件各寄存器的讀寫訪問和將底層硬件對用戶輸入訪問的響應(yīng)轉(zhuǎn)換為標(biāo)準(zhǔn)的輸入事件,再通過核心層提交給事件處理層;而核心層對下提供了設(shè)備驅(qū)動(dòng)層的編程接口,對上又提供了事件處理層的編程接口;而事件處理層就為我們用戶空間的應(yīng)用程序提供了統(tǒng)一訪問設(shè)備的接口和驅(qū)動(dòng)層提交來的事件處理。所以這使得我們輸入設(shè)備的驅(qū)動(dòng)部分不在用關(guān)心對設(shè)備文件的操作,而是要關(guān)心對各硬件寄存器的操作和提交的輸入事件。
149:
WMS自己設(shè)計(jì)的構(gòu)想:
1: 對Input(觸摸,鍵盤等)的管理 -? InputManagerService
2: 輸出到SurfaceFlinger? - SurfaceFinger -> 物理屏幕
3: 自己內(nèi)部, 一些列, 窗口大小,排序,等等? - WindowManagerService
4: 還要跟AmS配合啊? - ActivityManager
5: 對具體app的管理啊, 具體app的ActivityThread,里面會(huì)有l(wèi)ooper,一直刷ViewRoot啊? -? Application (ViewRoot)
150:
SurfaceFlinger相當(dāng)于攝像機(jī),只負(fù)責(zé)錄制; WMS相當(dāng)于話劇導(dǎo)演,導(dǎo)演各種站位等; ViewRoot則是演員,具體顯示等全看演技.
151:
具體設(shè)備的驅(qū)動(dòng)的實(shí)現(xiàn):
在Input子系統(tǒng)添加即可:
1)在驅(qū)動(dòng)模塊加載函數(shù)中設(shè)置Input設(shè)備支持input子系統(tǒng)的哪些事件;
2)將該具體設(shè)備注冊到input子系統(tǒng)中
3)在該具體設(shè)備發(fā)生輸入操作時(shí)(如:鍵盤被按下/抬起、觸摸屏被觸摸/抬起/移動(dòng)、鼠標(biāo)被移動(dòng)/單擊/抬起時(shí)等),提交所發(fā)生的事件及對應(yīng)的鍵值/坐標(biāo)等狀態(tài)
152:
Input子系統(tǒng)中:
對具體設(shè)備的:
1)分配
Struct input_dev *input_allocate_device*(void);
2)注冊
Int input_register_device(struct input_dev *dev);
3)被告知要注冊進(jìn)來的設(shè)備,具體支持哪些事件? -? (這個(gè)會(huì)在具體設(shè)備端的驅(qū)動(dòng)那里實(shí)現(xiàn))
Set_bit(EV_KEY,button_dev.evbit)? - Set_bit會(huì)跟Input子系統(tǒng)說自己要支持哪些事件.
153:
對HID的driver而言, 每次的按鍵上報(bào)都是調(diào)用hid_process_event()來完成的,這個(gè)是hid封裝的一個(gè)input device上報(bào)消息的接觸,最終會(huì)調(diào)用input_event()將事件上報(bào).
154:
對于828的藍(lán)牙系統(tǒng):
整個(gè)按鍵流程:
1)RC 發(fā)送按鍵信息到BT的HW部分
2)BT的HW上達(dá)BT的Driver部分(kernel層)
3)上達(dá)協(xié)議棧(so; 用戶層)
4)選擇HID作為輸入渠道
5)HID的uhid在用戶層有接口, 協(xié)議棧調(diào)用接口,傳送按鍵信息到HID的用戶層(可從uhid作為跟蹤的線索)
6)到達(dá)HID的驅(qū)動(dòng)(kernel層)
7)HID對接Linux的Input框架(kernel 層)
8)HID發(fā)送按鍵信息給Input框架(kernel層)
9)Input框架往上傳,到達(dá)用戶層, (event(5)類似), 讀取事件
10)可以在app獲取按鍵事件
155:
編譯系統(tǒng):
1: main.mk? ? -> 依賴
2: config.mk? -> 設(shè)置
3: envsetup.mk? -> 產(chǎn)出
先后順序:
1: main.mk -> 2: config.mk -> 3: envsetup.mk -> 4: product_config.mk -> 5: AndroidProducts.mk -> 6: $(product).mk -> 7: device.mk -> 8: device-common.mk
156:
build.prop的生成是由make系統(tǒng)解析build/core/Makefile完成。
1)Makefile中首先定義各種變量,這在下一步執(zhí)行時(shí)會(huì)用到
2)Makefile中調(diào)用build/tools/buildinfo.sh執(zhí)行腳本, 并輸出到build.prop.(Buildinfo.sh很簡單,只是echo一些屬性)
3)Makefile中直接把$(TARGET_DEVICE_DIR)/system.prop的內(nèi)容追加到build.prop中
4)收集ADDITIONAL_BUILD_PROPERTIES中的屬性,追加到build.prop中; ADDITIONAL_BUILD_PROPERTIES又會(huì)收集PRODUCT_PROPERTY_OVERRIDES中定義的屬性.
建議改在system.prop或PRODUCT_PROPERTY_OVERRIDES,這對應(yīng)于具體特定平臺(tái)或產(chǎn)品的修改.
157:system系統(tǒng)直接調(diào)用另一個(gè)程序
static int mstar_system(const char * cmdstring) {
pid_t pid;
int status;
ALOGI("[%s: %d] cmdstring=\"%s\"\n", __func__, __LINE__, cmdstring);
if (cmdstring == NULL) {
return (1);
}
if ((pid = fork())<0) {
status = -1;
} else if (pid == 0) {
execl("/system/bin/sh", "-c", cmdstring, (char *)0);
exit(127);
} else {
while (waitpid(pid, &status, 0) < 0){
if (errno != EINTR) {
status = -1;
break;
}
}
}
return status;
}
158:
log機(jī)制包括三部分:底層驅(qū)動(dòng)、讀和寫。關(guān)于寫log,我們可以在Java文件中,或者jni層的C/C++代碼中添加類似log.d()這樣的代碼來實(shí)現(xiàn)寫log,通過logcat命令來輸出我們想要查看的log,驅(qū)動(dòng)的任務(wù)則是真正地幫助我們實(shí)現(xiàn)讀和寫。
引用這張圖來說明log的框架。我們在JavaProgram或者Native Program中通過android.util.Log或者System.out或者log.h為我們提供的一下方法如Log.d或者ALOGD,就能把log添加進(jìn)去,最終這些log都被底層驅(qū)動(dòng)寫到了如下四個(gè)設(shè)備中:
/dev/log/main
/dev/log/radio
/dev/log/event
/dev/log/system
之后我們可以通過logcat命令或者Eclipse中的logcat來查看和過濾log,不過這些最本質(zhì)上是調(diào)用logcat命令,Eclipse中的logcat或者adblogcat命令都是對通過adbd進(jìn)程遠(yuǎn)程調(diào)用logcat命令罷了。
159:
Android的log機(jī)制主要包括三部分:讀、寫和驅(qū)動(dòng), 貫穿了應(yīng)用層、framework層和驅(qū)動(dòng)層, 而驅(qū)動(dòng)是核心。