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

frameworks/base/packages/SystemUI

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

USB connected

Select to copy files to/from your computer

点击这个项后会谈出 turn on USB storage

资源所在路径:

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

<!-- USB_STORAGE: When the user connects the phoneto a computer via USB, we show a notification asking if he wants toshare files across.  This is the title-->

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

<!-- See USB_STORAGE. This is 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里边被使用

StorageNotification.java

主要用来处理存储设备相关动作的状态更新、通知。主要涉及两个方面:一是插入usb cabel后的状态栏更新,主要针对ums功能。二是storage状态发生改变时,会调用这个activity,如mount、unmount等。

所以入口主要有两个:onUsbMassStorageConnectionChanged和onStorageStateChanged分别处理usb连接状态的改变和storage状态的改变。

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

Storagenotification这个activity是怎么被启动的呢?从而触发了usb connect 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的存储设备状态变更监听器来实现的。

二 针对usb线连接动作的通知

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

2.1 构造函数:

public StorageNotification(Context context) {

mContext = context;

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

final boolean connected =mStorageManager.isUsbMassStorageConnected();

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

Environment.getExternalStorageState()));

HandlerThread thr = new HandlerThread("SystemUIStorageNotification");

thr.start();

mAsyncEventHandler = new Handler(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 void onUsbMassStorageConnectionChangedAsync(booleanconnected) {

mUmsAvailable = connected;//插上usb ums就使能了,不合适啊,还得根据是否有mass_storage功能

另外这个函数中代码明确表示ums的优先级高于mtp。如果包含mass_storage功能,就发出status bar通知。

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

这个status bar的更新机制,很容易被误触,有时并不需要ums功能,但是需要光盘功能,却被误打开。尤其是mtp+cdrom的状态。

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);

//准备出等待要执行的activity,pi

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

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

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);

}

}

2.4 setUsbStorageNotification

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

boolean sound, boolean visible,PendingIntent pi) {

组装mUsbStorageNotification变量,最后通过notificationManager发出。

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

if (visible) {

notificationManager.notify(notificationId,mUsbStorageNotification);

} else {

notificationManager.cancel(notificationId);

}

在通过 notificationManager将mUsbStorageNotification发出时,会在status bar上出现提示条:usb connect,用户点击这个usb connect后,会弹出一个界面,提示用户是否打开usb mass storage。另外mUsbStorageNotification有一个重要的pendingintent参数,用来提示是否直接执行这个activity。

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

注意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中是得不到更新的。

所以 UsbStorageActivity的启动有两种方式,直接启动或者通过点击usb connect启动。

点击usbconect这个动作,没有找到代码,猜测应该是在notificationManager里边处理了,因为包括要启动的activity都在参数里边了。

2.5 UsbStorageActivity.java

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

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

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

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

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

<string name="usb_storage_message"product="default">You have connected to yourcomputer via USB. Touch the button below if you want to copy filesbetween your computer and your Android\u2018s SDcard.</string>

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

android:text="@string/usb_storage_button_mount"

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

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

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

public Dialog onCreateDialog(int id, Bundle args){

Log.i(TAG, "onCreateDialoge");

switch (id) {

case DLG_CONFIRM_KILL_STORAGE_USERS:

return new AlertDialog.Builder(this)

.setTitle(R.string.dlg_confirm_kill_storage_users_title)

.setPositiveButton(R.string.dlg_ok,new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {

mHasCheck = false;

switchUsbMassStorage(true);

}})

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

<!-- USB_STORAGE_KILL_STORAGE_USERSdialog  -->

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

<!-- USB_STORAGE_KILL_STORAGE_USERS dialog messagetext -->

<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.6 switchUsbMassStorage

private void switchUsbMassStorage(final boolean on) {

// things to do on the UI thread

mUIHandler.post(new Runnable() {

@Override

public void run() {

mUnmountButton.setVisibility(View.GONE);

mMountButton.setVisibility(View.GONE);

mProgressBar.setVisibility(View.VISIBLE);

// will be hidden once USB mass storage kicks in (orfails)

}

});

// things to do elsewhere

mAsyncStorageHandler.post(new Runnable() {

@Override

public void run() {

if (on) {

mSettingUMS = true;

mStorageManager.enableUsbMassStorage();

} else {

mSettingUMS = false;

mStorageManager.disableUsbMassStorage();

}

}

});

}

2.7 StorageManager.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.8 mountservice.java

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

public void setUsbMassStorageEnabled(boolean enable){

………………

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

doShareUnshareVolume(path, method,enable);

}

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

2.9 Doshareunsharevolume

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

// TODO: Add support for multiple share methods

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

throw new 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.10 comandlistener.cpp

system/vold/comandlistener.cpp

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

mconnector.doCommand进入nativedaemonconnector.java docommand--à

经过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.11 VolumeManager.cpp

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

#defineMASS_STORAGE_EXTERNAL_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun1/file"

int VolumeManager::shareVolume(const char *label, const char*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的对应。

2.12 流程图

三介质状态发生改变的处理

这个函数是当存储介质的状态发生改变时,会被调用。调用主要发生在StorageManager.java,MountService.java, UsbStorageActivity.java等一下文件中。

public void onStorageStateChanged(final String path,final String oldState, final String newState) {

mAsyncEventHandler.post(new Runnable() {

@Override

public void run() {

onStorageStateChangedAsync(path, oldState, newState);

}

});

}

存储的状态发生变化,如挂载完成了、卸载了、等等,所以当挂载完成后,也会去调用更新。

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;

StorageVolume volume = null;

StorageVolume[] Volumes =mStorageManager.getVolumeList();

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

if(Volumes[i].getPath().equals(path)){

volume = Volumes[i];

break;

}

}

if (volume == null) {

Slog.e(TAG,String.format(

"Can NOT find volume by name {%s}", path));

return;

}

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

……………………

} else if (newState.equals(Environment.MEDIA_MOUNTED)) {

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

setMediaStorageNotification(path, 0, 0, 0, false, false,null);

updateUsbMassStorageNotification(mUmsAvailable);

//挂载成功后,就会调用更新函数,并且只要usb连接着就更新。难道是有些场景usb一直连接着,但是发生了介质重新mounted的情况,所以需要update。

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

mUsbNotifications.clear();

}

}

todo://storage的逻辑思路,需要详细看下面两个文件:

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中功能提供后台服务用的,上层应用是调用不到的。

问题分析试验记录:

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。并且usb connect又出现了。Ums和mtp共用的情况下会出现adb offline?

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

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

private void onStorageStateChangedAsync(String path, StringoldState, 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 amedia device</string>

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

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

private voidupdateUsbNotification() {

android下usb框架系列文章---(2)Usb mass_storage turn on的过程相关推荐

  1. 无锁编程(Lock Free)框架 系列文章

    无锁编程(Lock Free)框架 系列文章: 1 前置知识:伪共享 原理 & 实战 2 disruptor 使用和原理 图解 3 akka 使用和原理 图解 4 camel 使用和 原理 图 ...

  2. Scott的ASP.net MVC框架系列文章之四:处理表单数据(2)

    前几周我发表了一系列文章介绍我们正在研究的ASP.NET MVC框架.ASP.NET MVC框架为你提供了一种新的开发Web应用程序的途径,这种途径可以让应用程序变得更加层次清晰,而且更加有利于对代码 ...

  3. [Android] 图像各种处理系列文章合集

        这是我最近在做Android随手拍一个项目的各种网上关于图片处理的资料,以前学过数字图像处理都是用C++写的,下面的资料个人认为是非常优秀的各种集合,另一方面它是在线笔记,希望对大家有所帮助吧 ...

  4. 2019 年起如何开始学习 ABP 框架系列文章-开篇有益

    阅读文本大概需要 3.3 分钟. 本系列文章推荐阅读地址为:52ABP 开发文档https://www.52abp.com/Wiki/52abp/latest/Welcome-to-52abp 本文的 ...

  5. USB入门系列之一:USB概述

    USB是什么呢?一说USB是You SB的意思,即"你傻B"的意思.另一种说法是USB其实是美国的弟弟,因为美国叫USA,USB当然是他的弟弟了. 那么USB到底是什么呢?其实US ...

  6. Adhesive框架系列文章--Mongodb数据服务模块使用(上)

    之前介绍的应用程序信息中心模块中所有日志.异常.性能和状态数据都依赖Mongodb数据服务,Mongodb数据服务的接口也简单的可以: public interface IMongodbInsertS ...

  7. Adhesive框架系列文章--分布式组件客户端模块使用

    Memcached是一个很常见的分布式组件,现在有很多.NET下开源的Memcached组件的客户端实现,比如EnyimMemcachedClient.在Adhesive框架中实现了一个分布式组件客户 ...

  8. [原]零基础学习在Android进行SDL开发系列文章

    [原]零基础学习SDL开发之移植SDL2.0到Android [原]零基础学习SDL开发之在Android使用SDL2.0显示BMP图 [原]零基础学习SDL开发之在Android使用SDL2.0显示 ...

  9. Adhesive框架系列文章--报警处理流程使用实践

    框架除了报警之外还提供了简单的报警处理流程. 先来看一下报警相关的配置: 比如这里有一个报警,30秒检查一次30秒内相关数据如果超过10条则报警. 在报警后,系统会自动创建一个事件,相关人员登录到后台 ...

最新文章

  1. python3菜鸟教程中文-我的python学习方法和资源整理,干货分享
  2. 思考…求知(boolean和Boolean的区别)
  3. 计算机删除qq用户信息吗,电脑中删除qq资料生日性别的方法
  4. 大前端快闪二:react开发模式 一键启动多个服务
  5. scala 单元测试_Scala中的法律测试简介
  6. python顺序结构的关键字_Python1_Python的目录结构、执行顺序、__name__ == __main__
  7. 00后大学生调研四五线城镇商户:91%用上移动支付
  8. php urledcode_攻防世界 php 2 函数urldecode 使用说明
  9. 通过kubeadm的方式以及二进制包的方式安装k8s的对比总结---K8S_Google工作笔记0016
  10. 全球首发!惯性导航导论(剑桥大学)第八部分
  11. Beta阶段第2周/共2周 Scrum立会报告+燃尽图 10
  12. 5G换机前夕变局:海外停滞,靠中国市场救命?
  13. C语言求一个文件的长度,求二进制文件的长度
  14. 剑指offer面试题55 - I. 二叉树的深度(DFS)(递归)
  15. 虹软java接摄像头_java基于虹软sdk实现人脸识别(demo)
  16. it营Typescript学习笔记02(基础完结)模块,命名空间,装饰器
  17. 恒大人寿保险搭载EastFax USB SERVER推动U盾管理革新
  18. MATLAB全局变量
  19. VOA 2009年11月23日 星期一 这里是美国——感恩节对美国人来说意味着什么
  20. Python-docx实战:同事要我帮忙补写178份日报!别吧

热门文章

  1. Spark多级目录输出,且输出不同值,重写MultipleTextOutputFormat
  2. 【嵌入式linux】linux上搭建嵌入式QT环境
  3. VB+Access设计图书管理系统
  4. Oracle创建序列方法
  5. SNOY VAIO 索尼电脑亮度自动变暗
  6. Java数据结构和算法-----数组
  7. java将js转成转义字符_java正则和JavaScript中的转义字符
  8. 郭德纲经典爆笑语录!!!(肚子疼别找我!!!)
  9. 【Python】Matplotlib中的annotate(注解)【转载】
  10. 5G基站 — CU和DU分离