UMSturnon的过程 turnon

UMSturn on 的过程

下面从framework层的ui来看一下插入usb后share的过程,这个动作的触发是从status bar下面弹出的usb connect开始的。

frameworks/base/packages/SystemUI

通过一系列反跟踪,这个packages是系统级别的,用来展示系统的UI,当插入usb线时,会在下方的status bar上会显示usb连接图标。

USBconnected

Select to copy files to/from your computer

点击这个项后会谈出 turnon USB storage

资源所在路径:

base/core/res/res/values/strings.xml

<!-- USB_STORAGE: When theuser connects the phone to a computer via USB, we show anotification asking if he wants to share files across. This is thetitle -->

<string name="usb_storage_notification_title">USBconnected</string>

<!-- See USB_STORAGE. Thisis the message. -->

<string name="usb_storage_notification_message">Selectto copy files to/from yourcomputer.</string>

这两个变量是在

/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java里边被使用

void updateUsbMassStorageNotification(booleanavailable) {

if(available) {

SXlog.d(TAG,"updateUsbMassStorageNotification - [true]");

Intent intent = new Intent();

intent.setClass(mContext,com.android.systemui.usb.UsbStorageActivity.class);//启用了这个activity

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

PendingIntent pi =PendingIntent.getActivity(mContext, 0, intent, 0);

setUsbStorageNotification(//在下面的status bar中显示usbconnect

com.android.internal.R.string.usb_storage_notification_title,

com.android.internal.R.string.usb_storage_notification_message,

com.android.internal.R.drawable.stat_sys_data_usb,

false, true, pi);

}else {

SXlog.d(TAG,"updateUsbMassStorageNotification - [false]");

setUsbStorageNotification(0, 0, 0, false,false, null);

}

}

下面将通过 updateUsbMassStorageNotification这个函数将插入前后的动作捋顺

一 注册StorageManager存储设备状态变更监听器StorageNotification

Storagenotification这个activity是怎么被启动的呢?从而触发了usbconnect changed的函数动作?

是通过下面的监听器注册来完成的。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarPolicy.java

//storage

mStorageManager = (StorageManager)context.getSystemService(Context.STORAGE_SERVICE);

mStorageManager.registerListener(

newcom.android.systemui.usb.StorageNotification(context));

这个将StorageNotification注册到mStorageManager的listener中,没有理解listener的机制。但是猜测应该是当listenser到某个消息时会启动这个注册的activity。

注册StorageManager的存储设备状态变更监听器来实现的。

StorageNotification

frameworks/base/packages/SystemUI/src/com/android/systemui/usb$

在storageNotification这个类的构造函数中,直接调用了下面这个usb连接状态的处理函数,onUsbMassStorageConnectionChanged(connected);通过和上面的联系起来就是,当监听器监听到变化后,开始启动这个activity,构造函数开始执行,执行一系列动作,包括对usb状态的处理,以及后面将会遇到的storage状态的处理。

2.1构造函数:

public StorageNotification(Context context) {

mContext = context;

mStorageManager = (StorageManager)context.getSystemService(Context.STORAGE_SERVICE);

finalboolean connected =mStorageManager.isUsbMassStorageConnected();

Slog.d(TAG, String.format( "Startup with UMS connection %s(media state %s)", mUmsAvailable,

Environment.getExternalStorageState()));

HandlerThread thr = new HandlerThread("SystemUIStorageNotification");

thr.start();

mAsyncEventHandler = newHandler(thr.getLooper());

mUsbNotifications = new HashSet();

mLastState = Environment.MEDIA_MOUNTED;

mLastConnected = false;

onUsbMassStorageConnectionChanged(connected);

……………………

StorageVolume[] volumes =mStorageManager.getVolumeList();

for(int i=0; i<volumes.length; i++) {

String sharePath = volumes[i].getPath();

String shareState =mStorageManager.getVolumeState(sharePath);

Slog.d(TAG, "onStorageStateChanged - sharePath: " + sharePath +" shareState: " + shareState);

if(shareState.equals(Environment.MEDIA_UNMOUNTABLE)){

onStorageStateChanged(sharePath,shareState, shareState);

}

}

2.2 onUsbMassStorageConnectionChanged

@Override

public void onUsbMassStorageConnectionChanged(finalboolean connected) {

mAsyncEventHandler.post(new Runnable() {

@Override

public void run() {

onUsbMassStorageConnectionChangedAsync(connected);

}

});

}

2.3 onUsbMassStorageConnectionChangedAsync

private voidonUsbMassStorageConnectionChangedAsync(boolean connected){

mUmsAvailable =connected;//相当于插上usbums就是使能的

另外这个函数中代码明确表示ums的优先级高于mtp。

这个函数中的主要工作是调用updateUsbMassStorageNotification来更新status bar,但是采用什么机制来决定是否调用这个函数进行更新,是会根据mtp/ums功能来选择的,不同的产品应该会有不同的机制。

2.4updateUsbMassStorageNotification

voidupdateUsbMassStorageNotification(booleanavailable) {

if(available) {

SXlog.d(TAG, "updateUsbMassStorageNotification -[true]");

Intent intent = new Intent();

intent.setClass(mContext, com.android.systemui.usb.UsbStorageActivity.class);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

PendingIntent pi = PendingIntent.getActivity(mContext, 0,intent, 0);

setUsbStorageNotification(

com.android.internal.R.string.usb_storage_notification_title,

com.android.internal.R.string.usb_storage_notification_message,

com.android.internal.R.drawable.stat_sys_data_usb,

false, true, pi);

}else {

SXlog.d(TAG, "updateUsbMassStorageNotification -[false]");

setUsbStorageNotification(0, 0, 0, false, false,null);

}

}

这个函数上面提到过,就是用来决定是否显示usbconnect status bar的。通过调用setUsbStorageNotification显示出了usbconnect相关的文字信息,同时通过intent启动了com.android.systemui.usb.UsbStorageActivity.class

2.5setUsbStorageNotification

private synchronized void setUsbStorageNotification(int titleId,int messageId, int icon,

boolean sound, boolean visible, PendingIntent pi){

这个函数在最后游侠面的动作,应该是一个通知消息。

if(visible) {

notificationManager.notify(notificationId,mUsbStorageNotification);

}else {

notificationManager.cancel(notificationId);

}

从使用上来看,用户点击这个usbconnect后,会弹出一个界面,提示用户是否打开usb massstorage。这个函数中有一个机关,就是当adb没有打开时,这个界面会默认打开,不需要用户点击usbconnect。

从这个函数的代码及实验现象来看,是这样设计的,如果没有启用adb,将直接弹出让用户使能ums的全屏,如果使能了adb,不会自动弹出来,需要用户自己去展开statusbar.

注意adb这部分的判断信息:

final boolean adbOn = 1 ==Settings.Secure.getInt(

mContext.getContentResolver(),

Settings.Secure.ADB_ENABLED,

0);

注意这块获取的是黄色部分的信息。

下面是UsbDeviceManager.java中的部分

//make sure the ADB_ENABLED setting value matches the currentstate

Settings.Secure.putInt(mContentResolver,Settings.Secure.ADB_ENABLED, mAdbEnabled ? 1 :0);

这个代码是在启动启动systemReady中的,就是说当用户设置的默认function中有adb功能时,将信息更新到Setting.Secure.ADB_ENABLED中,以便setting中同步。如果用户在应用中直接使用setprop的话,setting中是得不到更新的。

下面是提示用户打开ums的资源信息:

再看一下那个全屏显示的窗口的信息:

frameworks/base/core/res/res/values/strings.xml

<stringname="usb_storage_button_mount">Turn on USBstorage</string>

<stringname="usb_storage_message" product="default">Youhave connected to your computer via USB. Touch the button below ifyou want to copy files between your computer and yourAndroidu2018s SDcard.</string>

frameworks/base/core/res/res/layout/usb_storage_activity.xml

android:text="@string/usb_storage_button_mount"

所以整个的用户交互的UI信息都在SystremUI这个 系统app里边。

查看了以前总结的一个vold的流程框架,看来和usb关系不大,对于usb gadget来说,pc端是数据的发起者,usb端对应的存储只涉及到kernel,和vold中的部分代码(挂载成功后,但这部分早就完成了),只是将挂载点,指向back-file storage。

一直想跟踪turn on usb storage这个按钮来查询具体的动作,有一个向上广播sd卡卸载的intent,android.intent.action.MEDA_EJECT,这是为了防止PC和上层应用同时操作介质。

但是启动back-file storage功能在哪里完成的呢?

查看/sys/class/android_usb/f_mass_storage/lun/file为/dev/block/vold/179:4

原来挂载在mnt/sdcard下的sd卡已经没有了,从log流程上分析来看应该是被umount了,然后将这个sd卡对应的设备节点,指向back-file storage.

卸载的动作从mountservice发下来后,最后的动作还是在vold完成的。

在storage_common.c文件中,有对sys系统下的写入操作的处理接口:fsg_store_file函数用来处理当用户空间向内核操作,向/sys/class/android_usb/f_mass_storage/lun/file写入介质的处理,随后打开fsg_lun_open进行gadget层的处理。

还是回到老问题上,应用层什么时候向sys文件系统写入的。

2.6UsbStorageActivity.java

packages/SystemUI/src/com/android/systemui/usb

当点击turn on usb storage时,logcat中,跟踪到UsbStorageActivity:oncreatedialoge,这个tag在usbstorageactivity.java中发现

UsbStorageActivity这个activity在updateUsbMassStorageNotification已经做好准备了,等待用户turnon后立即启动。

public Dialog onCreateDialog(int id, Bundle args){

Log.i(TAG, "onCreateDialoge");

switch (id) {

caseDLG_CONFIRM_KILL_STORAGE_USERS:

return new AlertDialog.Builder(this)

.setTitle(R.string.dlg_confirm_kill_storage_users_title)

.setPositiveButton(R.string.dlg_ok, newDialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which){

mHasCheck = false;

switchUsbMassStorage(true);

}})

通过点击确认后回弹出一个alertdialog,确认就是这个流程。资源信息在下面。当点击确定按钮后将执行switchUsbMassStorage。

<!--USB_STORAGE_KILL_STORAGE_USERS dialog -->

<string name="dlg_confirm_kill_storage_users_title">Turnon USB storage</string>

<!--USB_STORAGE_KILL_STORAGE_USERS dialog message text-->

<stringname="dlg_confirm_kill_storage_users_text">If youturn on USB storage, some applications you are using will stop andmay be unavailable until you turn off USBstorage.</string>

onClick----checkStorageUsers---checkStorageUsersAsync

scheduleShowDialog

2.7switchUsbMassStorage

private void switchUsbMassStorage(final boolean on) {

// thingsto do on the UI thread

mUIHandler.post(new Runnable() {

@Override

publicvoid run() {

mUnmountButton.setVisibility(View.GONE);

mMountButton.setVisibility(View.GONE);

mProgressBar.setVisibility(View.VISIBLE);

// will behidden once USB mass storage kicks in (or fails)

}

});

// thingsto do elsewhere

mAsyncStorageHandler.post(new Runnable() {

@Override

publicvoid run() {

if (on){

mSettingUMS = true;

mStorageManager.enableUsbMassStorage();

} else{

mSettingUMS = false;

mStorageManager.disableUsbMassStorage();

}

}

});

}

2.9StorageManager.java

frameworks/base/core/java/android/os/storage/StorageManager.java

mStorageManager = (StorageManager)getSystemService(Context.STORAGE_SERVICE);

public void enableUsbMassStorage() {

try{

mMountService.setUsbMassStorageEnabled(true);

} catch(Exception ex) {

Log.e(TAG,"Failed to enable UMS", ex);

}

}

mMountService.setUsbMassStorageEnabled(true)(ImountService.java)

mMountService =IMountService.Stub.asInterface(ServiceManager.getService("mount"));

下面没有跟踪下去,猜想应该会在vold里边完成,但是怎么传达下去的呢?在mountservice.java中也有setUsbMassStorageEnabled函数,这个是services目录下面的。这个函数里边是我们要找的。

2.10 mountservice.java

/framework/base/services/java/com/android/server/mountservice.java

public void setUsbMassStorageEnabled(booleanenable) {

………………

}else if (enable &&state.equals(Environment.MEDIA_UNMOUNTED)) {

doShareUnshareVolume(path, method,enable);

}

将所有的volume都进行处理,方法为”ums”。

2.11 Doshareunsharevolume

private void doShareUnshareVolume(String path,String method, boolean enable) {

//TODO: Add support for multiple share methods

if(!method.equals("ums")) {

thrownew IllegalArgumentException(String.format("Method %s notsupported", method));

}

try{

mConnector.doCommand(String.format(

"volume %sshare %s %s", (enable ? "" : "un"), path,method));

}catch (NativeDaemonConnectorException e) {

Slog.e(TAG, "Failed to share/unshare", e);

}

}

上面红色的就是传达下去的命令及参数

2.12comandlistener.cpp

system/vold/comandlistener.cpp

----mconnector.docommand,命令应该对应volume,不同的是对应的命令为volume命令集。

mconnector.doCommand进入nativedaemonconnector.javadocommand--

经过jni进入到comandlistener.cpp该文件位于system/vold文件夹内,有各种命令的监听处理,cdrom、volume、storage等。

}else if (!strcmp(argv[1], "share")) {

if(argc != 4) {

cli->sendMsg(ResponseCode::CommandSyntaxError,

"Usage: volume share <path><method>", false);

return 0;

}

rc =vm->shareVolume(argv[2],argv[3]);

2.13VolumeManager.cpp

#define MASS_STORAGE_FILE_PATH"/sys/class/android_usb/android0/f_mass_storage/lun/file"

#define MASS_STORAGE_EXTERNAL_FILE_PATH"/sys/class/android_usb/android0/f_mass_storage/lun1/file"

intVolumeManager::shareVolume(const char *label, constchar *method) {

分别对内置和外置sd卡都作了处理,看来只支持2个。

if(primaryStorage) {

if((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0){

SLOGE("Unable to open ums lunfile (%s)",strerror(errno));

return -1;

}

}

else

{

if((fd = open(MASS_STORAGE_EXTERNAL_FILE_PATH, O_WRONLY))< 0) {

SLOGE("Unable to open ums lunfile (%s)",strerror(errno));

return -1;

}

}

if(write(fd, nodepath, strlen(nodepath)) < 0){

SLOGE("Unable to write to ums lunfile (%s)",strerror(errno));

close(fd);

return -1;

}

到此完成了back-file的对应。

base/core/java/android/os/storage/StorageManager.java

base/services/java/com/android/server/mountservice.java

framework是android向应用程序开发提供的一个框架,简单理解为API.她创建了一系列的class对象,通过这些对象的接口行为,来操作各种组件功能。Framework根据产品的功能及用户的行为抽象出了各种组件,应用程序开发可以直接调用。那么framework的设计也是有一个框架的,是一个独立的层。麻雀虽小,五脏俱全。

frameworks/base 这个目录下是framework的基本代码,基本代码中的core目录,顾名思义应该是框架的核心骨架代码。这个骨架的实现是需要java和cpp的,其间通过jni来实现调用。其中services目录是为framework中功能提供后台服务用的,上层应用是调用不到的。

中间涉及到了一些adb的东西,有助于上面的理解:

adb 功能的配置点:

工程版默认是有adb这个功能的,这个main.mk中没有看到,是在哪里配置的?
==> 把 enable_target_debugging := true
alpsbuildcoremain.mk
# Disable debugging in plainuser builds.
enable_target_debugging :=

ifeq (true,$(strip$(enable_target_debugging)))

#Target is more debuggable and adbd is on by default

ADDITIONAL_DEFAULT_PROPERTIES +=ro.debuggable=1

#Include the debugging/testing OTA keys in this build.

INCLUDE_TEST_OTA_KEYS := true

else # !enable_target_debugging

#Target is less debuggable and adbd is off by default

ADDITIONAL_DEFAULT_PROPERTIES +=ro.debuggable=0

endif # !enable_target_debugging

build/tools/post_process_props.py

ifprop.get("ro.debuggable") == "1":

val = prop.get("persist.sys.usb.config")

ifval == "":

val = "adb"

else:

val = val + ",adb"

走设置---开发人员选项途径:

当用户选择“Settings”->"Applictions"->"devleopment"->"USBDebugging"时

inpackages/apps/Settings/src/com/android/settings/DevelopmentSettings.java

public void onClick(DialogInterface dialog, intwhich) {

if (which == DialogInterface.BUTTON_POSITIVE){

mOkClicked = true;

Settings.Secure.putInt(getActivity().getContentResolver(),

Settings.Secure.ADB_ENABLED, 1);

} else {

// Reset the toggle

mEnableAdb.setChecked(false);

}

}


在usbDeviceManager.java中有对上面动作的observer.

private class AdbSettingsObserver extends ContentObserver{

public AdbSettingsObserver() {

super(null);

}

@Override

public void onChange(boolean selfChange){

boolean enable =(Settings.Secure.getInt(mContentResolver,

Settings.Secure.ADB_ENABLED, 0) >0);

mHandler.sendMessage(MSG_ENABLE_ADB,enable);

}

}


// register observer to listen for settingschanges

mContentResolver.registerContentObserver(

Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),

false, new AdbSettingsObserver());

当接收到消息后,会调用setAdbEnabled来更新mAdbEnabled这个变量,这个变量是在setEnabledFunctions会用到。

所以说底层usbDeviceManager.java在处理adb这个功能时,是看mAdbEnabled这个变量,而这个变量的设置,初始时是看defaultFunction中是否有adb,后期的更新就是通过setting中的设置,两者是需要同步的。

//make sure the ADB_ENABLED setting value matches the currentstate

Settings.Secure.putInt(mContentResolver,Settings.Secure.ADB_ENABLED, mAdbEnabled ? 1 :0);

这个代码是在启动systemReady中的,就是说当用户设置的默认function中有adb功能时,将信息更新到Setting.Secure.ADB_ENABLED中,以便setting中同步。如果用户在应用中直接使用setprop的话,setting中是得不到更新的。在setting的resume中会获取intent中 Settings.Secure.ADB_ENABLED的值来显示check状态。



问题分析试验记录:

1 使用当年的ums功能的,使能mass_storage,adb,acm时,ums可以使用 ,android_usb/f_mass_storage下面有相应的设备backfile

2 当使用mtp时,也是没有看到相应的设备文件。这个bin文件是比较早的,刚刚去掉cdrom的confirm dialog的。去掉对话框还是有bug的版本。当插入usb cabel时,下方还显示usb connect。这种情况下mtp进入后看不到盘符。(usb connect后市不是做了什么)

设置setprop sys.usb.configmass_storage,adb,acm后,虽然可以切换成功,但是点击turn on时,不会弹出alert对话框,并且backfile share不成功。

找到一部分原因:没有定义MTK_MASS_STORAGE=yes时,在android.c中是不会创建节点的。mass_storage_function_init验证中。一直出现adboffline。并且usbconnect又出现了。Ums和mtp共用的情况下会出现adb offline?


考虑到以前在mtp+cdrom的情况下是去掉usb connect显示的,没有adb也不要弹出usb mass_storage turn on提示框的。但是这种情形下都出来了(MTK_MASS_STORAGE= yes)。

SetUsbStorageNotification在onStorageStateChangedAsync也被调用过。不过这个是判断状态为shared的情况,share成功后显示Turnoff USB storage。


private void onStorageStateChangedAsync(String path,String oldState, String newState) {

Slog.i(TAG, String.format(

"Media {%s} state changed from {%s} ->{%s}", path, oldState, newState));


mLastState = newState;


if (newState.equals(Environment.MEDIA_SHARED)){

SXlog.d(TAG, "onStorageStateChangedAsync -[MEDIA_SHARED]");

Intent intent = new Intent();

intent.setClass(mContext,com.android.systemui.usb.UsbStorageActivity.class);

PendingIntent pi = PendingIntent.getActivity(mContext, 0,intent, 0);

setUsbStorageNotification(

com.android.internal.R.string.usb_storage_stop_notification_title,

com.android.internal.R.string.usb_storage_stop_notification_message,

com.android.internal.R.drawable.stat_sys_warning, false,true, pi);


if("/mnt/sdcard".equals(path)) {

mUsbNotifications.clear();

}

}

到底是从哪里触发的呢?

Bar中显示也变为”Connected as USB Storage”

./res/values/strings.xml:2859: <stringname="usb_ums_notification_title">Connected as USBStorage</string>

./res/values/strings.xml:2855: <stringname="usb_mtp_notification_title">Connected as amediadevice</string>

./res/values/strings.xml:2863: <stringname="usb_cd_installer_notification_title">Connectedas aninstaller</string>

这个更新是在UsbDeviceManager.java里边完成的。

private void updateUsbNotification() {

  

爱华网本文地址 » http://www.413yy.cn/a/25101010/21190.html

更多阅读

公猫绝育手术的过程 猫为什么有九条命

公猫绝育手术的过程——简介宠物医院在为公猫做绝育手术的时候是怎么样的一个过程中,下面我们不妨一起来了解一下吧。公猫绝育手术的过程——方法/步骤公猫绝育手术的过程 1、首先,宠物医院会告诉您,在24小时内断粮断水,至于为什么。是

补牙齿的过程 根管治疗哪个环节最疼

补牙在口腔专业中称作充填术。是终止龋齿、修复牙外形使之恢复功能的主要方法,那么要进行补牙,补牙的过程怎样,则是众多牙科患者较为关心的,今天我们就补牙的过程来进行详细的了解。补牙齿的过程——工具/原料补牙材料:银汞充填、进口树

国画颜料绘制夹竹桃的过程 国画颜料品牌

国画颜料绘制夹竹桃的过程——简介国画颜料的色泽比较沉着,在这里我用了三种色,分别是素白色,绯红色和墨色。起线用的是自动铅笔。勾线用的是小狼毫。国画颜料绘制夹竹桃的过程——工具/原料国画颜料,墨汁自动

龋齿--补牙的过程 龋齿补牙后注意事项

  我们如果有了蛀牙就要及时去口腔医院进行补牙,治疗后的蛀牙可以阻止龋病病变的进展,及早恢复牙齿的功能及美观,保持牙列的完整,避免我们的牙齿过早的坏死脱落。 龋齿的表现图 龋齿的细解图龋齿--补牙的过程——工具/原料

声明:《UMSturnon的过程 turnon》为网友雨辰分享!如侵犯到您的合法权益请联系我们删除