Android之 MTP框架和流程分析 (3)
前面轉發了篇部落格介紹了MTP, 偏重於上層,已經很清楚了。這篇側重於底層,按照一定的流程講。
1. 程式碼位置
packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.java
packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java
packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java
frameworks/base/media/java/android/mtp/MtpServer.java
frameworks/base/media/java/android/mtp/MtpDatabase.java
frameworks/base/media/java/android/mtp/MtpStorage.java
frameworks/base/media/java/android/mtp/MtpPropertyGroup.java
frameworks/base/media/java/android/mtp/MtpPropertyList.java
frameworks/base/media/java/android/mtp/MtpConstants.java
frameworks/base/media/jni/android_mtp_MtpServer.cpp
frameworks/base/media/jni/android_mtp_MtpDatabase.cpp
frameworks/av/media/mtp/MtpServer.h
frameworks/av/media/mtp/MtpServer.cpp
frameworks/av/media/mtp/MtpDatabase.h
frameworks/base/services/java/com/android/server/usb/UsbDeviceManager.java (UsbManager, UsbService)
kernel/drivers/usb/* (主要是android.c, f_mtp.c)
2. 在Settings設定mtp後,程式碼執行
Usbanager.SetCurrentFunction()
->UsbService.SetCurrentFunction()
->UsbDeviceManager.setCurrentFunctions()
-> mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS)
->setEnabledFunctions(functions, makeDefault);
->SystemProperties.set("persist.sys.usb.config", functions);
此時會呼叫到init.usb.rc執行相應的程式碼
如果直接開機,開機時會在設定persist.sys.usb.config/sys.usb.config時執行init.usb.rc中程式碼(沒有經過framework及以上程式碼)。
write /sys/class/android_usb/android0/enable 0/1
以上程式碼對應執行enable_store (android.c)
enable_store
1)enabled
f->enable(f_holder->f);
adb_android_function_enable
android_disable
usb_ep_dequeue
usb_remove_config
android_enable(dev);
usb_add_config
usb_gadget_connect
2)disabled
android_disable(dev);
usb_ep_dequeue
usb_remove_config
f->disable(f_holder->f)
adb_android_function_disable
usb_add_config(android_bind_config) composite.c
bind()
android_bind_config()
android_bind_enabled_functions()
f->bind_config()
mtp_function_bind_config(mtp)
adb_function_bind_config(adb)
-> usb_add_function()
usb_remove_config()
reset_config(cdev);
unbind_config(cdev, config);
f->unbind(config, f);
****_function_unbind_config()
config->unbind(config);
write /sys/class/android_usb/android0/functions mtp
以上程式碼對應執行functions_store (android.c)
functions_store()
-> android_enable_function()
-> list_add_tail
3. 如果開機後,連上USB線,首先執行chargr檢測,然後是列舉過程 (以高通某晶片為例),這小節講充電器檢測
kernel\drivers\power\qpnp-charger.c
rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
qpnp_chg_usb_usbin_valid_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"usbin-valid", chip);
qpnp_chg_usb_usbin_valid_irq_handler()中斷處理函式,檢測USB插入拔出
在連USB開機的情況下,這個處理函式會在qpnp_charger_probe()呼叫。
首先是電源恢復工作,
power_supply_set_present()
->msm_otg_set_vbus_state(POWER_SUPPLY_PROP_PRESENT)
->msm_otg_sm_work()
->pm_runtime_resume()
->msm_otg_runtime_resume()
->msm_otg_resume()
此時會看到log "USB exited from low power mode"
開始充電器檢測工作
主要函式式msm_chg_detect_work() in msm_otg.c
通常USB線的檢測狀態變化
USB_CHG_STATE_UNDEFINED->USB_CHG_STATE_WAIT_FOR_DCD(迴圈幾次)->USB_CHG_STATE_DCD_DONE
USB線的檢測結果是USB_SDP_CHARGER,
此時會設定otg->phy->state=b_peripheral, 並設定current=100mA
4. 列舉過程
4.1 中斷
ci13xxx_msm.c
ret = request_irq(wake_irq, ci13xxx_msm_resume_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT, "usb resume", NULL);
ret = request_irq(_udc_ctxt.irq, msm_udc_irq, IRQF_SHARED, pdev->name, pdev);
msm_udc_irq()直接呼叫udc_irq(),處理PM and tr complete
isr_reset_handler/isr_suspend_handler/isr_resume_handler/isr_tr_complete_handler
msm_otg.c
Vbus檢測中斷
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
"msm_otg", motg);
msm_otg_irq()->queue_work(system_nrt_wq, &motg->sm_work);->msm_otg_sm_work()
插OTG 線後中斷
msm_pmic_id_irq(), ID pin
4.2 呼叫過程
ci13xxx_udc.c
isr_reset_handler/isr_suspend_handler/isr_resume_handler/isr_tr_complete_handler
(我還不太熟,略過這個部分)
4.3 判讀HS, FS
ci13xxx_udc.c
udc_probe()
udc->gadget.speed = USB_SPEED_UNKNOWN;
udc->gadget.max_speed = USB_SPEED_HIGH; //最大速度
isr_resume_handler()
udc->gadget.speed = hw_port_is_high_speed() ? USB_SPEED_HIGH : USB_SPEED_FULL;
HS/FS是通過函式hw_port_is_high_speed()得到
4.4 判斷Host/Device
msm_otg_start_peripheral(on=1)
這裡通過判斷是SDP_CHARGER,然後設成peripheral(device).
qpnp_chg_usb_usbin_valid_irq_handler: qpnp_chg_usb_usbin_valid_irq_handler usbin-valid triggered: 1 host_mode: 0
上面就可以打印出host_mode, 是通過下面函式得到
host_mode = qpnp_chg_is_otg_en_set(chip);
接OTG線後,可以通過如下中斷處理函式看出
msm_pmic_id_irq(), 主要處理函式msm_pmic_id_status_w()
也可以通過函式得到msm_otg_read_pmic_id_state()
PMIC: ID clear host
PMIC: ID set device
5. 下面才是MTP的單獨部分
5.1 start MTP server
android_work()傳送uevent(USB_STATE=CONFIGURED)給上層
packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.java
handleUsbState()
intent = new Intent(context, MtpService.class);
context.startService(intent);
packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java
onStartCommand
manageServiceLocked() MtpService.java "starting MTP server in MTP mode"
mServer = new MtpServer(mDatabase, mPtpMode);
MtpServer(MtpDatabase database, boolean usePtp) frameworks/base/media/java/android/mtp/MtpServer.java
mServer.start();
frameworks/base/media/jni/android_mtp_MtpServer.cpp
native_setup
android_mtp_MtpServer_setup
int fd = open("/dev/mtp_usb", O_RDWR);
mtp_open() f_mtp.c
MtpServer* server = new MtpServer(fd, getMtpDatabase(env, javaDatabase),..)
packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java
mServer.start();
run() frameworks/base/media/java/android/mtp/MtpServer.java
native_run frameworks/base/media/jni/android_mtp_MtpServer.cpp
android_mtp_MtpServer_run
server->run();
MtpServer::run() frameworks/av/media/mtp/MtpServer.cpp
5.2 主要處理函式
frameworks/av/media/mtp/MtpServer.cpp
MtpServer::run()
infinite loop; read request; send data/response (write)
Read part
mRequest.read(fd);
MtpRequestPacket::read() (MtpRequestPacket mRequest;)
::read(fd, mBuffer, mBufferSize);
mtp_read() f_mtp.c
Write data/response
mData.write
MtpDataPacket::write(int fd)
::write(fd, mBuffer, mPacketSize);
mtp_write() f_mtp.c
mResponse.write
MtpResponsePacket::write
::write(fd, mBuffer, mPacketSize);
mtp_write() f_mtp.c
Event
MtpServer::doGetObject()
ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
mtp_ioctl() in f_mtp.c
MtpServer::doSendObject()
ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
mtp_ioctl() in f_mtp.c
MtpServer::sendObjectAdded/sendObjectRemoved/sendStoreAdded/sendStoreRemoved/sendDevicePropertyChanged
MtpServer::sendEvent(MtpEventCode code, uint32_t param1)
MtpEventPacket::write(int fd)
::ioctl(fd, MTP_SEND_EVENT, (unsigned long)&event);
mtp_ioctl() in f_mtp.c
mtp_send_event()
開始的幾個操作
MTP_OPERATION_OPEN_SESSION (1002)
MTP_OPERATION_GET_DEVICE_INFO (1001)
MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED (9801)
MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED (9801)
MTP_OPERATION_GET_DEVICE_PROP_DESC (1014)
MTP_OPERATION_GET_OBJECT_PROP_LIST (9805)
6. Debug方法
首先看看是哪部分出問題了
a. 檢查main log, UsbDeviceManager, setEnabledFunctions()是否正常
b. 檢查property, persist.sys.usb.config, sys.usb.config, sys.usb.state
c. 檢查sysfs, functions and state, vid, pid
d. 檢查kernel log, 能否看到sent uevent(USB_STATE=CONFIGURED), 同時看看main log, UsbDeviceManager
e. 檢查main log/kernel, MTP server啟動是否正常
f. 如果正常看看命令接收和response是否正常
針對不同出錯地方,仔細看相應部分程式碼
除錯工具
USB sniffer 方便看到所有資料,從協議上看看出錯地方,尤其是可能是PC問題時
對比方法
換PC, 換手機的方法來對比測試
7. 正常log
mtp_bind_config
msm_otg : USB exited from low power mode
msm_otg : chg_type = USB_SDP_CHARGER
msm_hsusb msm_hsusb: vbus online
msm_hsusb msm_hsusb: CI13XXX_CONTROLLER_RESET_EVENT received
msm_hsusb msm_hsusb: CI13XXX_CONTROLLER_CONNECT_EVENT received
msm_hsusb msm_hsusb: reset
msm_otg : Avail curr from USB = 100
android_work: android_work: did not send uevent (0 0 (null))
android_work: android_work: sent uevent USB_STATE=CONNECTED
msm_hsusb msm_hsusb: reset
android_work: android_work: sent uevent USB_STATE=DISCONNECTED
android_work: android_work: sent uevent USB_STATE=CONNECTED
msm_otg : Avail curr from USB = 500
android_work: android_work: sent uevent USB_STATE=CONFIGURED
MtpService: starting MTP server in MTP mode
mtp_open
相關推薦
Android之 MTP框架和流程分析 (3)
前面轉發了篇部落格介紹了MTP, 偏重於上層,已經很清楚了。這篇側重於底層,按照一定的流程講。 1. 程式碼位置 packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.j
android之MTP框架和流程分析
1 static void android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) 2 { 3 Mutex::Autolock autoLock(sMutex); 4 5
Android之 MTP框架和流程分析
1 static void android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) 2 { 3 Mutex::Autolock autoLock(sMutex); 4 5
Android MTP框架和流程分析
packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.java packages/providers/MediaProvider/src/com/android/providers/media/MtpS
Android OTA升級原理和流程分析(一)
這篇及以後的篇幅將通過分析update.zip包在具體Android系統升級的過程,來理解Android系統中Recovery模式服務的工作原理。我們先從update.zip包的製作開始,然後是Android系統的啟動模式分析,Recovery工作原理,如何從
Android OTA升級原理和流程分析(三)---Android系統的三種啟動模式
以下的篇幅開始分析我們在上兩個篇幅中生成的update.zip包在具體更新中所經過的過程,並根據原始碼分析每一部分的工作原理。 一、 系統更新update.zip包的兩種方式 1. 通過上一個文件,我們知道了怎樣製作一個updat
Android OTA升級原理和流程分析(二)---update.zip差分包問題的解決
Android OTA升級原理和流程分析(二)—update.zip差分包問題的解決 在上一篇末尾提到的生成差分包時出現的問題,現已解決,由於最近比較忙,相隔的時間也比較長,所以單列一個篇幅提示大家。這個問題居然是原始碼中的問題,可能你已經制作成功了,不過我的
Spring系列之Spring框架和SpringAOP整合過程分析(十二)
轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80808447 在這篇文章中我們接著上一篇的文章說。在上一篇文章中我們提到了getAdvicesAndAdvisorsForBean這個方法,這個方法的內
Spring系列之Spring框架和SpringAOP整合過程分析(十)
轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80724180 在開始這個系列之前大家先想一下我們是怎麼在專案中使用SpringAOP的(這裡的分析都是基於AspectJ註解的)。我們需要在我們的Spr
Android系統載入Apk檔案的時機和流程分析(1)--Android 4.4.4 r1的原始碼
Android系統在啟動時安裝應用程式的過程,這些應用程式安裝好之後,還需要有一個Home應用程式來負責把它們在桌面上展示出來,在Android系統中,這個預設的Home應用程式就是Launcher了。Android系統的Home應用程式Launcher是由Activit
Android之Fresco框架(四)--ImagePipeline的呼叫和使用
之前大致把ImagePipeline的配置和底層實現都講了一下,這一篇來重點講一下我們在傳送圖片請求的時候是怎麼把請求傳給ImagePipeline的,以及我們如何自己直接對ImagePipeline例項進行請求,記憶體管理等操作。SimpleDraweeView中Image
Android 5.0 Camera系統原始碼分析(3):Camera預覽流程控制流
1. 前言 本文分析的是Android系統原始碼,從frameworks層到hal層,記錄了Camera進入預覽模式的重點程式碼,主要為控制流程的程式碼,有關影象buffer的傳遞暫不涉及,硬體平臺基於mt6735。由於某些函式比較複雜,在貼出程式碼時會適當對
1、Android項目框架搭建 (分析需求、整理資料)
res 菜單 master sliding pan mos 時間 nes oid 閑來無事、想搭個框架試試 分析一般應用 將資料整理整理 粗略統計 須要下面資料 1、android-pulltorefresh 一個強大的拉動刷新開源項目,支持各種控
[Abp 源碼分析] 一、Abp 框架啟動流程分析
arch rep man job dsi 法則 依賴 gconf dep Abp 不一定僅用於 Asp.Net Core 項目,他也可以在 Console 與 WinFrom 項目當中進行使用,所以關於啟動流程可以分為兩種,一種是 Asp.Net Core 項目的啟動流程
C語言基礎之函數和流程控制
argv round ext 組成 htm pre 多個參數 nor ali 函數和流程控制也是每個編程語言的基本概念,函數是劃分模塊的最小單位,良好的函數規劃能直接提升軟件的質量,C語言的流程控制主要由以下幾個語句組成,條件分支語句、選擇語句、循環語句、goto語句、r
滴滴開源Android外掛化框架VirtualAPK原理分析
概述 Activity 支援 Hook ActivityManagerService Hook Instrumentation 啟動外掛Acti
Android之Volley框架載入網路圖片
更多幹貨 分散式實戰(乾貨) spring cloud 實戰(乾貨) mybatis 實戰(乾貨) spring boot 實戰(乾貨) React 入門實戰(乾貨) 構建中小型網際網路企業架構(乾貨) python 學習持續更
Android 之採用execSQL和rawQuery方法完成資料的添刪改查操作
/* Android提供了一個名為SQLiteDatabase的類,該類封裝了一些操作資料庫的API,使用該類可以完成對資料進行新增(Create)、查詢(Retrieve)、更新(Update)和刪除(Delete)操作(這些操作簡稱為CRUD)。對SQLiteData
K8S 原始碼探祕 之 kubeadm join 執行流程分析
一、引言 本文將基於 Kubernetes 1.12 版本,分析 kubeadm join 的執行流程,希望對讀者理解 k8s 有幫助! 關於 init 流程
K8S 原始碼探祕 之 kubeadm init 執行流程分析
一、引言 kubeadm 是 k8s 重要的快速部署工具,也是其原生支援的部署工具,在實現自動化部署方面具有重要的研究價值。 本文將基於 Kubernetes 1.12 版本,分析