Android之 MTP框架和流程分析 (3)

2024-06-03 15:48
文章标签 分析 android 流程 框架 mtp

本文主要是介绍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)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027424

相关文章

MySQL 临时表与复制表操作全流程案例

《MySQL临时表与复制表操作全流程案例》本文介绍MySQL临时表与复制表的区别与使用,涵盖生命周期、存储机制、操作限制、创建方法及常见问题,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小... 目录一、mysql 临时表(一)核心特性拓展(二)操作全流程案例1. 复杂查询中的临时表应用2. 临时

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

MySQL 升级到8.4版本的完整流程及操作方法

《MySQL升级到8.4版本的完整流程及操作方法》本文详细说明了MySQL升级至8.4的完整流程,涵盖升级前准备(备份、兼容性检查)、支持路径(原地、逻辑导出、复制)、关键变更(空间索引、保留关键字... 目录一、升级前准备 (3.1 Before You Begin)二、升级路径 (3.2 Upgrade

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致