一 使能光盘功能

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

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.javadocommand--

经过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时,光盘弹出

更多相关文章

  1. Android开发:Android虚拟机启动错误Can't find 'Linux version '
  2. Android(安卓)ViewPager分页功能
  3. 使用android隐藏api实现亮度调节的方法
  4. Android(安卓)获取manifest.xml中meta-data值遇到的问题
  5. android通过servlet上传文件到服务器
  6. Android中写文本文件的方法
  7. avd 配置
  8. 使用NDK编译CMU Sphinx
  9. Android输入法切换引导功能

随机推荐

  1. android中translate动画
  2. Android如何在service中弹出对话框
  3. Android(安卓)Application Task Activiti
  4. Android中LinearLayout布局的常用属性总
  5. ArcGIS for Android地图控件的5大常见操
  6. Android 监听home键(android:launchMode="
  7. 下载android sdk, adt
  8. 【Android-002】【常见布局】
  9. Android Edittext焦点处理;
  10. Android超链接去下划线--Android学习笔记