1. 程式人生 > >Android之 MTP框架和流程分析 (3)

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

androidMTP框架流程分析

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

AndroidFresco框架(四)--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

AndroidVolley框架載入網路圖片

更多幹貨 分散式實戰(乾貨) spring cloud 實戰(乾貨) mybatis 實戰(乾貨) spring boot 實戰(乾貨) React 入門實戰(乾貨) 構建中小型網際網路企業架構(乾貨) python 學習持續更

Android 採用execSQLrawQuery方法完成資料的添刪改查操作

/*  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 版本,分析