android下usb框架系列文章---(4)android下的光盘功能控制

一 使能光盘功能

 

1. 1内核项中增加cd-rom文件系统的支持

 alps/mediatek/config/xxxx/autoconfig/kconfig/project

         #

         # CD-ROM/DVD Filesystems

         #

         CONFIG_ISO9660_FS=y

         CONFIG_JOLIET=y

         CONFIG_ZISOFS=y

         # CONFIG_UDF_FS is not set

1.2 挂载iso文件到/mnt/cd-rom目录下

 alps/mediatek/config/xxxx/init.project.rc

         mount ext4 emmc@android /system waitcommit=1,noauto_da_alloc

         mount iso9660 loop@/system/mobile_toolkit/iAmCdRom.iso /mnt/cd-romro

         mkdir/system/secro 0600 system system

注意:由于mtk编译规则除了编译用户目录下的文件,还会处理mt6575平台下的目录。

Mt6575下的init.rc

mkdir /mnt/cd-rom 0000 system system

mount iso9660 loop@/system/mobile_toolkit/iAmCdRom.iso /mnt/cd-romro

1.3 定义系统属性变量(ro.sys.usb.storage.type)

alps/mediatek/config/xxxx/system.prop 

          # audio

          ro.camera.sound.forced=0

          ro.audio.silent=0

         #ipo

          sys.ipo.tbl=1

         # USB Config Type

         ro.sys.usb.storage.type=mtp,mass_storage

这个选项是用来让设备工作在mtp+cdrom的情形下,如果工作在ums+cdrom情形下的话,ro.sys.usb.storage.type=mass_storage

对于系统变量ro.sys.usb.storage.type在下面的文件中用到了。                              frameworks/base/services/java/com/android/server/usb/UsbDeviceManager.java

mUsbStorageType= SystemProperties.get("ro.sys.usb.storage.type",UsbManager.USB_FUNCTION_MTP);

Framework层有专门对usb设备的管理。这个目录下有4个文件,device和host管理,service文件和settingmanage文件。属于android中的service。

Todo:这部分代码需要看,以便打通usb从上到下的通路。

1.4 增加整个工程的编译控制宏(MTK_BICR_SUPPORT)

alps/mediatek/config/xxxx/ProjectConfig.mk(AUTO_ADD_GLOBAL_DEFINE_BY_NAME 最后加上MTK_BICR_SUPPORT)

          AUTO_ADD_GLOBAL_DEFINE_BY_NAME= …. MTK_BICR_SUPPORT

    文件中加入MTK_BICR_SUPPORT=yes

宏定义的生效还得通过设置为yes来完成。如果不想启动mtp,启动ums。需要加入MTK_MASS_STORAGE=yes。当这个宏被定义后,build\core\main.mk中的以下代码将会起作用。用来记录系统当前的一些属性变量值。和上面的ro.sys.usb.storage.type一样。大部分在下面的文件中出现:

frameworks/base/services/java/com/android/server/usb/UsbDeviceManager.java

frameworks/base/core/java/android/hardware/usb/UsbManager.java

String config= SystemProperties.get("persist.sys.usb.config",UsbManager.USB_FUNCTION_MTP);

这个属性变量在初始化时是在init.usb.rc中首先起作用的,会根据这个变量的值来操作sys/class/android_usb下的文件,来写入vid/pid以及androidusb gadget复合设备支持的function。

build\core\main.mk

#defaulusb function

ifeq ($(strip $(MTK_MASS_STORAGE)),yes)

ADDITIONAL_DEFAULT_PROPERTIES +=persist.sys.usb.config=mass_storage

else
ifeq ($(strip $(MTK_BICR_SUPPORT)),yes)

ADDITIONAL_DEFAULT_PROPERTIES +=persist.sys.usb.config=mtp,mass_storage

else
ADDITIONAL_DEFAULT_PROPERTIES +=persist.sys.usb.config=mtp

endif
endif

Umsmtp不能共存,mtpcdrom可以共存。

//shareman:上面这几个修改配置的地方都是在mediatek/config/a2_3g_data目录下,也就是说在mtk平台下,当用户要修改配置项时都是在自己的项目目录下修改。

内核项配置:autoconfig/kconfig/project

工程的初始化、启动配置:init.project.rc

系统存储设备参数默认初始值:system.prop

整个工程级别的配置:ProjectConfig.mk

下面这个storage_list.xmlframework层面关于storage的一些配置。

1.5 使能allowMassStorage(storage_list.xml)

alps/mediatek/custom/xxxx/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml           

2207上这个默认是加上的

<StorageListxmlns:android="http://schemas.android.com/apk/res/android">

   <!-- removable is not set in nosdcard product-->

   <storage android:mountPoint="/mnt/sdcard"

                                android:storageDescription="@string/storage_phone"

                                android:allowMassStorage="true"

                                android:primary="true" />

                                

   <storageandroid:mountPoint="/mnt/sdcard2"

                                android:storageDescription="@string/storage_sd_card"

                                android:removable="true"

                                android:allowMassStorage="true"

                                android:primary="false" />

</StorageList>

这个的作用没有看明白,todo

1.6. 增加开机时usb功能初始化文件

 alps/mediatek/config/xxxx/init.usb.rc

  这个文件里的vid/pid信息需要根据产品情况做修改。

oninit

#Workarunod for USB unknow device issue

# USBwould switch correct function whenset properity sys.usb.config

   setprop sys.usb.vid 0BB4

   write /sys/class/android_usb/android0/iSerial$ro.serialno

   write /sys/class/android_usb/android0/idVendor$sys.usb.vid

   write /sys/class/android_usb/android0/idProduct2008

   write /sys/class/android_usb/android0/functionsmass_storage //这只是个默认值

   write /sys/class/android_usb/android0/enable 1

 

onpost-fs-data

   chown system system/sys/class/android_usb/android0/f_mass_storage/lun/file

   chmod 0660/sys/class/android_usb/android0/f_mass_storage/lun/file

   chown system system/sys/class/android_usb/android0/f_rndis/ethaddr

   chmod 0660/sys/class/android_usb/android0/f_rndis/ethaddr

 

   write /sys/class/android_usb/android0/f_rndis/wceis1

   write /sys/class/android_usb/android0/f_rndis/manufacturerMediaTek   

   write /sys/class/android_usb/android0/f_rndis/vendorID$sys.usb.vid

 

# Usedto set USB configuration at boot and to switch theconfiguration

# whenchanging the default configuration

onproperty:persist.sys.usb.config=*

   setprop sys.usb.config $persist.sys.usb.config

 

# Usedto disable USB when switching states

onproperty:sys.usb.config=none

   stop adbd

   write /sys/class/android_usb/android0/enable 0

   write /sys/class/android_usb/android0/bDeviceClass 0

   setprop sys.usb.state $sys.usb.config

 --------------------------------------

#25.USBaccessory configuration

onproperty:sys.usb.config=accessory

   write /sys/class/android_usb/android0/enable 0

   write /sys/class/android_usb/android0/idVendor 18d1

   write /sys/class/android_usb/android0/idProduct 2d00

   write /sys/class/android_usb/android0/functions$sys.usb.config

   write /sys/class/android_usb/android0/enable 1

   setprop sys.usb.state $sys.usb.config

1.7 制作ISO文件及autorun

Iso 文件制作:

工具ultraISO

1 更改光盘显示的名称

2 将要在光盘中存放的文件,拖拽到光盘处,文件à保存,ok

android下usb框架系列文章---(4)android下的光盘功能控制

3制作autorun.inf

      光盘的一些属性需要通过autorun.inf来完成。

下面是自动运行wmp11-windowsxp-x86-ZH-CN.exe

[autorun]

open=wmp11-windowsxp-x86-ZH-CN.exe

4 iso文件的更新

使用工具制作iso文件后,通过adbpush到设备上。重启后将mount新的iso文件。

(Iso文件alps\system\mobile_toolkit)

注意quick boot是假关机,不能重新挂载

mount iso9660loop@/system/mobile_toolkit/iAmCdRom.iso /mnt/cd-rom ro

系统启动时,将iso文件挂载到了/mnt/cd-rom目录下

Todo:如何将inf形式的驱动做成可执行的驱动文件

1.8 不同pid驱动问题

由于以前的pid是7498,对应的功能为adb/mtp

现在使用了cdrom,对应的功能为adb/mtp/mass-storage,pid为749D

而这时碰到了adb和mtp驱动不能工作的问题,需要重新安装adb驱动,在googleandroid_winusb.inf文件中重新加入对该pid的支持。

%CompositeAdbInterface%    = USB_Install,USB\VID_17EF&PID_749D&MI_02

代表复合设备,adb接口,对应的是接口2

但是mtp的驱动仍然不好使呢?即使去掉了adbdebug功能。

Android原生的mtp有问题,当和其他功能复合使用时,驱动不能自动安装。

注意:注册表中设备驱动记录项,

路徑:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB

  遇到一次,inf文件中明明有对应的adbpid,更新驱动失败,后又重新添加了一遍,就成功了。

犯了一个大错误,当时出现了问题,只是草草解决,却没有知其所以然。后来出了问题。在解决上面的驱动时,当时发现了怎么有pid还不行,随便拷贝了一下。就解决了,没有考虑为什么。原来分别是64位机和32位机的驱动。

找到[Google.NTx86] 或 [Google.NTamd64] 字样,然后添加以下文本,看起来就像下面所示(红色部分替换为你的。第一行红色字是你的设备名称,第二行红色字是第3步骤所记录的硬件Id):

[Google.NTx86]
; HTC Desire HD
%CompositeAdbInterface% =USB_Install, USB\VID_0BB4&PID_0CA2&MI_01

 

 

Temprecord:

2012-5-24

mtp修改为ums功能

1

alps/mediatek/config/xxxx/ProjectConfig.mk

AUTO_ADD_GLOBAL_DEFINE_BY_NAME=….  MTK_BICR_SUPPORT

最下方再補上 MTK_BICR_SUPPORT=yes

添加:

AUTO_ADD_GLOBAL_DEFINE_BY_NAME= ….MTK_MASS_STORAGE

MTK_MASS_STORAGE =yes

 

2alps/mediatek/config/xxxx/system.prop 

          # audio

          ro.camera.sound.forced=0

          ro.audio.silent=0

         #ipo

          sys.ipo.tbl=1

         # USB Config Type

         ro.sys.usb.storage.type=mtp,mass_storage

改为:   ro.sys.usb.storage.type=mass_storage

 

结果:弹出2个可移动磁盘和一个光盘,但是移动磁盘没有介质。

查看cd-rom的file文件,sys/class/android_usb/f_mass_storage/lun-cdrom

内容为:/dev/block/loop0

原来是pad下方有一个bar,需要turnon mass_storage

 

PR:后来发现在以前mtp+光驱的配置时,

AUTO_ADD_GLOBAL_DEFINE_BY_NAME= …. MTK_MASS_STORAGE这个是有的。

MTK_MULTI_STORAGE_SUPPORT MTK_MULTI_STORAGE_SUPPORT=YES这个也是有的.

而这个时候为什么没有弹出u盘,而是以mtp形式出现的?

难道mtpums冲突,只能以一个呈现?是pad的上层有设定么?原理上确实是不能有两个功能同时使用一个介质sd卡。所以是不能同时使用的。

在没有任何修改时,sys/class/android_usb/anroid0/functions 内容为mtp,adb,也就是说function没有使能的话,如mass_storage是不会被bind的。

使用mtp+光驱的方式,sys/class/android_usb/anroid0/functions内容为mtp,mass-storage,adb

使用上面修改的方式,ums+光驱sys/class/android_usb/anroid0/functions内容为mass-storage,adb

1.9 光驱弹出行为

        见如下光盘bicr介质的挂载流程。

 

 

附录:

 

ISO 9660 CDROM file systemsupport (ISO9660),This is the standard file systemused on CD-ROMs. The so-called Rock-Ridge extensions which allowfor long Unix filenames and symbolic links are also supported bythis driver. If you have a CD-ROM drive and want to do more with itthan just listen to audio CDs and watch its LEDs, say Y

Microsoft Joliet CDROM extensions(Joliet) is a Microsoft extension for the ISO 9660CD-ROM file system which allows for longfilenames in unicode format 。Say Y here if you want to be able to read JolietCD-ROMs under Linux.  微软的扩展,用于cd-rom上的长文件名,unicode格式。

Transparent decompressionextension(ZISOFS), This is aLinux-specific extension to RockRidge which lets you store data incompressed form on a CD-ROM and have it transparently

decompressed when the CD-ROM isaccessed.  say Y here if you want to be able toread such compressed CD-ROMs.  Linux的扩展,用于cd-rom上的压缩格式

光盘挂载:

1、将文件和目录制作成光盘镜像文件,执行下面的命令。

 #mkisofs -r -J -V mydisk -o /home/sunky/mydisk.iso/home/sunky/ mydir

注:这条命令将/home/sunky/mydir目录下所有的目录和文件制作成光盘镜像文件/home/sunky/mydisk.iso,光盘卷标为:mydisk

2、光盘镜像文件的挂接(mount)

  #mkdir /mnt/vcdrom

注:建立一个目录用来作挂接点(mount point)

  #mount -o loop -t iso9660 /home/sunky/mydisk.iso/mnt/vcdrom

 

二 光盘bicr介质的挂载流程(UsbDeviceManager.java)

2.1 光盘backfile的控制

sys.usb.mtk_bicr_support:这个值系统变量用来标识是否显示光盘内容,两个值yes,yes_hide.

这个值的初始化发生在UsbDeviceManager.java文件里

if(nativeInitUMSproperty())

     SystemProperties.set("sys.usb.mtk_bicr_support","yes");

 

static jbooleanandroid_server_UsbService_initUMSproperty(JNIEnv *env, jobjectthiz)

{

#ifdefMTK_BICR_SUPPORT

   return true;

#else

   return false;

#endif

}

 

是否支持光盘内容弹出通过MTK_BICR_SUPPORT宏来决定。光盘作为mass_storage的一个子类,只要在使能了mass_storage功能后,并且在mass_storage驱动中定义了cdrom的lun个数非0后,就会在pc上出现光驱。但是是否有文件系统还需要一个步骤。上面的sys.usb.mtk_bicr_support就是用来控制这个功能的开关。

该值为yes的话就会触发文件系统的挂载。

 

总体流程:

在UsbDeviceManager.java中showBuiltinInstallerUI,启用了BuiltinInstallerActivity。这个activity会弹出对话框询问用户是否需要光盘,其实是是否挂在光盘内容。

Mountservice.java中,shareCDRom---doshareunshareCDRom--mconnector.doCommand

进入nativedaemonconnector.java docommand--

经过jni进入到comandlistener.cpp该文件位于vold文件夹内,

执行CDROMCmd的runCommand函数,执行bicr.cpp的shareCdRom函数,

const char*Bicr::CD_ROM_PATH           = "/dev/block/loop0";

const char*Bicr::CD_ROM_LUN_PATH       ="/sys/class/android_usb/android0/f_mass_storage/lun-cdrom/file";

最后通过else if (write(fd, CD_ROM_PATH,strlen(CD_ROM_PATH)) < 0) {

完成了文件对应介质的操作。

2.2 光盘backfile的触发启动

PR:那么showBuiltinInstallerUI是什么时候启动的呢?挂载的介质在拔除usbcabel时有没有被清掉呢?防止下次在界面中虽然设置了hide,依然会显示光盘内容?所以应该是在拔除这个动作发生时清除才对。代验证。

第一种情况:系统启动完成时,但是要判断usb是否连接着,连接着才会考虑

       if(action.equals(Intent.ACTION_BOOT_COMPLETED)) {

              Slog.i(TAG, "BOOT_COMPLETED");

              Handler showBuiltinInstallerHandler = new Handler();

              showBuiltinInstallerHandler.postDelayed(mShowBuiltinInstallerRunnable,14000);

           }

       private Runnable mShowBuiltinInstallerRunnable = newRunnable()

       {

           @Override

           public void run()

           {

               Slog.i(TAG, "Delay show");

               showBuiltinInstallerUI(mConnected);

           }

       };

二 系统上电的时候

 

 else if(action.equals(IPO_POWER_ON)) {

                   SXlog.d(TAG, "onReceive - [IPO_POWER_ON] mDefaultFunctions: " +mDefaultFunctions + ", mSettingUsbCharging: " +mSettingUsbCharging);

                   if (mSettingUsbCharging) {

                       mSettingUsbCharging= false;

                       setCurrentFunction(mDefaultFunctions, false);

                   }

                   showBuiltinInstallerUI(mConnected);

 

三 收到更新消息,并且是发生了硬件重新插拔动作才进行处理,所以如果仅仅是软的连接不会发生这个动作

       public void handleMessage(Message msg) {

           switch (msg.what) {

               case MSG_UPDATE_STATE:

                   mConnected = (msg.arg1 == 1);

                   mConfigured = (msg.arg2 == 1);

                   updateUsbNotification();

                   updateAdbNotification();

                   if (containsFunction(mCurrentFunctions,

                           UsbManager.USB_FUNCTION_ACCESSORY)) {

                       updateCurrentAccessory();

                   }

                            //注意下面这个处理,当usb状态位connect(false),function会切换到默认的功能上,变成false有两种情况:1软断,这种断开后会紧跟着一个设置会进来,这种情况是为了设置新的,才会先断一下,所以要设置的会生效2、真断,这种就是硬件上断开、拔除了,下面这部分代码会将其设置到默认的function。(目前打算是在setting中设置功能,但是每次设置完后,等再次插入时,又会恢复到默认的状态,mHwDisconnected标识硬件上是否连接的状态)

                   if(!mConnected &&!mSettingUsbCharging) {

                       // restore defaults when USB is disconnected

                       SXlog.d(TAG, "handleMessage - MSG_UPDATE_STATE - mConnected: " +mConnected + ", mSettingUsbCharging: " +mSettingUsbCharging);

                       setEnabledFunctions(mDefaultFunctions, false);

                   }

                   if (mBootCompleted) {

                       updateUsbState();//将传过来的最新usb信息更新到UsbManager及其他全局变量中

 

                       Log.w(TAG, "handleMessage mConnected:" + mConnected +",mConfigured:" + mConfigured +

                                                                                         ", mHwDisconnected:" + mHwDisconnected + ", mHwReconnected:" +mHwReconnected);

 

                       if(mHwReconnected == true &&mConnected == true) {

                           showBuiltinInstallerUI(true);//只有当硬件重新连接过,才会重新挂载介质

                           mHwReconnected = false;

                       }

                   }

                   break;

          下面这个函数用来更新状态,发送消息,随后上面的handleMessage进行处理

       public void updateState(String state)

这个updateState的触发是有kernel层上来的,kernel层会发出uevent消息,所以上面需要接收、处理uevent消息。

如下:

   

    privatefinal UEventObserver mUEventObserver = new UEventObserver(){

       @Override

       public void onUEvent(UEventObserver.UEvent event) {

           if (DEBUG) Slog.v(TAG, "USB UEVENT: " +event.toString());

 

           String state = event.get("USB_STATE");

           String accessory = event.get("ACCESSORY");

 

//Added for USB Develpment debug, more log for more debuginghelp

           if(DEBUG) Log.w(TAG, "mUEventObserver: onUEvent: state = " +state);

//Added for USB Develpment debug, more log for more debuginghelp

 

           if (state != null) {

               mHandler.updateState(state);

           } else if ("START".equals(accessory)) {

               if (DEBUG) Slog.d(TAG, "got accessory start");

               setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY,false);

           }

       }

   };

下面看一下       mHandler = newUsbHandler(thread.getLooper());

   private final class UsbHandlerextends Handler {

这个UsbHandler是一个主要的usb处理类。

 

    publicvoid updateState(String state){

………………

           Message msg = Message.obtain(this, MSG_UPDATE_STATE);

           msg.arg1 = connected;

           msg.arg2 = configured;

           // debounce disconnects to avoid problems bringing up USBtethering

           if (mHwDisconnected ||mSettingUsbCharging){

               SXlog.d(TAG, "updateState - UPDATE_DELAY  " +state + " mSettingFunction: " + mSettingFunction);

               sendMessageDelayed(msg,(connected == 0) ? UPDATE_DELAY : 0);

           }

………………

在updateState函数中,通过传进来的state,重新调整了connected和 configured两个参数,并传递了消息。

然后回到了上面的第三种情况中的消息处理函数handleMessage

 

root@android:/sys/class/android_usb/android0 # catstate

CONFIGURED

在updateState函数中有4个state状态:

HWDISCONNECTED硬件上拔除了usb cabel

DISCONNECTED 这个应该是软拔除,现在理解是软件上的一种设置

CONNECTED 已经连接上了

CONFIGURED 已经配置完成

其中有一个重要变量mHwReconnected用来记录这次连接是否是硬件的再次连接,而不是软件设置上的重新连接。

2.3 光盘backfile的unshare

上面有一个疑问是,什么时候将光盘的文件系统介质拿掉的。如下,通过下面的receiver接收到usb的action:ACTION_USB_STATE,如果发生了拔除动作,则shareCDRom(false)卸载掉文件系统介质。

// This class is used to closeBuiltInstallerActivity and ims service unMount if it ismounted

public class BuiltinInstallerReceiver extendsBroadcastReceiver {

   private static final String TAG ="BuiltinInstallerReceiver";

   @Override

    publicvoid onReceive(Context context, Intent intent) {

       String action = intent.getAction();

       if (UsbManager.ACTION_USB_STATE.equals(action)) {

           boolean connected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);

           if (!connected && BuiltinInstallerActivity.getSharedStatus()){

               try {

                       IMountService ims = BuiltinInstallerActivity.getMountService();

                       if (ims == null) {

                          Log.e(TAG, "Cant get mount service");

                       }

                       ims.shareCDRom(false);

                       BuiltinInstallerActivity.setSharedStatus(false);

                       Log.i(TAG, "STOP sharing builtin installer");

                   } catch (RemoteException e) {

                       Log.e(TAG, "Cant call mount service");

                   }

           }

       }

   }

这个receiver在manifest.xml中定义,这种方式类似于下面这种注册的方式     

registerReceiver(mUsbStateReceiver, newIntentFilter(UsbManager.ACTION_USB_STATE)); 

这个receiver收到广播消息后,调用了BuiltinInstallerActivity这个类的static成员函数。而当时修改去掉对话框的方式时没有启动这个activity,导致其中的static成员状态没有被更新。导致再拔除usb时,这个reciever获取不到正确的信息,不能卸载介质。(当发生了拔除动作,并且当前处于share状态,才进行unshare的动作)。这也是我当时去掉对话框后,留下的隐患,查看/sys/class/android_usb/android0/f_mass_storage/lun-cdrom/file始终是/dev/block/loop0。

 这块对类的理解:BuiltinInstallerActivity类是一个特殊的对象,外界可以直接调用他的static成员,又可以实例化对象,被实例化的对象之间可以通过static通信,static有点像全局变量,类这个大家庭的全局变量。

 

PR:所以下面的问题就是消息的问题,当usb没有发生硬插拔时是广播的什么消息?可以确认的是即使广播的消息没有触发showBuiltinInstallerUI动作,也没有关系。因为由于上面BuiltinInstallerReceiver 的错误处理,一直都没有unshare光盘的介质,导致后期一直都处于share状态。也就是说直接有是否使能mass_storage这个功能来决定是否弹出光盘(本来应该是两个决定因素:1 使能mass_storage 功能,2 share 介质)。

2.4 设置usbfunction的动作

PR:2012-07-04添加了复选框用来使能光盘ornot。主要是通过addFunction和removeFunction两个动作来处理usb的function的。但是当使能光盘时,sys.usb.config变为mtp,adb,mass_storage不在init.usb.rc中,所以这个时候就会setUsbConfig失败,转而重新设置为刚才的(mtp,adb).

所以复选框的功能是否应该更改为:1 setCurrentFunction(“mass_storage”).2 setCurrentFunction(“mtp,adb”).其中2还要看是否使能了debug,如果没有的话还得去掉。

所以这个部分现在只是行为方式上的定义,以及编译时对persist.sys.usb.config的控制(去掉mass_storage).

 

对于在调用 setCurrentFunction后的动作中,有很多猫腻。setCurrentFunction发送消息,随后在处理函数中调用setEnabledFunctions完成整个设置过程,但这个setEnabledFunctions有对usbfunction的各种各样的变化。下面看看setEnabledFunctions的处理思路:

setEnabledFunctions(String functions, booleanmakeDefault) {

mDefaultFunctions:代表系统默认的function,persist.sys.usb.config

mCurrentFunctions:代表系统当前的usbfunction

mSettingFunction代表当前要设置的function

functions:参数传入时代表当前要设置的function,但是这个值会在这个函数内部根据系统的功能发生变化,如当定义了cdrom,它会默认加入mass_storage功能等,所以最后设置的functions将有可能不是最初传入的function,最初传入的function一直保存在mSettingFunction中。

根据是否override persist.sys.usb.config进行了分支,persist.sys.usb.config考虑是否被修改为makeDefault。

 

 else{

               if (functions == null) {

                   functions = mDefaultFunctions;//如果传入参数为空,使用persist.sys.usb.config

               }

 

               // Override with bootmode specific usb mode if needed

               functions = processOemUsbOverride(functions);//留给oem一个插一杠子的机会

                   mSettingFunction = functions;

                                   //如果要启用MTPfunction,并且系统还定义了光驱功能,那么就需要在加入一个mass_storagefunction,有点强奸民意的意思。在驱动中使能了光盘,上层应用就一定要用么?会什么和MTP还有关系呢?难道是,系统默认的存储一个是UMS一个是MTP,两个功能必用一个。如果定义了MTP,又定一个了光盘,那就说明要加入mass_storage,如果没定义MTP,那系统一定定义了mass_storage功能,所以不用再加入,什么狗屁逻辑!都是自我揣测。

               if (mUmsAlwaysEnabled &&containsFunction(mSettingFunction, UsbManager.USB_FUNCTION_MTP)){

                   functions = addFunction(functions,UsbManager.USB_FUNCTION_MASS_STORAGE);

               }

//mSettingUsbCharging:UsbManager.USB_FUNCTION_CHARGING_ONLY代表usb只用来充电,这块的意思是如果在非只充电的情况下,用户的function设置,必须遵循系统的一些特性,尊重系统的adb功能,用户的设置会被改动

               if (mAdbEnabled &&!mSettingUsbCharging) {

                   functions = addFunction(functions,UsbManager.USB_FUNCTION_ADB);

               } else {

                   functions = removeFunction(functions,UsbManager.USB_FUNCTION_ADB);

               }

//acm和adb类似,注意这几个系统级别的function的顺序

               if (mAcmEnabled &&!mSettingUsbCharging) {

                   functions = addFunction(functions,UsbManager.USB_FUNCTION_ACM);

               } else {

                   functions = removeFunction(functions,UsbManager.USB_FUNCTION_ACM);

               }

               if (!mCurrentFunctions.equals(functions)) {//看看是否需要设置,和当前功能没变化就不用设置了

                   if (!setUsbConfig("none")) {

                                              //先把功能设置成none,相当于软断开,如果失败,则切换到当前的function上

                       Slog.e(TAG, "Failed to disable USB");

                       // revert to previous configuration if we fail

                       setUsbConfig(mCurrentFunctions);

                       return;

                   }

                                              //切换到当前需要的功能上,如果切换失败,在切换回刚才的功能上

                   if(setUsbConfig(functions)) {

                       mCurrentFunctions = functions;

                   } else {

                       Slog.e(TAG, "Failed to switch USB config to " +functions);

                       // revert to previous configuration if we fail

                       setUsbConfig(mCurrentFunctions);

                   }

               }

           }

       }

 

 

 

 

三 控制显示光盘内容的两种方式

3.1 切换usbmass_storage功能

      在每次功能切换时,如果不需要光盘了,直接通过设置sys.usb.config去掉mass_storage,但是这种情况下u盘功能也不能用了。当不需要u盘功能时,这种方式还是可以的。

 

    private voidhandleToggleTurnonCdRomPreferenceClick(){

 

       UsbManager usbManager =(UsbManager)getSystemService(Context.USB_SERVICE);

       String mCurrentFunction =SystemProperties.get("sys.usb.config","none");

       if (mTurnOnCdRomPreference.isChecked() == true){

           SystemProperties.set("sys.usb.mtk_bicr_support","yes");

                           //直接将功能设置成mass_storage功能,如果希望光盘中的介质出来,需要处理,因为光盘介质的share只发生在硬插拔时。

           mCurrentFunction = UsbManager.USB_FUNCTION_MASS_STORAGE;

           usbManager.setCurrentFunction(mCurrentFunction,false);

           Log.w(TAG, "MENGFANODNG mCurrentFunction, functions: " +mCurrentFunction);

           Log.w(TAG, "trun on cdrom");

       }else {

                           如果不显示光盘内容,按理不应该切换当前的功能,只是unshare掉

           SystemProperties.set("sys.usb.mtk_bicr_support","yes_hide");

                           //不合理,需根据需求调整,如turnOffMountBicr

           mCurrentFunction = UsbManager.USB_FUNCTION_MTP;

           usbManager.setCurrentFunction(mCurrentFunction, false);

           Log.w(TAG, "MENGFANODNG mCurrentFunction, functions: " +mCurrentFunction);

           Log.w(TAG, "hide cdrom");

       }

   }

 

 

3.2 通过设置backfile来完成

      光盘一直在,但是没有了内容。

1)添加资源文件

将控制开关放在setting----accessibility中,名称为Install usb driver

packages/apps/Settings/res/values$ vi strings.xml

   <!-- Title for accessibility preference to installusb driver. [CHAR LIMIT=35] -->

       <stringname="accessibility_turnon_cdrom_title">Install usbdriver</string>

 

2) 修改布局文件

packages/apps/Settings/res/xml$vi accessibility_settings.xml

在布局中添加一个复选框

       <CheckBoxPreference

               android:key="turnon_cdrom"

               android:title="@string/accessibility_turnon_cdrom_title"

               android:persistent="false"

               android:order="9"/>

3) 添加代码

        

增加导入包

importandroid.os.storage.IMountService;

importandroid.os.IBinder;

importandroid.os.ServiceManager;

 

增加变量定义

   private final String TURNON_CDROM = "turnon_cdrom";

   private CheckBoxPreference mTurnOnCdRomPreference;

 

增加操作代码

初始化中加入

private voidinitializeAllPreferences() {

                  ………………

       //turn on cdrom

       mTurnOnCdRomPreference = (CheckBoxPreference)findPreference(TURNON_CDROM);

mTurnOnCdRomPreference用来记录当前复选框的状态,TURNON_CDROM对应的是复选框的键值。

 

点击处理动作

public booleanonPreferenceTreeClick(PreferenceScreen preferenceScreen, Preferencepreference) {

                  ………………

                  else if (mTurnOnCdRomPreference == preference) {//如果点击的是TURNON_CDROM

               handleToggleTurnonCdRomPreferenceClick();

               returntrue;

          }

 

 

加入实际的处理动作

   //add start by mengfandong 0620 for donot show the cdrom confirmdialog

   public  IMountService getMountService(){

       IBinder service = ServiceManager.getService("mount");

       if (service != null) {

           return IMountService.Stub.asInterface(service);

       }

       return null;

   }

 

   private void turnOnMountBicr(){

                  try {

                       IMountService ims = getMountService();

                       if (ims == null)

                       {

                           Log.e(TAG, "Cant get mount service");

                       }

                       ims.shareCDRom(true);

                       Log.i(TAG, "Share builtin installer");

                   }catch (Exception e) {

                       Log.e(TAG, "Cant call mount service");

                   }

   }

 

   private void turnOffMountBicr(){

                  try {

                       IMountService ims = getMountService();

                       if (ims == null)

                       {

                           Log.e(TAG,"Cant get mount service");

                       }

                       ims.shareCDRom(false);

                       Log.i(TAG, "do not Share builtin installer");

                   }catch (Exception e) {

                       Log.e(TAG, "Cant call mount service");

                   }

   }

 

这个地方就是假设usb 功能包含了mass_storage,并且sys.usb.mtk_bicr_support为yes

   private void handleToggleTurnonCdRomPreferenceClick(){

 

       if (mTurnOnCdRomPreference.isChecked() == true){

               Log.w(TAG,"trun on cdrom");

               turnOnMountBicr();

       }else {

               turnOffMountBicr();

               Log.w(TAG, "hide cdrom");

       }

   }

   //add end by mengfandong

4)去掉UsbDeviceManger.java中对光盘的处理,防止插入usbcabel时,光盘弹出

你可能感兴趣的:(android下usb框架系列文章---(4)android下的光盘功能控制)