国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 學習筆記 > 嵌入式之Android移植學習筆記

嵌入式之Android移植學習筆記 時間:2018-08-23      來源:未知

jni:java native interface java調(diào)用c語言的接口

HAL(hardware abtract layer) 硬件抽象層

binder 虛擬設備,不是硬件,用于進程間通訊(獨立的進程通訊機制)

更為安全高效、拿一段內(nèi)存進行設備通訊、相比共享內(nèi)存安全、可以創(chuàng)建多個

一般學習過程首先研究binder

總結(jié):binder是更為安全高效的進程間通訊機制

libraries 庫 native 本地

C/C++開發(fā)的庫,一般成為本地庫,上層開發(fā)一般是java,對于內(nèi)核而言是應用層

surface Manager 界面開發(fā)、圖形開發(fā)

Media Framework 音頻框架

SQLite 數(shù)據(jù)庫、本地的庫

OpenGL|ES 圖形渲染

FreeType 字體素材

WebKit 瀏覽器的內(nèi)核

SGL 2d圖形渲染

SSL 加密套接層

Libc 標準C庫

Android Runtime 安卓運行時環(huán)境 runtime 一般指運行環(huán)境

Core Libreries

java 虛擬機將代碼解析到對應的平臺

Application Framework

Activity Manager 活動窗口(界面)

Window Manager 窗口管理

Content Provider 數(shù)據(jù)共享,可使2個app共享數(shù)據(jù)

View system 界面渲染

Notification Manager 通知

Package Manager apk包的管理

Telephone Manager 打電話

Resource Manager 資源管理

Location Manager 與GPS相關(guān),定位

XMPP Service 短信接收和發(fā)送

Application

應用程序

home等(laucher)

boot.img 是一個uboot + kernal + rootfs

①source bulid/envsetup.sh

②lunch //envsetup里面的一個函數(shù)

③extract-bsp

④make -j2

⑤pack //打包

boot.img + system.img + recovery.img = 最終產(chǎn)物

如何進行數(shù)據(jù)的傳輸?

①adb devices

②adb push .\文件名 /system/lib

出現(xiàn)系統(tǒng)只讀則需要重新掛載 執(zhí)行 adb remount

③使用adb shell 進入到對應的安卓命令行 //安卓和電腦使用數(shù)據(jù)線連接,usb可調(diào)式確認后才可使用

④使用 adb pull /system/lib/文件名 將對應的文件獲取到當前目錄

使用 exit 退出安卓平臺

⑤使用apk 安裝

adb install *.apk //有個push過程,再進行安裝

關(guān)于linux網(wǎng)絡這塊問題解決

使用局域網(wǎng)時用靜態(tài)ip連接開發(fā)板 橋接

使用wifi時用動態(tài)ip連接網(wǎng)絡 自定義橋接 使用wifi網(wǎng)卡

使用網(wǎng)線動態(tài)ip連接網(wǎng)絡 自定義橋接 使用以太網(wǎng)卡

5層模型

app 應用

app framework 應用框架

libs 核心庫

HAL 硬件抽象層

kernel 內(nèi)核

①source build/envsetup.sh

455-460 添加默認的編譯菜單

1506-1512 查找device和vendor目錄下名稱為vendorsetup.sh腳本并執(zhí)行

查看device/softwinner/fspad-733/vendorsetup.sh

添加產(chǎn)品編譯

8個產(chǎn)品編譯選項保存在 LUNCH_MENU_CHOICES數(shù)組中

②lunch

執(zhí)行build/envsetup.sh 481

488-490,打印選項菜單,讀取用戶輸入值

495-507,根據(jù)用戶輸入選項,從LUNCH_MENU_CHOICES數(shù)組菜單項內(nèi)容,保存到selection變量

518-536,將產(chǎn)品名和編譯類型提取,產(chǎn)品名保存到product,編譯類型保存到variant

544-546,賦值到對應的全局變量,導出

550,設置剩余的環(huán)境變量

551,打印變量列表

③extrap-bsp

將lichee編譯出來,boot.img和modules.ko拷貝到androidL下面,為下一步打包做準備

④make

執(zhí)行androidL/Makefile

執(zhí)行build/core/main.mk

執(zhí)行對應93行,包含build/core/config.mk

跳轉(zhuǎn)到build/core/config.mk

63-99,賦值一些列編譯系統(tǒng)內(nèi)部的子makefile路徑,為后面直接使用,可以編譯成不同類型產(chǎn)物

151,包含build/core/envsetup.mk

跳到該mk下

138行,包含了build/core/product_config.mk

跳轉(zhuǎn)到該文件

189,讀取源碼樹下面所有的名稱為AndroidProducts.mk產(chǎn)品makefile

獲取device/softwinner/fspad-733/AndroidProducts.mk

該文件獲取device/softwinner/fspad-733/fspad_733.mk

定義軟件系統(tǒng)配置 app屬性 copy產(chǎn)品信息

150-155行,查找device和vendor目錄下面產(chǎn)品目錄名為BoardConfig.mk獲取文件

跳轉(zhuǎn)到mk下

獲取文件為 device/softwinner/fspad-733/BoardConfig.mk

該文件進行硬件配置

配置板子上硬件,主要是wifi和bt配置

⑤pack //由于一開始source后即可使用pack命令來進行解析

打包 boot.img+system.img+recovery.img

打包為 lichee/tools/pack/sun8iw3p1_andorid_fspad_733_card0.img

添加一個產(chǎn)品的時候需要在哪些文件上添加?

①device/osoftwinner/fspad-733/vendorsetup.sh 下添加產(chǎn)品菜單

②device/softwinner/fspad-733/AndroidProducts.mk 下添加對應產(chǎn)品文件名

③device/softwinner/fspad-733/fspad_733.mk 軟件添加文件

④device/softwinner/fspad-733/BoardConfig.mk 硬件添加文件

A := a A賦值為a

新建一個文件夾hello

在里面

編寫 hello.c

編寫自己的Android.mk

#current module path

①LOCAL_PATH := $(call my-dir)

#clear vars old value

②include $(CLEAR_VARS)

#module name don't need to specify a path.

③LOCAL_MODULE := hello

#specify source file

④LOCAL_SRC_FILES := hello.c \

world.c\

#build this module to executable binary file

⑤include $(BUILD_EXECUTABLE)

最后

編譯

source build/envsetup.sh

lunch 9

mmm device/softwinner/fspad-733/hello/hello.c //絕對路徑

如果在當前目錄下則為 mm 使用當前路徑來進行編譯模塊

為什么會提示對應的依賴錯誤?

No private recovery resources for TARGET_DEVICE fspad-733

make: Entering directory `/home/linux/fs733/androidL'

make: *** No rule to make target `/hello.c', needed by `out/target/product/fspad-733/obj/EXECUTABLES/hello_intermediates/hello.o'. Stop.

make: Leaving directory `/home/linux/fs733/androidL'

路徑出錯

可能是自己對應的代碼敲寫錯誤導致

adb的使用說明:

adb的使用

使用過程:

1.通過usb線將主機和平板從機連接,打開PhoenixSuit工具,必須顯示和設備已經(jīng)連接上。

2.使用以下命令與平板android系統(tǒng)交互:

a.adb shell 進入到android的linux的命令行模式

exit 進入到命令行模式之后需要的退出

b.adb push 主機需要被推送的文件目錄 平板存放推送文件的位置

將文件推送到從機指定目錄

c.adb pull 平板中需要被拉去出來的文件的位置

從從機拉取文件到主機

d.adb install xxxx.apk 將xxxx.apk android應用程序安裝到從機上

e.adb devices 列出所有連接到主機的從機信息

tips:在敲adb命令的時候,如果提示read-only file system的時候,你就使用命令adb remount 重新掛載一下

android的文件系統(tǒng)就可以了。如果說還是不行,任然提示該信息,那么就要修改從機目錄屬性。

編譯完成后根據(jù)

Install: out/target/product/fspad-733/system/bin/hello

來找到對應目錄將文件拷貝到windows平臺下

打開phoenixSuit程序,連接安卓后

在含有adb.exe的文件下面的空白處點擊 shift + 鼠標右鍵 訓責phoenixSuit運行

使用adb push .\hello /system/bin (由于是執(zhí)行phoenixSuit后,/system/bin直接執(zhí)行)

使用adb shell進入安卓shell

hello 即可打印對應的函數(shù)

init啟動流程

①解析/init.rc

action_list 、service_list

②添加action到action_queue中

③執(zhí)行action相關(guān)命令(與action的序列有關(guān)),查看是否有需要重新啟動的服務,如果有則啟動這些服務

④poll監(jiān)聽3路socket

屬性設置→修改屬性

組合鍵→對應服務

服務進程退出→將標志位置為重啟與restart進行結(jié)合重啟進程

init啟動zygote

①修改進程名

②android Runtime的start方法 啟動虛擬機 vm

③調(diào)用執(zhí)行zygote init的main方法

C++代碼截止

init啟動后執(zhí)行system/core/init/init.c

1059 判斷ueventd 還是init

1060 如果啟動設備,解析設置uevent事件,創(chuàng)建設備文件

1062 若是啟動watchdogd 設置看門狗以及喂狗

1072-1081 創(chuàng)建一些目錄并掛在文件系統(tǒng)

1120 從文件中加載系統(tǒng)屬性默認值

1123 解析init.rc 建立服務鏈表和動作鏈表

1128-1134 創(chuàng)建內(nèi)部action

1139 創(chuàng)建init動作init到動作鏈表

1152 添加early-init動作到動作鏈表

action_for_each_trigger("early-init", action_add_queue_tail);

1145-1154 創(chuàng)建內(nèi)部action并觸發(fā)

①early_init

②wait_for_coldboot_done(內(nèi)部動作)

等待冷啟動設備掃描(為每個設備創(chuàng)建設備文件)

③keychord_init

打開組合鍵的監(jiān)聽文件

④console_init

檢測console終端是否存在,顯示logo

⑤property_service_init

打開屬性修改服務的socket

⑥signal_init

設置sigchild信號處理,回收孤兒進程資源

⑦late-init

⑧queue_property_trigger

促發(fā)rc腳本中property:屬性名= 屬性值 形式的動作

1166 主循環(huán)

①execute_one_command();

執(zhí)行一個命令

②restart_processes();

掃描是否有服務需要重啟

③ 監(jiān)控并處理屬性修改請求、組合按鍵啟動服務請求和檢測服務進程退出

init.rc本地服務被啟動

①ueventd 接收、解析和處理uevent,新建/刪除設備文件,固件加載

②console 終端,啟動shell程序

③adbc adb程序服務端

④service manager 服務管理程序

⑤vold(volume daemon) 完成系統(tǒng)cdrom,usb大量存儲,mmc卡等擴展存儲的掛載任務

⑥netd 網(wǎng)絡服務

⑦surfaceflinger 繪制android程序的ui,完成2d和3d的無縫融合

⑧zygote 啟動虛擬機服務

⑨media 多媒體服務

⑩bootanim 負責android播放開機啟動動畫以及背景音樂

其中關(guān)鍵

①zygote

定義 在init.zygote32.rc

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

class main

socket zygote stream 660 root system

onrestart write /sys/android_power/request_state wake

onrestart write /sys/power/state on

onrestart restart media

onrestart restart netd

可以看到主要啟動的程序 app_process

實現(xiàn)在frameworks/base/cmds/app_process/app_main.cpp‘

186 main函數(shù)

解析參數(shù)后

201行之后得到

227-236 將參數(shù) runtime

246-264 將后面參數(shù)解析出來,得到結(jié)果

301-304 進程名更改nicename = zygote

307 運行類com.android.internal.os.ZygoteInit

runtime.start();

rumtime是AndroidRuntime類

通過找到androidruntime類找到調(diào)用的start成員函數(shù)

frameworks/base/core/jni/AndroidRuntime.cpp 930行

966 啟動java虛擬機

974 注冊andorid本地函數(shù)

988 找到string類

1006 將傳進來的classname com.android.internal.os.ZygoteInit

轉(zhuǎn)換為路徑com/android/internal/os/ZygoteInit

1007 找到com/android/internal/os/ZygoteInit類

1018 com/android/internal/os/ZygoteInit類的main函數(shù)進入到java

ZygoteInit類定義在目錄

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

轉(zhuǎn)到里面 main函數(shù) 644

通過644里面函數(shù) 同時AndroidRuntime那邊將參數(shù)"start-system-server"也傳進來

668行通過注冊 zygote socket服務端

671 預加載了一些資源和庫

686 調(diào)用startSystemServer函數(shù)啟動了systemserver

查看startSystemServer 在573行定義

607行 創(chuàng)建一個子進程來運行forkSystemServer

624調(diào)用handleSystemServerProcess實現(xiàn)在494行

537行 RuntimeInit.zygoteInit();

該函數(shù)定義在rameworks/base/core/java/com/android/internal/os/RuntimeInit.java 267行

查看applicationInit函數(shù)在297行定義

關(guān)鍵321行,invokeStaticMain();

其中第一個參數(shù)就是前面?zhèn)鬟f過來的 com.android.server.SystemServer

該句子調(diào)用了com.android.server.SystemServer類的main函數(shù)

定義在frameworks/base/services/java/com/android/server/SystemServer.java 170

運行了run函數(shù),定義在179

255-257 啟動了好多services

其中316行,ActivityManagerService的systemReady函數(shù),表示ActivityManagerService的ready

ActivityManagerService的定義。frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

在11373,在systemReady調(diào)用startHomeActivityLocked啟動桌面應用

bootanimation

init.rc 中

service bootanim /system/bin/bootanimation

class main

user graphic

group graphics

disabled

oneshot

找到bootanimation源碼 frameworks/base/cmds/bootanimation/bootanimation_main.cpp 39行

55行,創(chuàng)建開機動畫播放線程

找到BootAnimation類,打開可以看到是利用opengl渲染的。

230行,看readyToRun函數(shù)

291行~301行,判斷在/sytem/media目錄下否有bootanimation的素材壓縮包。

313行,在線程循環(huán)函數(shù)中判斷了上面判斷結(jié)果,是否有bootanimation.zip

如果有就播放,如果沒有就調(diào)用android函數(shù)。

328行,android函數(shù)定義

330,331行,可以看到定義圖片的位置。

下面opengl播放圖片。

找到圖片放的位置, find . -depth -name android-logo-mask.png

在frameworks/base/core/res/assets/images/android-logo-mask.png

所以如何定制開機啟動動畫?

1.在/data/local或/system/media目錄下添加自己的動畫bootanimation.zip文件(同時也可以添加相應的開機音樂boot.mp3),這樣在系統(tǒng)啟動時就會播放自己的開機動畫和播放音樂。

2.可以替換一下frameworks/base/core/res/assets/images/ 目錄下兩張圖片。

粗略啟動流程

uboot

內(nèi)核

掛載根文件系統(tǒng)

掛載system系統(tǒng) 里面含有很多文件

執(zhí)行第一個進程init

解析init.rc文件

執(zhí)行了一些列命令,啟動了一些服務,后退化成為一個守護進程

該守護進程 ①系統(tǒng)屬性修改 ②重啟子進程 ③組合鍵按下啟動對應服務

其中有一個很重要的服務zygote

創(chuàng)建虛擬機

運行systemserver 啟動很多java服務

其中有個很重要的服務activityManager執(zhí)行一個systemReady函數(shù)運行了一個界面

VFS 統(tǒng)一文件系統(tǒng)差異,為上層提供接口

HAL

統(tǒng)一下層硬件差異,為上層提供接口

為了保護硬件供應商的知識產(chǎn)權(quán)

不是所用硬件設備都有標準的linux kernel接口

為什么open在modules中,而close在device

每個device是對應不同的關(guān)閉方式,所以在device中關(guān)閉,而打開只需統(tǒng)一打開

hal_*.h

#include

//stub具體某一個device id號

#define LED1 1

//led模塊stub的id

#define LED_HARDWARE_MODULE_ID "led"

①定義一個led_module_t 模塊結(jié)構(gòu)體

里面第一個結(jié)構(gòu)體必須為struct hw_module_t 的對象

struct led_module_t {

struct hw_module_t common;

};

②定義led_device_t 設備結(jié)構(gòu)體

里面第一個為struct hw_device_t 結(jié)構(gòu)體

struct led_device_t {

struct hw_device_t common;

int fd; //存放調(diào)用open返回描述符

int (*led_on)(struct hw_device_t *dev); //

int (*led_off)(struct hw_device_t *dev);

};

hal_*.c

①定義一個hw_module_t 對象HAL_MODULE_INFO_SYM必須為這個對象

在對象里面對其成員進行初始化

struct hw_module_t HAL_MODULE_INFO_SYM = {

tag: HARDWARE_MODULE_TAG,

version_major: 1,

version_minor: 0,

id: LED_HARDWARE_MODULE_ID,//頭文件中含有

name: "led module",

author: "farsight",

methods: &led_module_methods,//主要是實現(xiàn)一些方法

};

②定義一個 hw_module_methods_t 對象led_module_methods 里面裝著一個led_open函數(shù)地址

static struct hw_module_methods_t led_module_methods = {

open: led_open,

};

③定義 led_open函數(shù)

static int led_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device)

{

char devpath[128] = "/dev/";

struct led_device_t *dev;

//函數(shù)中新建一個結(jié)構(gòu)體指針指向led_device_t開辟的空間中

//1.分配描述被打開的設備device結(jié)構(gòu)體

dev = (struct led_device_t *)malloc(sizeof(struct led_device_t));

if (!dev) {

LOGE("alloc device memory failed\n");

return -EFAULT;

}

memset(dev, 0, sizeof(struct led_device_t));

//對其結(jié)構(gòu)體成員進行賦值

//2.填充設備結(jié)構(gòu)體的成員

dev->common.tag = HARDWARE_DEVICE_TAG;.//必須為這個

dev->common.version = 0;

dev->common.module = (struct hw_module_t *)module;

dev->common.close = led_close;

dev->led_on = led_on;

dev->led_off = led_off;

strcat(devpath, name);//devpath設備文件路徑 /dev/name

//通過結(jié)構(gòu)體賦值close、led_on、led_off

//3.調(diào)用系統(tǒng)調(diào)用open,open再通過linux內(nèi)核調(diào)用到驅(qū)動代碼中的led_open函數(shù)

dev->fd = open(devpath, O_RDWR);

if (dev->fd == -1) {

free(dev);

LOGE("open device failed\n");

return -1;

}

//4.返回打開的具體設備的描述結(jié)構(gòu)體指針

*device = &(dev->common);

return 0;

}

④led_on、led_off、led_close的實現(xiàn)

主要是調(diào)用了系統(tǒng)調(diào)用,通過系統(tǒng)調(diào)用將設備的信息傳遞給結(jié)構(gòu)體

static int led_on(struct hw_device_t* device)

{

struct led_device_t *dev = (struct led_device_t *)device;

if (dev->fd != -1)

return ioctl(dev->fd, LED_ON); //調(diào)用系統(tǒng)調(diào)用ioctl,ioctl回去通過linux內(nèi)核調(diào)用到驅(qū)動中unlocked_ioctl

else

return -1;

}

static int led_off(struct hw_device_t* device)

{

struct led_device_t *dev = (struct led_device_t *)device;

if (dev->fd != -1)

return ioctl(dev->fd, LED_OFF);

else

return -1;

}

static int led_close(struct hw_device_t* device)

{

struct led_device_t *dev = (struct led_device_t *)device;

if (dev->fd != -1) {

close(dev->fd);//調(diào)用系統(tǒng)調(diào)用close,close回去通過linux內(nèi)核調(diào)用到驅(qū)動中l(wèi)ed_close

free(dev);

}

return 0;

}

lib中

使用hal提供的框架接口 hw_get_module();//獲取到對應hal里模塊的結(jié)構(gòu)體地址

通過訪問這個結(jié)構(gòu)體的methods里的led_open即可調(diào)用到底層的open

touch可以更新對應的代碼時間戳,使編譯的時候重新編譯

整體一個流程:

①app上 通過led_open會調(diào)用coreLib庫

②庫中使用hal接口函數(shù)hw_get_module();

來通過LED_HARDWARE_MODULE_ID進行獲取到對應的模塊module,

③通過獲取模塊中的第一個成員hw_modules_t 中的mothods方法集合里面的open方法將對應的模塊傳入進入到hal中

④在hal中通過上面?zhèn)魅胂聛淼膎ame,將器設備路徑給獲取后,通過打開設備驅(qū)動的open函數(shù)即完成獲取,并且創(chuàng)建一個led_dev結(jié)構(gòu)體,通過結(jié)構(gòu)體進行初始化,將其傳遞給在coreLib中的device對象,便于后續(xù)的操作使用,雖然傳遞過去的不是led_dev對應的結(jié)構(gòu)體,但是由于hw_device_t與對應結(jié)構(gòu)體的首地址一致,所以通過強轉(zhuǎn)即可獲取到led_dev對應的方法

Android硬件抽象層框架代碼在 hardware目錄

Dalvik虛擬機作用:

①Dalvik基于虛擬機,JVM基于棧,所以效率更高

②Dalvik可運行壓縮過,針對內(nèi)存優(yōu)化過的dex,減少文件尺寸,提高查找類的速度

③Dalvik每一個應用程序運行與一個獨立進程

android系統(tǒng)中,使用 make ramdisk命令 只編譯文件系統(tǒng)

android系統(tǒng)app framework層,HAL層,core Libs 代碼編譯之后在system.img

通過GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V")找到對應的方法應該

①([Ljava/lang/String;)V") ===》 [ 數(shù)組 String =》tring 類型,參數(shù) V ===》void 返回值

②main為函數(shù)名 即可推出 void main (String [] )

init.rc包含5個部分

①import導入 ②commond命令 ③service服務 ④action行為 ⑤option選項

簡述linux內(nèi)核編譯步驟

①進入lichee ./build.sh config //編譯選擇配置

②./build.sh 編譯內(nèi)核和uboot

簡述android源碼的編譯步驟(以fspad-733配套androidL源碼為例)進入androidL

①source build/envsetup.sh 添加配置調(diào)試命令到shell進程

②lunch 選擇編譯的產(chǎn)品好

③extract-bsp 將內(nèi)核生成的bImage和模塊拷貝到androidL/device/softwinner/fspad-733/下

④make -j2 編譯

androidL ===>生成 system.img(非內(nèi)核部分) + ramdisk.img(rootfs) + recovery.img(恢復出廠鏡像)

lichee ===>生成 uboot.bin + uImage === > bImage

簡單介紹一下Android系統(tǒng)中的HAL,并說出舊HAL架構(gòu)libhardware_legacy和新HAL架構(gòu)libhardware的區(qū)別

①屏蔽下層硬件差異,為上層提供統(tǒng)一接口

②保護硬件的知識產(chǎn)權(quán)

③硬件設備不全都有l(wèi)inux kernel接口

舊的沒有經(jīng)過封裝,上層可以直接操走硬件

新的通過hal層將硬件分類,一個類一個stub,通過stub再進行訪問

請介紹Android系統(tǒng)架構(gòu),并簡單說明每層架構(gòu)的作用

①linux內(nèi)核 在內(nèi)核基礎上添加了android特有的驅(qū)動,binder驅(qū)動(進程間通訊)

②HAL 屏蔽下層差異,為上層提供統(tǒng)一接口

③核心庫 libs 一些三方庫和c/c++庫的提供,

runtime Dalvik虛擬機和對應的運行環(huán)境

④app framework 讓應用開發(fā)更為方便

⑤app 一些與用戶進行交互的程序

android源碼樹添加新產(chǎn)品目錄支持,必須有哪幾個文件?

①vendorsetup.sh 添加產(chǎn)品編譯的選項

②BoardConfig.mk 硬件方面定制

③AndroidProduct.mk 產(chǎn)品文件列表

④產(chǎn)品名.mk 定制軟件系統(tǒng)的配置

上一篇:c語言指針詳解,學霸課堂記錄

下一篇:C++學習總結(jié),學霸課堂筆記

熱點文章推薦
華清學員就業(yè)榜單
高薪學員經(jīng)驗分享
熱點新聞推薦
前臺專線:010-82525158 企業(yè)培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權(quán)所有 ,京ICP備16055225號-5京公海網(wǎng)安備11010802025203號

回到頂部