編輯:關於Android編程
Android vold 全稱 Android volume daemon,實際是負責完成系統的CDROM,USB大容量存儲,MMC卡等擴展存儲的掛載任務自動完成的守護進程。
一.底層分析入口
System\vold\Main.cpp文件入口
int main(){
………..
if(!(vm = VolumeManager::Instance())){
…..
}
if(!(nm = NetlinkManager::Instance())){
…..
}
cl = new CommandListener();
vm->setBroadcaster((SocketListener*)cl);
nm->setBroadcaster((SocketListener*)cl);
if(vm->start()){//這裡沒有做什麼
……
}
If(process_config(vm)){
…..
}
if(nm->start()){//重要的是看這裡
}
…..
if(cl->startListener()){
…..
}
}
1.查看system\vold\VolumeManager.cpp
VolumeManager *VolumeManager::Instance(){
if(!sInstance)
sInstance = new VolumeManager();
return sInstance;
}
2.查看system\netd\NetlinkManager.cpp
NetlinkManager *NetLinkManager::Instance(){
if(!sInstance)
sInstance = new NetLinkManager ();
return sInstance;
}
3.system\vold\CommandListener.cpp
CommandListener::CommandListener():
FrameworkListener(“vold”){//這裡傳入的是一個vold的,表示會創建一個名字為vold類型的Socket
…………
}
4. system\core\libsyscutils\src\FrameworkListener.cpp
FrameworkListener::FrameworkListener(const char *socketName):
SocketListener(socketName,true){
……………….
}
5.system\core\libsysutils\src\SocketListener.cpp
SocketListener::SocketListener(const char *socketName,bool listen){
………….
根據socketName創建Socket
}
6.SocketListener::SocketListener(int socketFd,bool listen){
………….
socketFd是一個Socket對象
}
從上面的5中可以查看這裡創建的是一個名字為vold的Socket對象
7. 查看system\netd\NetlinkManager.cpp
int NetlinkManager::start(){
struct sockadd_nl nladdr;
int sz = 64 * 1024;
int on = 1;
memset(&nladdr,0,sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr_nl_pid = getpid();
nladdr_nl_groups = 0xffffffff;
//這裡創建的是AF_NETLINK類型協議的Socket,此協議主要用來用戶空間和內核空間通信
if((mSock = socket(PF_NETLINK,
SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0){
……………
}
…………
if(bind(mSock,(struct sockaddr*)&nladdr,sizeof(nladdr)) < 0){
……………..
}
mHandler = new NetLinkHandler(mSock);
if(mHandler->start()){
………………..
}
Return 0;
}
8.system\netd\NetlinkHandler.cpp
NetLinkHandler::NetlinkHandler(NetlinkManager *nm,int listenerSocket):
NetlinkListener(listenerSocket){
…………
}
9.system\core\libsyscutils\src\NetlinkListener.cpp
NetLinkListener::NetlinkListener(int socket):
SocketListener(socket,fase){
}
此時我們已經創建了兩個Socket的
一個是名字為vold的Socket對象
另一個是AF_NETLINK協議的Socke對象
二.這裡我們分析Socket對象
啟動入口時在system\vold\Main.cpp
cl->startListener()這一行
跟蹤可以看到這個方法是在CommandListener類的父類中的父類裡
即SocketListener類
int SocketListener::startListener(){
………………….
if(){
}else if(!mListen){
mClients->push_back(new SocketClient(mSock));
}
…………..
//啟動線程來處理Socket
If(pthread_create(&mThread,NULL,SocketListener::threadStart,this)){
……………
}
}
線程會調用
Void SocketListener::runListener(){
………………………….
這裡用重要的兩步
mClients->push_back(new SocketClient(c));
…………………..
由於名字為void 的Socket會調用在FrameworkListener的OnDataAvailable方法中會讀取Socket中的數據,並會向發送端寫入數據
而AF_NETLINK會調用NetlinkListener .cpp中的OnDataAvailable方法
onDataAvailable(*it)
…………………………………….
}
1.NetlinkListener.cpp(在NetlinkManager.cpp中創建) 中的onDataAvailable方法又會調用 NetLinkHandler::OnEvent方法,此方法最終會根據nm->setBroadcaster((SocketListener*)cl);方法注入的回調類,從而調用回調類中的SendBroadcast方法,
此時回調類就是CommandListner.cppp ,而SendBroadcast方法在它的父類的父類,即SocketListener類中
Void SocketListner::sendBroadcast(int code,const char *msg,bool add Error){
……………..
for(i = mClients->begin(); i != mClient->end();++i{
if((*i)->sendMsg(code,msg,addErrno)){//向socket中寫入數據,即向客戶端發送數據
……………….
}
}
}
2.FrameworkListener.cpp(由CommandListener.cpp創建)類中的onDataAvailable方法會讀取Socket中數據,並且會調用dispathCommand方法來處理讀取到的命令數據,詳細可以看
System\vold\CommandListener.cpp
int CommandListener::***::runCommand()方法,這裡處理客戶端對Sd card的一些操作,如
mount,unmount,list,shared,unshare,format 等等
這些操作主要是通過調用VolumeManager中的方法來完成的
三.分析客戶端
1.分析AF_NETLINK 類型的Socket對象的客戶端
(1) 在framework中有一些類如
BatteryService.java DockObserver.java, HookSwitchObserver.java UsbMonitor.java
UsbService.java 等等
這些類中都以看到 對UEventObserver類的用法,這個對象主要是用來監聽系統進程對用戶進程發送的消息
(2) UEventObserver類在frameworks\base\core\java\android\os\UEventObserver.java
Public abstract class UEventObserver{
……………….
Private staic class UEventThread extends Thread{
…………….
public void run(){
native_setup();//此方法是一個native方法(1)
bute[] buffer = new buffer[1024];
int len;
while(true){
len = next_event(buffer);// /此方法是一個native方法(2)
………………..
}
}
}
}
(3)對應的JNI類在frameworks\base\core\jni\android_os_UEventObserver.cpp
static int android_os_UEventObserver_native_setup(JNIEnv *env,jclass clazz){
If(!uevent_init()){
}
}
Static int android_os_UEventObserver_next_event(JNIEnv *env,jclass clazz,jbyteArray jbuffer){
………….
Int length = uevent_ext_event(buffer,buf_sz-1);
}
本篇文章講的是Android 自定義ViewGroup之實現標簽流式布局-FlowLayout,開發中我們會經常需要實現類似於熱門標簽等自動換行的流式布局的功能,網上也有
兩個彈出框布局: java 文件: package hi.braincol.example.iphoneA
1. Re-installation failed due to different application signatures. 將原來的軟件包刪除掉,然後重新安裝一
對Android的啟動模式不是很了解,這裡記錄下簡單的理解內容以便日後查看。 Androi的四種啟動模式分別為:standard,singleTop,singl