Andrid MTP之UsbService分析

在分析Android MTP之前,先介绍下UsbService,它有何用呢?先看下源码中的注释

/**
 * UsbService manages all USB related state, including both host and device support.
 * Host related events and calls are delegated to UsbHostManager, and device related
 * support is delegated to UsbDeviceManager.
 */
public class UsbService extends IUsbManager.Stub {}

注释其实已经对UsbService解释的很清楚,但是如果需要明白具体是啥意思,我们需要一点USBMTP的知识。 在USB协议中,连接USB的两端被称为USB HostUSB Device,而Android设备既可以作为USB Host端,也可以作为USB Device端,因此UsbService就是用来管理这两种情况的。从注释中可以看出,UsbServiceUsbDeviceManager代理手机作为Usb Device端的功能,而用UsbHostManager代理手机作为Usb Host端的功能。

而本文要分析的MTP协议是构建于物理层USB之上的,Usb Host被称为InitiatorUsb Device被称为ResponderInitiator用来向Responder发送操作请求,而Responder用来响应请求。

那么,什么时候设备可以作为Usb Device端,什么时候又可以作为Usb Host端呢? 当手机连接电脑的时候,手机就是Usb Device端,而当手机连接鼠标时,手机可以作为Usb Host端。

那么今天我们要讨论的MTP对应的情况是手机连接电脑,那么手机就是作为USB Device端,那么我们的目光自然就要聚焦到UsbDeviceManager这个类上。不过,在分析这个类之前,我们需要知道UsbService是如何启动的。

UsbService的类声明就可以猜出它是一个系统服务,那么就是从SystemServer.java中启动的

public final class SystemServer {
    private static final String USB_SERVICE_CLASS =
            "com.android.server.usb.UsbService$Lifecycle";

    private void startOtherServices() {
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
                || mPackageManager.hasSystemFeature(
                        PackageManager.FEATURE_USB_ACCESSORY)) {
            mSystemServiceManager.startService(USB_SERVICE_CLASS);
            traceEnd();
        }
    }
}    

我们注意到,USB_SERVICE_CLASS指的是UsbService的一个内部类Lifecycle,这个内部类实现了SystemService接口,实现这个接口的子类表明是一个系统服务,并且用来接收各种生命周期回调,然而Lifecycle并不似一个真正的系统服务,因为当发生生命周期回调的时候,调用的是UsbService相应的方法,这就是一个典型的代理模式的应用,其实系统中很多服务都是这样设计的。

那么,我们来粗略看下SystemServiceManager是如何启动这个系统服务的

/**
 * Manages creating, starting, and other lifecycle events of
 * {@link com.android.server.SystemService system services}.
 */
public class SystemServiceManager {
    public SystemService startService(String className) {
        final Class<SystemService> serviceClass;
        try {
            serviceClass = (Class<SystemService>)Class.forName(className);
        } catch (ClassNotFoundException ex) {
			// ...
        }
        return startService(serviceClass);
    }

    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            final String name = serviceClass.getName();

            // Create the service.
            // 判断是否是相同类型
            if (!SystemService.class.isAssignableFrom(serviceClass)) {
                throw new RuntimeException("Failed to create " + name
                        + ": service must extend " + SystemService.class.getName());
            }
            final T service;
            try {
            	// 获取有Context类型作为参数的构造函数
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                // 创建对象
                service = constructor.newInstance(mContext);
            } catch (Exception ex) {
				// ...	
			}
            startService(service);
            return service;
        } finally {
            // ...
        }
    }

    // Services that should receive lifecycle events.
    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
    
    public void startService(@NonNull final SystemService service) {
        // Register it.
        // 保存在mServices中,以便这个系统服务能收到各种生命周期事件
        mServices.add(service);
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
        	// 真正启动系统服务的地方
            service.onStart();
        } catch (RuntimeException ex) {
         	// ...
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }
} 

首先调用的是UsbService$Lifecycle的带Context参数的构造函数创建Lifecycle对象,然后调用这个对象的onStart()方法。在分析这个onStart()方法之前,在代码中有一点需要注意,在创建Lifecycle对象后,用一个ArrayList变量mService保存了这个Lifecycle对象,显而易见,mService是用来保存各种系统服务(可能这个服务只是一个代理)。当时机得当,就可以统一调用各种服务的的声明周期,UsbService$Lifecycle就回调了各种声明周期方法,在后面即将看到。

UsbService启动

那么,现在来看下UsbService$LifecycleonStart()方法吧

public class UsbService extends IUsbManager.Stub {

    public static class Lifecycle extends SystemService {
		// ...

        @Override
        public void onStart() {
        	// 创建UsbService对象
            mUsbService = new UsbService(getContext());
            // 向系统注册这个服务,以便其他Service和App能访问
            publishBinderService(Context.USB_SERVICE, mUsbService);
        }

        @Override
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                mUsbService.systemReady();
            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
                mUsbService.bootCompleted();
            }
        }

		// ...
    }
}    

与我们分析相关的生命周期回调有两个,一个是onStart(),在创建时候回调,一个是onBootPhase是在系统启动阶段回调。 在onStart()中首先创建了UsbService对象,然后向系统注册了这个服务,那么接下来看下UsbService的构造函数。

public class UsbService extends IUsbManager.Stub {
    public UsbService(Context context) {
        mContext = context;
# UsbService的启动
        mUserManager = context.getSystemService(UserManager.class);
        // 用户设置相关
        mSettingsManager = new UsbSettingsManager(context);
        // USB音频相关
        mAlsaManager = new UsbAlsaManager(context);

        final PackageManager pm = mContext.getPackageManager();
        // 如果设备有作为Host端的feature,就创建UsbHostMananger对象
        if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
            mHostManager = new UsbHostManager(context, mAlsaManager, mSettingsManager);
        }
		// 从这里可以看出/sys/class/android_usb节点代表设备是否支持作为Device端的feature
        if (new File("/sys/class/android_usb").exists()) {
            mDeviceManager = new UsbDeviceManager(context, mAlsaManager, mSettingsManager);
        }
        
        if (mHostManager != null || mDeviceManager != null) {
            mPortManager = new UsbPortManager(context);
        }

		// 用户切换
        onSwitchUser(UserHandle.USER_SYSTEM);

		// 监听设备策略广播,决定是否限制数据访问
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
                        .equals(action)) {
                    if (mDeviceManager != null) {
                        mDeviceManager.updateUserRestrictions();
                    }
                }
            }
        };

        final IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
        mContext.registerReceiver(receiver, filter, null, null);
    }
}    

构造函数做了很多初始化工作,根据前面的介绍,我们需要把重点聚焦到UsbDeviceManager的创建

public class UsbDeviceManager {
    public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
            UsbSettingsManager settingsManager) {
        // 1. 初始化参数
        mContext = context;
        mUsbAlsaManager = alsaManager;
        mSettingsManager = settingsManager;
        mContentResolver = context.getContentResolver();
        PackageManager pm = mContext.getPackageManager();
        mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
        // 用序列号初始化RNDIS以太网地址
        initRndisAddress();

		// 2. 读取OEM的配置
        readOemUsbOverrideConfig();
		
		// 3. 创建UsbHandler对象
		// 这个Handler是真正为UsbDeviceManager做事的
        mHandler = new UsbHandler(FgThread.get().getLooper());

        if (nativeIsStartRequested()) {
            if (DEBUG) Slog.d(TAG, "accessory attached at boot");
            startAccessoryMode();
        }

		// 4. 根据情况创建DebuggingManager对象(与adb相关)
		// ro.adb.secure代表adb是否授权,user版本上这个属性的值是1
        boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
        // 是否经过加密
        boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
        // 基本可以理解为User版本创建UsbDebuggingManager对象
        if (secureAdbEnabled && !dataEncrypted) {
            mDebuggingManager = new UsbDebuggingManager(context);
        }

		// 5. 注册各种广播监听器,利用UsbHandler来进行更新操作
        BroadcastReceiver portReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                UsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT);
                UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS);
                mHandler.updateHostState(port, status);
            }
        };

        BroadcastReceiver chargingReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
                boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
                mHandler.sendMessage(MSG_UPDATE_CHARGING_STATE, usbCharging);
            }
        };

        BroadcastReceiver hostReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Iterator devices = ((UsbManager) context.getSystemService(Context.USB_SERVICE))
                        .getDeviceList().entrySet().iterator();
                if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
                    mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, true);
                } else {
                    mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, false);
                }
            }
        };

        BroadcastReceiver languageChangedReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED);
            }
        };

        // 监听USB端口改变
        mContext.registerReceiver(portReceiver,
                new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED));

        // 监听电量改变
        mContext.registerReceiver(chargingReceiver,
                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

        // 监听USB连接/断开
        IntentFilter filter =
                new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        mContext.registerReceiver(hostReceiver, filter);

        // 监听区域改变
        mContext.registerReceiver(languageChangedReceiver,
                new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
    }
}    

虽然我分了这么多步,但是我们只分析和本文主题相关的第二步和第三步。

首先看下第步,这一步是读取OEM厂商的需要覆盖USB功能的配置。

    private void readOemUsbOverrideConfig() {
        // [bootmode]:[original USB mode]:[USB mode used]
        String[] configList = mContext.getResources().getStringArray(
                com.android.internal.R.array.config_oemUsbModeOverride);

        if (configList != null) {
            for (String config : configList) {
                String[] items = config.split(":");
                if (items.length == 3 || items.length == 4) {
                    if (mOemModeMap == null) {
                        mOemModeMap = new HashMap<>();
                    }
                    HashMap<String, Pair<String, String>> overrideMap
                            = mOemModeMap.get(items[0]);
                    if (overrideMap == null) {
                        overrideMap = new HashMap<>();
                        mOemModeMap.put(items[0], overrideMap);
                    }

                    // Favoring the first combination if duplicate exists
                    if (!overrideMap.containsKey(items[1])) {
                        if (items.length == 3) {
                            overrideMap.put(items[1], new Pair<>(items[2], ""));
                        } else {
                            overrideMap.put(items[1], new Pair<>(items[2], items[3]));
                        }
                    }
                }
            }
        }
    }

是不是看的一头雾水,但是如果你理解com.android.internal.R.array.config_oemUsbModeOverride数组每一项如何定义后就明白了

    <!-- Array of OEM specific USB mode override config.
         OEM can override a certain USB mode depending on ro.bootmode.
         Specify an array of below items to set override rule.
         [bootmode]:[original USB mode]:[USB mode used]-->
    <integer-array translatable="false" name="config_oemUsbModeOverride">
    </integer-array>

mOemModeMap就是保存了这些数据,置于怎么保存数据我就不解释了,简单的用如下的json格式表示如下

{
	{bootmode:{original_usb_mode:{usb_mode_used}}},
	{bootmode:{original_usb_mode:{usb_mode_used}}},
	// ...
}

其实,我们可以注意到,这里其实没有保存任何数据,那么我为何还要把它提出来分析,因为这在我们做系统定制的时候也许有帮助的,而且在后面的分析中也涉及到mOemModeMap,到时候我们再看下这些数据到底有何作用。

那么,现在我们接着看UsbDeviceManager构造函数的第步,代码如下

mHandler = new UsbHandler(FgThread.get().getLooper());

UsbHandler是真正为UsbDeviceManager干活的家伙,这里我们需要注意,它使用的Looper其实是HandlerThread中的Looper,这样一来UsbDeviceManager就把所有工作放到了另外一个线程中处理了。

现在我们来看下UsbHandler的构造函数吧

	    /**
	     * The persistent property which stores whether adb is enabled or not.
	     * May also contain vendor-specific default functions for testing purposes.
	     */
	    private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
	
	    /**
	     * The non-persistent property which stores the current USB settings.
	     */
	    private static final String USB_CONFIG_PROPERTY = "sys.usb.config";
	
	    /**
	     * The non-persistent property which stores the current USB actual state.
	     */
	    private static final String USB_STATE_PROPERTY = "sys.usb.state";

		/*
		 * 用于读取USB状态
		 */
    	private static final String STATE_PATH = "/sys/class/android_usb/android0/state";
	    
        public UsbHandler(Looper looper) {
            super(looper);
            try {
            	// 1. 获取当前USB的设置,并与实际的USB状态相比较
                if (isNormalBoot()) {
                	// 表示USB功能的当前设置
                    mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
                            UsbManager.USB_FUNCTION_NONE);
                    // 表示USB功能的当前设置是否全部被应用
                    mCurrentFunctionsApplied = mCurrentFunctions.equals(
                            SystemProperties.get(USB_STATE_PROPERTY));
                } else {
					// ...
                }

				
				// 2. 检测adb是否开启
                mAdbEnabled = UsbManager.containsFunction(
                        SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY),
                        UsbManager.USB_FUNCTION_ADB);

                /*
                 * Previous versions can set persist config to mtp/ptp but it does not
                 * get reset on OTA. Reset the property here instead.
                 * 按照注释所说,跟OTA相关,具体的操作是移除persist.sys.usb.config属性中的ptp值
                 */
                String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
                if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)
                		|| UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) {
                    SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
                            UsbManager.removeFunction(UsbManager.removeFunction(persisted,
                            		UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP));
                }

				// 3. 读取当前USB状态,并更新状态
                String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
                updateState(state);

                // 注册Observer监听adb设置的改变,从而利用socket,开关adb
                mContentResolver.registerContentObserver(
                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
                        false, new AdbSettingsObserver());

                // 4. 监听USB配置改变,从而利用mHandler更新状态
                mUEventObserver.startObserving(USB_STATE_MATCH);
                mUEventObserver.startObserving(ACCESSORY_START_MATCH);
            } catch (Exception e) {
                Slog.e(TAG, "Error initializing UsbHandler", e);
            }
        }

虽然代码比较简单,但是我列出了与MTP分析相关的这几步用于分析。

步,根据启动模式来为两个变量赋值,这里我们只考虑正常启动模式。mCurrentFunctions代表USB功能的当前设置,mCurrentFunctionsApplied表示USB功能的当前设置是否与实际功能相符。

sys.usb.config 属性如注释所说,代表当前USB设置,什么意思呢? 例如,当我们在手机上设置USB的模式为File transfer,也就是MTP模式的时候,sys.usb.config的值一般为mtp, adb,我们暂且不用关心为何有adb属性,其实我们只要明白sys.usb.config就代表了设置USB模式时对应的值。

sys.usb.state属性如注释所说,代表了USB实际状态,什么意思呢?虽然用户设置USB模式为MTPsys.usb.config的值也变为了mtp, adb,然而底层是否能设置成功呢?如果没有成功,那么sys.usb.state的值可能就为none,如果成功了,那么sys.usb.state的值就与sys.usb.config的值一样了。这就可以解释了为何在代码中去比较这两个属性的值,当这两个值相等的时候,就证明当前的USB设置是成功的。

步,检测abd是否开启了,怎么判断的呢?首先读取persist.sys.usb.config属性的值,然后判断这个值中是否包含adb

步,读取USB状态并更新,这算是一个USB状态初始化操作。读取的节点是/sys/class/android_usb/android0/state。现在我们看下更新操作

public class UsbDeviceManager {
    private final class UsbHandler extends Handler {
        public void updateState(String state) {
            int connected, configured;

            if ("DISCONNECTED".equals(state)) {
                connected = 0;
                configured = 0;
            } else if ("CONNECTED".equals(state)) {
                connected = 1;
                configured = 0;
            } else if ("CONFIGURED".equals(state)) {
                connected = 1;
                configured = 1;
            } else {
                Slog.e(TAG, "unknown state " + state);
                return;
            }
            removeMessages(MSG_UPDATE_STATE);
            Message msg = Message.obtain(this, MSG_UPDATE_STATE);
            msg.arg1 = connected;
            msg.arg2 = configured;
            // debounce disconnects to avoid problems bringing up USB tethering
            sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
        }
    }
}    

从这个函数的实现中,我们可以发现,USB的合理状态其实只有DISCONNECTED, CONNECTED, CONFIGURED三个值。其实,当手机通过USB连接电脑的时候,USB状态就是从DISCONNECTED- > CONNECTED -> CONFIGURED转换的。

我们现在分析的阶段为UsbService的创建阶段,我们假设此时USB还没有连接上,那么这里的变量connectedconfigured都为0。

最后发送了一个MSG_UPDATE_STATE消息来处理USB状态更新。

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_STATE:
                	// 1. 保存了USB状态
                	mConnected = (msg.arg1 == 1);
                	mConfigured = (msg.arg2 == 1);
					
					// 2. 更新下usb和adb通知
                    updateUsbNotification(false);
                    updateAdbNotification(false);
                    
                    // 3. 如果已经启动完毕,就发送USB状态广播
                    if (mBootCompleted) {
                        updateUsbStateBroadcastIfNeeded(false);
                    }
                    
                    // 3. USB的ACCESSORY功能相关操作
                    if (UsbManager.containsFunction(mCurrentFunctions,
                            UsbManager.USB_FUNCTION_ACCESSORY)) {
                        updateCurrentAccessory();
                    }
                    
                    // 4. 启动完毕,但是USB没有连接上
                    if (mBootCompleted) {
                        if (!mConnected) {
                            // restore defaults when USB is disconnected
                            // 重置USB功能为none,adb
                            setEnabledFunctions(null, !mAdbEnabled, false);
                        }
                        // 与USB的AUDIO和MIDI相关的更新
                        updateUsbFunctions();
                    } else {
                        mPendingBootBroadcast = true;
                    }
                    break;
                    
                // ...
            }
        }

由于目前分析的阶段为UsbServiceonStart()阶段,也就是创建阶段,这里其实只是简单的保存了USB状态,再加上最后一行的mPendingBootBroadcast = true代码。当系统启动完毕后,我们会再次看到这个消息的处理,到时候再来分析这里的代码逻辑。

步,这一步非常重要,我们可以看下mUEventObserver变量的赋值

    /*
     * Listens for uevent messages from the kernel to monitor the USB state
     */
    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();
            }
        }
    };

从注释中我们可以知道,这里是监听内核的消息,当我们把手机和电脑通过USB连接上后,USB状态就会改变,我们发现又是调用mHandlerupdateState()方法,这个方法我们在前面分析过,这里不再重复。然而目前我们并不去分析手机连接电脑的情况,等我们把UsbService分析完毕后,再来分析连接USB的情况。

系统启动阶段

当系统启动完毕,就会执行UsbService.Lifecycle对象的onBootPhase()回调。

public class UsbService extends IUsbManager.Stub {

    public static class Lifecycle extends SystemService {
    
    	// ...
    	
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                mUsbService.systemReady();
            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
                mUsbService.bootCompleted();
            }
        }
    }
}    

这涉及到系统的启动几个阶段,PHASE_ACTIVITY_MANAGER_READY代表ActivityManagerService已就绪,PHASE_BOOT_COMPLETED代表启动启动完毕。很显然,先是经历PHASE_ACTIVITY_MANAGER_READY再经历PHASE_BOOT_COMPLETED

PHASE_ACTIVITY_MANAGER_READY阶段

先看下PHASE_ACTIVITY_MANAGER_READY阶段的操作,调用的是systemRead()函数

    public void systemReady() {
        mAlsaManager.systemReady();

        if (mDeviceManager != null) {
            mDeviceManager.systemReady();
        }
        if (mHostManager != null) {
            mHostManager.systemReady();
        }
        if (mPortManager != null) {
            mPortManager.systemReady();
        }
    }

我们这里只需要关心UsbDeviceManagersystemRead()函数

    public void systemReady() {
        if (DEBUG) Slog.d(TAG, "systemReady");
		
		// 可以注意到mNotificationManager是在系统系统就绪阶段创建的,这就代表了这个阶段可以发送广播了
        mNotificationManager = (NotificationManager)
                mContext.getSystemService(Context.NOTIFICATION_SERVICE);

        // Ensure that the notification channels are set up
        // TV相关
        if (isTv()) {
			// ...
        }

        // We do not show the USB notification if the primary volume supports mass storage.
        // The legacy mass storage UI will be used instead.
        // 如果主存储支持USB的mass storage功能,那么就不会显示USB通知
        boolean massStorageSupported;
        final StorageManager storageManager = StorageManager.from(mContext);
        final StorageVolume primary = storageManager.getPrimaryVolume();
        massStorageSupported = primary != null && primary.allowMassStorage();
        mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_usbChargingMessage);

        // make sure the ADB_ENABLED setting value matches the current state
        // 根据mAdbEnabled的值,来更新数据库的值
        try {
            Settings.Global.putInt(mContentResolver,
                    Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
        } catch (SecurityException e) {
            // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed.
            Slog.d(TAG, "ADB_ENABLED is restricted.");
        }
        // 发送MSG_SYSTEM_READY消息
        mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
    }

在这个函数中我们只关心最后发送的MSG_SYSTEM_READ的消息,现在来看下这个消息的处理

        public void handleMessage(Message msg) {
            switch (msg.what) {
            	// ...
                case MSG_SYSTEM_READY:
                	// 1. 如果USB连接上,就发送USB通知,通过这个通知,我们可以选择USB模式
                    updateUsbNotification(false);
                    // 2. 如果USB连接上,发送adb通知,可以通过这个通知打开开发者模式界面
                    updateAdbNotification(false);
                    // 3. 更新USB的AUIO和MIDI功能
                    updateUsbFunctions();
                    break;
                // ...
            }
        }

与前面保持一致,我们假设现在手机还没有通过USB连接到电脑,因此这里就不分析了。

PHASE_BOOT_COMPLETED阶段

那么再回到UsbService.LifecycleonBootPhase()回调,来看下PHASE_BOOT_COMPLETED阶段的操作

public class UsbService extends IUsbManager.Stub {
	public static class Lifecycle extends SystemService {
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                mUsbService.systemReady();
            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
                mUsbService.bootCompleted();
            }
        }
    }

    public void bootCompleted() {
        if (mDeviceManager != null) {
            mDeviceManager.bootCompleted();
        }
    }
}    

PHASE_BOOT_COMPLETED阶段,调用的是UsbDeviceManager对象的bootCompleted()函数,看下这个函数的实现

public class UsbDeviceManager {
    public void bootCompleted() {
        mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
    }
}    

非常简单,就是发送了一个MSG_BOOT_COMPLETED消息,接下来看下消息如何处理的

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_BOOT_COMPLETED:
                	// mBootCompleted代表系统是否已经启动完毕
                    mBootCompleted = true;
                    // 1. 如果usb状态改变就发送USB状态广播
                    if (mPendingBootBroadcast) {
                        updateUsbStateBroadcastIfNeeded(false);
                        mPendingBootBroadcast = false;
                    }
                    // 2. 设置USB功能为none
                    setEnabledFunctions(null, false, false);
                    //  与USB Accessory功能相关
                    if (mCurrentAccessory != null) {
                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
                    }
                    // 与adb进程通信,弹出USB授权窗口,根据用户操作,决定是否开启adb
                    if (mDebuggingManager != null) {
                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
                    }
                    break;

这里只关心前两步,第步,根据USB状态是否改变来决定是否发送USB状态广播。这里有个条件mPendingBootBroadcast,还记得吗?在前面分析UsbService的启动中这个变量被设置为true。为了与前面分析保持一致,我们继续假设手机没有通过USB和电脑连接,因此这里也不会发送广播。

再来看下处理MSG_BOOT_COMPLETED消息的第步,这一步相当于重置USB功能,代码为setEnabledFunctions(null, false, false),注意这里参数。

    /**
     * Evaluates USB function policies and applies the change accordingly.
     */
    private void setEnabledFunctions(String functions, boolean forceRestart,
            boolean usbDataUnlocked) {
        // 1. 如果数据锁定状态改变了就更新usb通知
        if (usbDataUnlocked != mUsbDataUnlocked) {
            mUsbDataUnlocked = usbDataUnlocked;
            updateUsbNotification(false);
            forceRestart = true;
        }   

        // Try to set the enabled functions.
        final String oldFunctions = mCurrentFunctions;
        final boolean oldFunctionsApplied = mCurrentFunctionsApplied;

        // 2. 尝试设置USB可用功能
        if (trySetEnabledFunctions(functions, forceRestart)) {
            return;
        } 
        
        // Didn't work.  Try to revert changes.
        // We always reapply the policy in case certain constraints changed such as
        // user restrictions independently of any other new functions we were
        // trying to activate.
        // 3. 到这一步表示设置USB新功能失败,那么就回退呗
        if (oldFunctionsApplied && !oldFunctions.equals(functions)) {
            Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
            if (trySetEnabledFunctions(oldFunctions, false)) {
                return;
            }
        }

        // Still didn't work.  Try to restore the default functions.
        // 4. 到这一步,表明回退都失败了,那么就恢复默认吧
        Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
        if (trySetEnabledFunctions(null, false)) {
            return;
        } 

        // Now we're desperate.  Ignore the default functions.
        // Try to get ADB working if enabled.
        Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
        // 5. 如果到这里,那么证明恢复默认都失败,握草,放弃吧,把USB功能设置为none(意思就是,我不玩了还不行吗)
        if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) {
            return;
        }  

        // Ouch.
        // 6. 到这一步应该不可能吧,加个Log压压惊!
        Slog.e(TAG, "Unable to set any USB functions!");
    }    

第一步,根据参数的值,很显然这里的条件不成立。后面的几步呢,其实都是调用同一个函数,因此我们用第二步来分析这个函数
,注意传入的参数functionsnullforceRestartfalse

		/*
		 * 参数functions代表需要设置给USB的功能,例如"mtp"
		 * 参数forceRestart代表USB功能是否强制重新设置
		 */
        private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
        	// 1. 如果功能为null,就获取默认的功能
            if (functions == null || applyAdbFunction(functions)
                    .equals(UsbManager.USB_FUNCTION_NONE)) {
                functions = getDefaultFunctions();
            }
            
            // 2. 根据情况决定是否增加adb组合
            functions = applyAdbFunction(functions);

			// 3. 使用运营商设置的参数,覆盖对应的功能。默认的是没有任何覆盖的。
            String oemFunctions = applyOemOverrideFunction(functions);

            // 非正常启动情况,设置一些属性
            if (!isNormalBoot() && !mCurrentFunctions.equals(functions)) {
                SystemProperties.set(getPersistProp(true), functions);
            }
			
			// 4. 根据条件判断是否设置USB新功能
            if ((!functions.equals(oemFunctions) &&
                    (mCurrentOemFunctions == null ||
                            !mCurrentOemFunctions.equals(oemFunctions)))
                    || !mCurrentFunctions.equals(functions)
                    || !mCurrentFunctionsApplied
                    || forceRestart) {
                Slog.i(TAG, "Setting USB config to " + functions);
                mCurrentFunctions = functions;
                mCurrentOemFunctions = oemFunctions;
                mCurrentFunctionsApplied = false;

                // Kick the USB stack to close existing connections.
                // 4.1. 设置sys.usb.config的属性值,这里指关闭已存在的的USB链接
                setUsbConfig(UsbManager.USB_FUNCTION_NONE);

                // 用1秒钟检测sys.usb.stat属性是否等于UsbManager.USB_FUNCTION_NONE
                // 如果成功,代表前面的USB连接关闭成功,如果失败就直接返回
                if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
                    Slog.e(TAG, "Failed to kick USB config");
                    return false;
                }

                // Set the new USB configuration.
                // 4.2. 设置新的USB功能
                setUsbConfig(oemFunctions);

                // 4.3. 如果手机已经启动完毕,而且切换的功能中包含MTP/PTP,就发送广播
                if (mBootCompleted
                        && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
                        || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
                    // Start up dependent services.
                    updateUsbStateBroadcastIfNeeded(true);
                }

                // 用1秒钟检测sys.usb.stat属性是否等于oemFunctions
                // 如果成功,代表USB功能切换成功,如果失败,直接返回
                if (!waitForState(oemFunctions)) {
                    Slog.e(TAG, "Failed to switch USB config to " + functions);
                    return false;
                }

                mCurrentFunctionsApplied = true;
            }
            return true;
        }

根据传入参数的值,很显然第步就会调用getDefaultFunctions()来获取USB默认的功能。

        private String getDefaultFunctions() {
            String func = SystemProperties.get(getPersistProp(true),
                    UsbManager.USB_FUNCTION_NONE);

            // if ADB is enabled, reset functions to ADB
            // else enable MTP as usual.
            if (UsbManager.containsFunction(func, UsbManager.USB_FUNCTION_ADB)) {
            	// 这里为何不直接用一条语句return funcs;解决问题?
                if (UsbManager.USB_FUNCTION_ADB.equals(func)) {
                    return UsbManager.USB_FUNCTION_ADB;
                } else {
                    return func;
                }
            } else {
                return UsbManager.USB_FUNCTION_MTP;
            }
        }
        
	    public static String getPersistProp(boolean functions) {
	        String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
	        // persist.sys.usb.config
	        String persistProp = USB_PERSISTENT_CONFIG_PROPERTY;
	        // 非正常模式启动的属性
	        if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) {
	            if (functions) {
	                persistProp = "persist.sys.usb." + bootMode + ".func";
	            } else {
	                persistProp = "persist.sys.usb." + bootMode + ".config";
	            }
	        }
	
	        return persistProp;
	    }

我们假设手机的启动模式是正常启动模式,那么getPersistProp()方法获取的就是persist.sys.usb.config属性的值,这个值我们在前面提过一次,当初用这个属性值是用来判断是否要开启adb,然而这里用这个属性值来决定USB的默认功能。可以看出,如果这个属性值包含adb,那么就会把这个属性值作为默认的USB功能返回,否则USB的默认功能就是mtp

接着看第步,这里是把adb功能设置上去,以我手机为例,上一步,我们获取的默认的值是charging, adb

        private String applyAdbFunction(String functions) {
            // Do not pass null pointer to the UsbManager.
            // There isnt a check there.
            if (functions == null) {
                functions = "";
            }
            boolean adbEnable = mAdbEnabled;
            if (isStrictOpEnable()
                    && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
                    && !mUsbDataUnlocked)) {
                adbEnable = false;
            }
            if (adbEnable) {
                functions = UsbManager.addFunction(functions, UsbManager.USB_FUNCTION_ADB);
            } else {
                functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
            }
            return functions;
        }

		// 与运营商认证相关
        private boolean isStrictOpEnable() {
            return SystemProperties.getBoolean("persist.vendor.strict_op_enable", false);
        }

persist.vendor.strict_op_enable这个属性呢,我稍微查了下,好像跟运营商入网认证有关系,我用的测试机,这个值是没有设置的,我们就暂时先不管这个值了。

mAdbEnabled 这个值在我们前面的分析中出现过,赋值代码如下

				// 读取persist.sys.usb.config的值,看是否包含adb
                mAdbEnabled = UsbManager.containsFunction(
                        SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY),
                        UsbManager.USB_FUNCTION_ADB);

mAdbEnabled的值是根据persist.sys.usb.config属性的值是否包含adb来决定的,我的测试样机中这个属性的默认值是charging,adb,很显然mAdbEnabled的值为true

那么applyAdbFunction()方法的返回值,其实就是与参数一样,是charging,adb

步,使用OEMUSB功能覆盖原始的USB功能。在前面的分析中我们说过,我们需要看下这个覆盖功能是如何使用的


    private String applyOemOverrideFunction(String usbFunctions) {
        if ((usbFunctions == null) || (mOemModeMap == null)) {
            return usbFunctions;
        }

        String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
        Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode);

        Map<String, Pair<String, String>> overridesMap =
                mOemModeMap.get(bootMode);
        // Check to ensure that the oem is not overriding in the normal
        // boot mode
        // 从条件可以看出,正常启动模式下,usb功能是不覆盖的
        if (overridesMap != null && !(bootMode.equals(NORMAL_BOOT) ||
                bootMode.equals("unknown"))) {
            Pair<String, String> overrideFunctions =
                    overridesMap.get(usbFunctions);
            if (overrideFunctions != null) {
                Slog.d(TAG, "OEM USB override: " + usbFunctions
                        + " ==> " + overrideFunctions.first
                        + " persist across reboot "
                        + overrideFunctions.second);
                if (!overrideFunctions.second.equals("")) {
                    String newFunction;
                    if (mAdbEnabled) {
                        newFunction = UsbManager.addFunction(overrideFunctions.second,
                                UsbManager.USB_FUNCTION_ADB);
                    } else {
                        newFunction = overrideFunctions.second;
                    }
                    Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: "
                            + UsbDeviceManager.getPersistProp(false));
                    SystemProperties.set(UsbDeviceManager.getPersistProp(false),
                            newFunction);
                }
                return overrideFunctions.first;
            } else if (mAdbEnabled) {
                String newFunction = UsbManager.addFunction(UsbManager.USB_FUNCTION_NONE,
                        UsbManager.USB_FUNCTION_ADB);
                SystemProperties.set(UsbDeviceManager.getPersistProp(false),
                        newFunction);
            } else {
                SystemProperties.set(UsbDeviceManager.getPersistProp(false),
                        UsbManager.USB_FUNCTION_NONE);
            }
        }
        // return passed in functions as is.
        return usbFunctions;
    }

原来这个运营商的USB覆盖功能是针对非正常模式启动的情况,具体分析就不多说了,因为我们现在并不关心这种情况。

步,这里的条件肯定是成立的,至少目前来看mCurrentFunctionsnullmCurrentFunctionsAppliedfalse

那么,现在我们来好好看看这个USB功能是如何设置上的,代码片段如下


			// 4. 根据条件判断是否设置USB新功能
            if ((!functions.equals(oemFunctions) &&
                    (mCurrentOemFunctions == null ||
                            !mCurrentOemFunctions.equals(oemFunctions)))
                    || !mCurrentFunctions.equals(functions)
                    || !mCurrentFunctionsApplied
                    || forceRestart) {
                Slog.i(TAG, "Setting USB config to " + functions);
                mCurrentFunctions = functions;
                mCurrentOemFunctions = oemFunctions;
                mCurrentFunctionsApplied = false;

                // Kick the USB stack to close existing connections.
                // 4.1. 设置sys.usb.config的属性值,这里指关闭已存在的的USB链接
                setUsbConfig(UsbManager.USB_FUNCTION_NONE);

                // 用1秒钟检测sys.usb.stat属性是否等于UsbManager.USB_FUNCTION_NONE
                // 如果成功,代表前面的USB连接关闭成功,如果失败就直接返回
                if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
                    Slog.e(TAG, "Failed to kick USB config");
                    return false;
                }

                // Set the new USB configuration.
                // 4.2. 设置新的USB功能
                setUsbConfig(oemFunctions);

                // 4.3. 如果手机已经启动完毕,而且切换的功能中包含MTP/PTP,就发送广播
                if (mBootCompleted
                        && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
                        || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
                    // Start up dependent services.
                    updateUsbStateBroadcastIfNeeded(true);
                }

                // 用1秒钟检测sys.usb.stat属性是否等于oemFunctions
                // 如果成功,代表USB功能切换成功,如果失败,直接返回
                if (!waitForState(oemFunctions)) {
                    Slog.e(TAG, "Failed to switch USB config to " + functions);
                    return false;
                }

                mCurrentFunctionsApplied = true;
            }

纵观整体,我们可以发现setUsbConfig()waitForState()是关键,而且waitForState()方法决定了设置是否设置成功。

首先看下setUsbConfig()是如何设置新功能的

        private void setUsbConfig(String config) {
			// 设置sys.usb.config属性的值
            SystemProperties.set(USB_CONFIG_PROPERTY, config);
        }

很简单,就是设置sys.usb.config系统属性的值,这个属性我们在前面提到过,代表USB当前的设置。

然后再来看下waitForState()方法

        private boolean waitForState(String state) {
            // wait for the transition to complete.
            // give up after 1 second.
            String value = null;
            for (int i = 0; i < 20; i++) {
                // 读取sys.usb.state属性值
                value = SystemProperties.get(USB_STATE_PROPERTY);
                if (state.equals(value)) return true;
                SystemClock.sleep(50);
            }
            Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value);
            return false;
        }

原来是循环读取sys.usb.state属性值,然后与sys.usb.config属性值判断是否相等,从而决定是否设置成功,这与我们前面说的是一致的。

就这样完了吗?我们是不是感觉漏掉了什么细节?sys.usb.state是何时设置成sys.usb.config的值的? 其实这一步是在底层完成的。

由于我对底层的代码并不熟悉,因此我把项目中遇到的情况拿来这里对比分析下,当我们把USB功能设置为mtp, adb时候,下面代码就会做相应动作。

on property:sys.usb.config=mtp,adb && property:sys.usb.configfs=0
	# 先写0
    write /sys/class/android_usb/android0/enable 0
    # 写序列号
    write /sys/class/android_usb/android0/iSerial ${ro.serialno}
    # 写vid, pid
    write /sys/class/android_usb/android0/idVendor 05C6
    write /sys/class/android_usb/android0/idProduct 9039
    # 设置USB功能为mtp,adb
    write /sys/class/android_usb/android0/functions mtp,adb
    # 再写1启动功能
    write /sys/class/android_usb/android0/enable 1
    # 启动adb
    start adbd
    # 设置 sys.usb.state属性值为sys.usb.config的属性值
    setprop sys.usb.state ${sys.usb.config}

这段代码的顺序很重要,因为涉及要调用的函数。这段代码实际做了三件事

  • 启用mtp功能
  • 开启adbd进程
  • 设置系统属性sys.usb.state的值为sys.usb.config的值

注意最后一步,我们在前面提到过sys.usb.stateUSB的实际状态,sys.usb.configUSB的当前设置,这下你明白了吗?

底层USB功能的切换必然导致USB状态的改变,那么上层总该有个地方能知道这个改变吧?还记得UsbDeviceManager的内部类UsbHandler的构造函数中如下代码吗

mUEventObserver.startObserving(USB_STATE_MATCH);

mUEventObserver就是用来监听内核的uevent message的,从而监听USB状态的

    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) {
            	// 发送USB状态改变广播
                mHandler.updateState(state);
            } else if ("START".equals(accessory)) {
                if (DEBUG) Slog.d(TAG, "got accessory start");
                startAccessoryMode();
            }
        }
    };

当状态改变的时候,就会发送USB通知,如果手机还没有与电脑通过USB相连,那么这里也不会有USB通知。

USB连接情况分析

至此,我们已经把UsbService的整个启动流程分析完毕了,之前的分析都是假设手机没有与电脑相连。既然我们已经对UsbService的整个启动流程有了初步的了解,那么我们就来挑战分析下手机通过USB与电脑相连的情况。

那么我们该从哪里入手呢?当USB建立连接的时候,USB状态肯定会改变,上层哪个底层在检测这个状态呢?前面刚分析过,你应该还记得吧

    /*
     * Listens for uevent messages from the kernel to monitor the USB state
     */
    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) {
            	// 更新USB状态
                mHandler.updateState(state);
            } else if ("START".equals(accessory)) {
                if (DEBUG) Slog.d(TAG, "got accessory start");
                startAccessoryMode();
            }
        }
    };

OK,是时候刚一波正面了,我们来分析下更新USB状态的流程

        public void updateState(String state) {
            int connected, configured;

            if ("DISCONNECTED".equals(state)) {
                connected = 0;
                configured = 0;
            } else if ("CONNECTED".equals(state)) {
                connected = 1;
                configured = 0;
            } else if ("CONFIGURED".equals(state)) {
                connected = 1;
                configured = 1;
            } else {
                Slog.e(TAG, "unknown state " + state);
                return;
            }
            removeMessages(MSG_UPDATE_STATE);
            Message msg = Message.obtain(this, MSG_UPDATE_STATE);
            msg.arg1 = connected;
            msg.arg2 = configured;
            // debounce disconnects to avoid problems bringing up USB tethering
            sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
        }

当我们把手机通过USB连接到电脑时,会经历CONNECTEDCONFIGURED的状态改变,相应的参数也会改变,我们现在只分析CONFIGURED状态的情况。现在来看下如何处理MSG_UPDATE_STATE消息,

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_STATE:
                	// 1. 保存了USB状态
                	mConnected = (msg.arg1 == 1);
                	mConfigured = (msg.arg2 == 1);
					
					// 2. 更新下usb和adb通知
                    updateUsbNotification(false);
                    updateAdbNotification(false);
                    
                    // 3. 如果已经启动完毕,就发送USB状态广播
                    if (mBootCompleted) {
                        updateUsbStateBroadcastIfNeeded(false);
                    }
                    
                    // 3. USB的ACCESSORY功能相关操作
                    if (UsbManager.containsFunction(mCurrentFunctions,
                            UsbManager.USB_FUNCTION_ACCESSORY)) {
                        updateCurrentAccessory();
                    }
                    
                    // 4. 启动完毕,但是USB没有连接上
                    if (mBootCompleted) {
                        if (!mConnected) {
                            // restore defaults when USB is disconnected
                            // 重置USB功能为none,adb
                            setEnabledFunctions(null, !mAdbEnabled, false);
                        }
                        // 与USB的AUDIO和MIDI相关的更新
                        updateUsbFunctions();
                    } else {
                        mPendingBootBroadcast = true;
                    }
                    break;
                    
                // ...
            }
        }

步,保存这些参数,值都为true

步,发送USBADB通知,如下图所示

usb和adb的通知
步发送USB状态改变广播,因为手机已经通过USB与电脑相连,因此USB状态肯定改变了,那么自然就会发送USB状态改变广播,我们看下实现

        private void updateUsbStateBroadcastIfNeeded(boolean configChanged) {
            // send a sticky broadcast containing current USB state
            Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
                    | Intent.FLAG_RECEIVER_FOREGROUND);
            intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
            intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
            intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
            intent.putExtra(UsbManager.USB_DATA_UNLOCKED,
                    isUsbTransferAllowed() && mUsbDataUnlocked);
            intent.putExtra(UsbManager.USB_CONFIG_CHANGED, configChanged);

            if (mCurrentFunctions != null) {
                String[] functions = mCurrentFunctions.split(",");
                for (int i = 0; i < functions.length; i++) {
                    final String function = functions[i];
                    if (UsbManager.USB_FUNCTION_NONE.equals(function)) {
                        continue;
                    }
                    intent.putExtra(function, true);
                }
            }

            // send broadcast intent only if the USB state has changed
            // 如果usb状态没有改变并且配置也没有改变,就不发送广播
            if (!isUsbStateChanged(intent) && !configChanged) {
                if (DEBUG) {
                    Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras());
                }
                return;
            }

            if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
            mBroadcastedIntent = intent;
        }

那么,这个广播由谁来接收?跟MTP又有什么关系呢?这就是下一篇的内容了。

总结

本文对UsbService进行了一个整体性的分析,这为后面MTP的分析打下基础。 不过在本片文章中还附带了adb相关的东西,例如监听adb的改变,开关adb,如果有时间的话,我会单独开一篇文章来分析这个主题。

发布了50 篇原创文章 · 获赞 30 · 访问量 400万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 像素格子 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览