前言:
对于USB的一些常量属性,比如:UsbManager. USB_FUNCTION_RNDIS(USB的模式)等,现在也是一个比较模糊的概念,只能具体问题具体分析,我们重点说的是类结构,与USB整个框架(仅限于framework层)的逻辑。本来想画一张流程图呢。画来画去好像都跟实际情况有出入。就只能用文字叙述了。
一、调用:
我们从最常见与USB相关的界面说起。当手机连接电脑时,有如下界面:
这个界面是设置里面的一个界面,源码就不贴了,核心代码
获取 UsbManager类的对象:
mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
切换USB连接的模式。比如上图中的,把USB设置为仅充电:
function = UsbManager.USB_FUNCTION_CHARGE_ONLY; mUsbManager.setCurrentFunction(function, true);
下面我们就围绕这两行代码进行分析。
二、UsbManager 如何获得的
1、首先,android 启动的时候会加载SystemServer.java(路径:\frameworks\base\services\java\com\android\server\SystemServer.java),在SystemServer 类中,调用
initAndLoop()方法加载各种服务,USB相关的核心代码
public void initAndLoop() { ...... UsbService usb = null; ...... try { Slog.i(TAG, "USB Service"); // Manage USB host and device support usb = new UsbService(context); ServiceManager.addService(Context.USB_SERVICE, usb); } catch (Throwable e) { reportWtf("starting UsbService", e); } ..... }可以看到SystemServer类中加载的USB相关的服务是 UsbServeice (路径:\frameworks\base\services\java\com\android\server\usb\UsbService.java)
我们这里记着:SystemServer类 中在initAndLoop()方法中,把UsbServeice 加到了 ServiceManager中。
2、其次,我们看ContextImpl.java (路径:\frameworks\base\core\java\android\app\ContextImpl.java)
static{ ... registerService(USB_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(USB_SERVICE); return new UsbManager(ctx, IUsbManager.Stub.asInterface(b)); }}); ... }
registerService()方法的代码:
private static void registerService(String serviceName, ServiceFetcher fetcher) { if (!(fetcher instanceof StaticServiceFetcher)) { fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++; } SYSTEM_SERVICE_MAP.put(serviceName, fetcher); }SYSTEM_SERVICE_MAP 对象
private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP = new HashMap<String, ServiceFetcher>();
由上我们看到,ContextImpl 类中有一个static 块,从ServiceManager 把usbService取出来,然后注册到ContextImpl类中,其实是放到你个HashMap中。
我们在上文“调用”中执行的代码,
mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);这句是在Activity中调用的,而Activity中都有一个关联的ContextImpl 对象,ContextImpl 是对Context的实现类,当在Activity中调用getSystemService(),其实调用的就是ContextImpl类中的getSystemService()。 这个ContextImpl 与Activity的关系我就不说了,可以看下源码,或者网上搜索,比如 http://www.cnblogs.com/android100/p/Android-Context.html 中就有相关的说明。
我们看下ContextImpl类中的getSystemService()
@Override public Object getSystemService(String name) { ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name); return fetcher == null ? null : fetcher.getService(this); }
三、UsbManager 的使用
我们先分析下整个USB的类结构了。首先,我们来一个大体的概念。UsbManager类里面引用了一个UsbService的对象,而UsbService里面又引用了UsbDeviceManager与UsbHostManager的对象,而UsbDeviceManager与UsbHostManager中又分别引用了UsbSettingsManager的对象,而UsbDeviceManager中又引用了UsbDebuggingManager类的对象。大体情况如下图:
这里所说的类的路径都在android 系统源码\frameworks\base\services\java\com\android\server\usb 目录下。
这里插一句:USB分两种模式(这里所说的模式是针对于手机与其所连接的设备所扮演的角色,而我们通篇说的模式是USB选择的功能,如仅充电,PTP,MTP,大容量存储)
usb host 模式:举一例,手机插上键盘之类的外设,手机充当host角色,而UsbHostManager就是跟这个模式相关的,来管理外接设备。
usb Accessory模式:举一例,手机连上电脑,电脑充当host角色,手机是电脑的附件。而UsbDeviceManager就是跟这个模式相关的。而我们通篇都是针对于这种模式来讲解的。
从上图,我们可以清晰的看出类之间的引用关系,接着我回到我们的主题
我们在上文“调用”中执行的代码,
function = UsbManager.USB_FUNCTION_CHARGE_ONLY; mUsbManager.setCurrentFunction(function, true);是设置USB为仅充电模式。那么这句调用是如何执行的呢。先看setCurrentFunction()方法
public void setCurrentFunction(String function, boolean makeDefault) { try { mService.setCurrentFunction(function, makeDefault); } catch (RemoteException e) { Log.e(TAG, "RemoteException in setCurrentFunction", e); } }
@Override public void setCurrentFunction(String function, boolean makeDefault) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); if (mDeviceManager != null) { mDeviceManager.setCurrentFunctions(function, makeDefault); } else { throw new IllegalStateException("USB device mode not supported"); } }
private UsbDeviceManager mDeviceManager;
public void setCurrentFunctions(String functions, boolean makeDefault) { if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ") default: " + makeDefault); mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, makeDefault); }
@Override public void handleMessage(Message msg) { switch (msg.what) { ...... case MSG_SET_CURRENT_FUNCTIONS: String functions = (String)msg.obj; boolean makeDefault = (msg.arg1 == 1); setEnabledFunctions(functions, makeDefault); break; } }
setEnabledFunctions()方法:
private void setEnabledFunctions(String functions, boolean makeDefault) { if (DEBUG) Slog.d(TAG, "setEnabledFunctions " + functions + " makeDefault: " + makeDefault); // Do not update persystent.sys.usb.config if the device is booted up // with OEM specific mode. if (functions != null && makeDefault && !needsOemUsbOverride()) { if (mAdbEnabled) { functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB); } else { functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB); } if (!mDefaultFunctions.equals(functions)) { mInUsbSetting = true; if (!setUsbConfig("none")) { Slog.e(TAG, "Failed to disable USB"); // revert to previous configuration if we fail setUsbConfig(mCurrentFunctions); mInUsbSetting = false; return; } // setting this property will also change the current USB state // via a property trigger SystemProperties.set("persist.sys.usb.config", functions); if (waitForState(functions)) { mCurrentFunctions = functions; mDefaultFunctions = functions; } else { Slog.e(TAG, "Failed to switch persistent USB config to " + functions); // revert to previous configuration if we fail SystemProperties.set("persist.sys.usb.config", mDefaultFunctions); } mInUsbSetting = false; } } else { boolean rndisTetherSetting = UsbManager.USB_FUNCTION_RNDIS.equals(functions); if (functions == null) { functions = mDefaultFunctions; } // Override with bootmode specific usb mode if needed functions = processOemUsbOverride(functions); if (mAdbEnabled) { functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB); } else { functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB); } if (!mCurrentFunctions.equals(functions) || rndisTetherSetting) { if (rndisTetherSetting && containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) { functions = mCurrentFunctions; } mInUsbSetting = true; if (!setUsbConfig("none")) { Slog.e(TAG, "Failed to disable USB"); // revert to previous configuration if we fail setUsbConfig(mCurrentFunctions); mInUsbSetting = false; 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); } mInUsbSetting = false; } }我们看下三个判断条件:
functions != null:设置的USB功能不为空;而当传如的参数为null的话,就是恢复默认功能。
makeDefault:“如果函数应设置为新的默认功能,makeDefault为true。“根据以上代码,当makeDefault为true的时候,会把mDefaultFunctions这个全局变量改为你这次的设置,这个全局变量的作用是,而当你断开连接时,或者传入参数functions为null的情况下,会用这个全局变量来设置USB功能。
needsOemUsbOverride():是否用厂商的属性覆盖。
知道了这三个判断条件,就能很清楚的看到其实执行到这里,就是把functions 写入到了系统属性中,推测kernel会监听这个属性,来改变USB功能。
.... SystemProperties.set("persist.sys.usb.config", functions); .....
private boolean setUsbConfig(String config) { if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")"); // set the new configuration SystemProperties.set("sys.usb.config", config); return waitForState(config); }好了,从应用层调用,一直追溯到这里,就知道了USB是模式切换是怎么实现的了,其实就是到最后,就是把要设置USB当前的模式写入到系统属性文件中。
四、USB查上电脑或者断开,上层会做些什么。
核心的类就是UsbDeviceManager类了。当插上或者断开USB的时候,这个类会监听底层上报的事件,然后上层根据这个事件来做一系列的动作。至于如何监听的,就是UEventObserver类了,UEventObserver是androidJava层利用uevent与获取Kernel层状态变化的机制,这里我们可以看到使用前必须先初始化一个新的UEventObserver类来处理事件,实现函数onUEvent,这是一个回调函数,之后我们会看到他是怎么被调用的
上代码:
private final 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"); if (state != null) { mHandler.updateState(state); } else if ("START".equals(accessory)) { if (DEBUG) Slog.d(TAG, "got accessory start"); startAccessoryMode(); } } };
private final class UsbHandler extends Handler { ...... public UsbHandler(Looper looper) { super(looper); try { ..... mUEventObserver.startObserving(USB_STATE_MATCH); mUEventObserver.startObserving(ACCESSORY_START_MATCH); ..... } catch (Exception e) { Slog.e(TAG, "Error initializing UsbHandler", e); } } }UsbHandler 是UsbDeviceManager中的一个内部类,设置一个UEventObserver监听Usb连接断开的状态,然后通过Handler机制来让上层做一系列的动作,如:弹出通知栏(Notification),或者发送UsbManager.ACTION_USB_STATE 的广播等。
接着就要说UEventObserver机制了,上述代码中:
1、调用startObserving()启动,传入的参数是标记事件的,就是一个Key。
mUEventObserver.startObserving(USB_STATE_MATCH); mUEventObserver.startObserving(ACCESSORY_START_MATCH);2、UEventObserver类中的startObserving()方法
public final void startObserving(String match) { if (match == null || match.isEmpty()) { throw new IllegalArgumentException("match substring must be non-empty"); } final UEventThread t = getThread(); t.addObserver(match, this); }3、getThread()方法
private static UEventThread getThread() { synchronized (UEventObserver.class) { if (sThread == null) { sThread = new UEventThread(); sThread.start(); } return sThread; } }
private static final class UEventThread extends Thread { private final ArrayList<Object> mKeysAndObservers = new ArrayList<Object>(); private final ArrayList<UEventObserver> mTempObserversToSignal = new ArrayList<UEventObserver>(); public UEventThread() { super("UEventObserver"); } @Override public void run() { nativeSetup(); while (true) { String message = nativeWaitForNextEvent(); if (message != null) { if (DEBUG) { Log.d(TAG, message); } sendEvent(message); } } } private void sendEvent(String message) { synchronized (mKeysAndObservers) { final int N = mKeysAndObservers.size(); for (int i = 0; i < N; i += 2) { final String key = (String)mKeysAndObservers.get(i); if (message.contains(key)) { final UEventObserver observer = (UEventObserver)mKeysAndObservers.get(i + 1); mTempObserversToSignal.add(observer); } } } if (!mTempObserversToSignal.isEmpty()) { final UEvent event = new UEvent(message); final int N = mTempObserversToSignal.size(); for (int i = 0; i < N; i++) { final UEventObserver observer = mTempObserversToSignal.get(i); observer.onUEvent(event); } mTempObserversToSignal.clear(); } } public void addObserver(String match, UEventObserver observer) { synchronized (mKeysAndObservers) { mKeysAndObservers.add(match); mKeysAndObservers.add(observer); nativeAddMatch(match); } } /** Removes every key/value pair where value=observer from mObservers */ public void removeObserver(UEventObserver observer) { synchronized (mKeysAndObservers) { for (int i = 0; i < mKeysAndObservers.size(); ) { if (mKeysAndObservers.get(i + 1) == observer) { mKeysAndObservers.remove(i + 1); final String match = (String)mKeysAndObservers.remove(i); nativeRemoveMatch(match); } else { i += 2; } } } } }
Run()方法,调用了两个native方法(JNI),我们来分析一下:
nativeSetup(); nativeWaitForNextEvent();UEventObserver中所有的JNI调用的方法所在的文件是android_os_UEventObserver.cpp
路径:\frameworks\base\core\jni\android_os_UEventObserver.cpp
static void nativeSetup(JNIEnv *env, jclass clazz) { if (!uevent_init()) { jniThrowException(env, "java/lang/RuntimeException", "Unable to open socket for UEventObserver"); } }
static jstring nativeWaitForNextEvent(JNIEnv *env, jclass clazz) { char buffer[1024]; for (;;) { int length = uevent_next_event(buffer, sizeof(buffer) - 1); if (length <= 0) { return NULL; } buffer[length] = '\0'; ALOGV("Received uevent message: %s", buffer); if (isMatch(buffer, length)) { // Assume the message is ASCII. jchar message[length]; for (int i = 0; i < length; i++) { message[i] = buffer[i]; } return env->NewString(message, length); } } }
int uevent_init() { struct sockaddr_nl addr; int sz = 64*1024; int s; memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_pid = getpid(); addr.nl_groups = 0xffffffff; s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if(s < 0) return 0; setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { close(s); return 0; } fd = s; return (fd > 0); }会创建一个socket ,定义内核事件向用户态通知(NETLINK_KOBJECT_UEVENT),返回返回一个fd
int uevent_next_event(char* buffer, int buffer_length) { while (1) { struct pollfd fds; int nr; fds.fd = fd; fds.events = POLLIN; fds.revents = 0; nr = poll(&fds, 1, -1); if(nr > 0 && (fds.revents & POLLIN)) { int count = recv(fd, buffer, buffer_length, 0); if (count > 0) { struct uevent_handler *h; pthread_mutex_lock(&uevent_handler_list_lock); LIST_FOREACH(h, &uevent_handler_list, list) h->handler(h->handler_data, buffer, buffer_length); pthread_mutex_unlock(&uevent_handler_list_lock); return count; } } } // won't get here return 0; }
总结一下:底层通过Poll与socket获取消息,然后到上层android_os_UEventObserver.cpp 类中,然后到UEventObserver中,UEventObserver回调UsbDeviceManager类中mUEventObserver实现的函数onUEvent,然后上层做处理,无论是发通知,或者发广播。
5、编译android源码默认开启USB调试模式
当android源码编译时,会执行\build\tools\post_process_props.py (Python语言)文件来配置属性,有一段代码是这样的:
if prop.get("ro.debuggable") == "1": val = prop.get("persist.sys.usb.config") if val == "": val = "adb" else: val = val + ",adb" prop.put("persist.sys.usb.config", val)如果ro.debuggable 值为1的话,就在属性里增加adb,就是开启USB调试模式
所以,你可以在你的属性配置文件里配置这个属性为1就行了。
比如我的配置文件prod_xxxxxx.mk中
#Add for adb debug open PRODUCT_PROPERTY_OVERRIDES += \ ro.debuggable=1
到此,USB相关的逻辑部分就分析到这里。