打开 “USB 调试” 开关流程

在开发者模式中打开 “USB调试” 开关,程序会调用如下代码:

public void onAdbDialogConfirmed() {
        writeAdbSetting(true);
    }

其中 writeAdbSetting 在 com.android.settingslib.development.AbstractEnableAdbPreferenceController 类中定义:

protected void writeAdbSetting(boolean enabled) {
        Settings.Global.putInt(mContext.getContentResolver(),
                Settings.Global.ADB_ENABLED, enabled ? ADB_SETTING_ON : ADB_SETTING_OFF);
        notifyStateChanged();
    }

修改 Settings.Global.ADB_ENABLED 设置项,并发送广播:

private void notifyStateChanged() {
        LocalBroadcastManager.getInstance(mContext)
                .sendBroadcast(new Intent(ACTION_ENABLE_ADB_STATE_CHANGED));
    }

在 com.android.settings.development.DevelopmentSettingsDashboardFragment 类中处理了该广播:

private void registerReceivers() {
        LocalBroadcastManager.getInstance(getContext())
                .registerReceiver(mEnableAdbReceiver, new IntentFilter(
                        AdbPreferenceController.ACTION_ENABLE_ADB_STATE_CHANGED));

        final IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED);
        getActivity().registerReceiver(mBluetoothA2dpReceiver, filter);
    }

广播接收器:

private final BroadcastReceiver mEnableAdbReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            for (AbstractPreferenceController controller : mPreferenceControllers) {
                if (controller instanceof AdbOnChangeListener) {
                    ((AdbOnChangeListener) controller).onAdbSettingChanged();
                }
            }
        }
    };

上面的广播接收器主要处理 view 的状态,指示调试模式已经打开。

重点看 Settings.Global.ADB_ENABLED 设置项控制的代码,在 com.android.server.adb.AdbService 类中会监测该设置项变化:

mContentResolver.registerContentObserver(
                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
                        false, new AdbSettingsObserver());

使用 AdbSettingsObserver 对 Settings.Global.ADB_ENABLED 设置项进行观察:

private class AdbSettingsObserver extends ContentObserver {
        AdbSettingsObserver() {
            super(null);
        }

        @Override
        public void onChange(boolean selfChange) {
            boolean enable = (Settings.Global.getInt(mContentResolver,
                    Settings.Global.ADB_ENABLED, 0) > 0);
            mHandler.sendMessage(MSG_ENABLE_ADB, enable);
        }
    }

当设置项发生改变时,通过 mHandler 发送 MSG_ENABLE_ADB 消息,消息处理如下:

@Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_ENABLE_ADB:
                    setAdbEnabled(msg.arg1 == 1);
                    break;
                case MSG_BOOT_COMPLETED:
                    if (mDebuggingManager != null) {
                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
                    }
                    break;
            }
        }

通过 setAdbEnabled 来设置 ADB 使能。

private void setAdbEnabled(boolean enable) {
        if (DEBUG) Slog.d(TAG, "setAdbEnabled(" + enable + "), mAdbEnabled=" + mAdbEnabled);

        if (enable == mAdbEnabled) {
            return;
        }
        mAdbEnabled = enable;

        for (IAdbTransport transport : mTransports.values()) {
            try {
                transport.onAdbEnabled(enable);
            } catch (RemoteException e) {
                Slog.w(TAG, "Unable to send onAdbEnabled to transport " + transport.toString());
            }
        }

        if (mDebuggingManager != null) {
            mDebuggingManager.setAdbEnabled(enable);
        }
    }

mTransports 是集合类型,通过内部类 AdbManagerInternalImpl 的 registerTransport 函数增加新的元素。在 com.android.server.usb.UsbDeviceManager 类中注册了 Transport。

LocalServices.getService(
                            AdbManagerInternal.class).registerTransport(new AdbTransport(this));

那么 AdbTransport 的 onAdbEnabled 函数会被调用,此函数发送了 MSG_ENABLE_ADB 消息。本地函数 setAdbEnabled 处理了该消息:

private void setAdbEnabled(boolean enable) {
            if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);

            if (enable) {
                setSystemProperty(USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_ADB);
            } else {
                setSystemProperty(USB_PERSISTENT_CONFIG_PROPERTY, "");
            }

            setEnabledFunctions(mCurrentFunctions, true);
            updateAdbNotification(false);
        }

其中 USB_PERSISTENT_CONFIG_PROPERTY 定义如下:

protected static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";

该属性会持久化保存到文件系统中。紧接着调用 setEnabledFunctions 函数:

@Override
        protected void setEnabledFunctions(long usbFunctions, boolean forceRestart) {
            ...
            if (trySetEnabledFunctions(usbFunctions, forceRestart)) {
                return;
            }
            ...
        }

多次调用 trySetEnabledFunctions 来配置 USB 的功能:

private boolean trySetEnabledFunctions(long usbFunctions, boolean forceRestart) {
            ...
            if ((!functions.equals(oemFunctions)
                    && !mCurrentOemFunctions.equals(oemFunctions))
                    || !mCurrentFunctionsStr.equals(functions)
                    || !mCurrentFunctionsApplied
                    || forceRestart) {
                ...
                setUsbConfig(UsbManager.USB_FUNCTION_NONE);

                if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
                    Slog.e(TAG, "Failed to kick USB config");
                    return false;
                }

                setUsbConfig(oemFunctions);
                ...
            }
            return true;
        }

最关键的函数 setUsbConfig :

private void setUsbConfig(String config) {
            if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
            /**
             * set the new configuration
             * we always set it due to b/23631400, where adbd was getting killed
             * and not restarted due to property timeouts on some devices
             */
            setSystemProperty(USB_CONFIG_PROPERTY, config);
        }

其中 USB_CONFIG_PROPERTY 定义为:

private static final String USB_CONFIG_PROPERTY = "sys.usb.config";

在 init.msm.usb.configfs.rc 中会监测此属性,根据属性切换不同的 usb 模式:

on property:sys.usb.config=diag,adb,serial_cdev && property:sys.usb.configfs=1
    start adbd

如果 sys.usb.config 属性等于 diag,adb,serial_cdev 并且 sys.usb.configfs 为 1,则启动 adbd 服务。其中 sys.usb.configfs 为 1 表示 kernel 启用的 configfs,这个属性在 device/qcom/common/rootdir/etc/init.qcom.usb.sh 中初始化:

# check configfs is mounted or not
if [ -d /config/usb_gadget ]; then
	# Chip-serial is used for unique MSM identification in Product string
	msm_serial=`cat /sys/devices/soc0/serial_number`;
	msm_serial_hex=`printf %08X $msm_serial`
	machine_type=`cat /sys/devices/soc0/machine`
	product_string="$machine_type-$soc_hwplatform _SN:$msm_serial_hex"
	echo "$product_string" > /config/usb_gadget/g1/strings/0x409/product

	# ADB requires valid iSerialNumber; if ro.serialno is missing, use dummy
	serialnumber=`cat /config/usb_gadget/g1/strings/0x409/serialnumber 2> /dev/null`
	if [ "$serialnumber" == "" ]; then
		serialno=1234567
		echo $serialno > /config/usb_gadget/g1/strings/0x409/serialnumber
	fi
	setprop vendor.usb.configfs 1
fi

判断 configfs 是否已经挂载,如果已经挂载,则设置 vendor.usb.configfs 属性为 1。

总结:

1、开发者模式中打开 “USB 调试” 开关,对应的 Settings.Global.ADB_ENABLED 设置项会被修改。

2、AdbService 监测设置项,触发设置 adb 使能逻辑。

3、UsbDeviceManager 响应 adb 使能逻辑,修改 persist.sys.usb.config 和 sys.usb.config 的值,其中 persist.sys.usb.config 属性用于开机恢复上一次 usb 设置,修改 sys.usb.config 属性,会直接触发 init.rc 中的 action,触发对 usb 进行配置(configfs)、启动 adbd 等动作。

开机 USB 默认模式

AdbService 在 system_server 中启动,它的构造函数包含以下代码:

private AdbService(Context context) {
        ...
        mHandler = new AdbHandler(FgThread.get().getLooper());

        LocalServices.addService(AdbManagerInternal.class, new AdbManagerInternalImpl());
    }

这里 new 了一个 AdbHandler 对象。在看 AdbHandler 的构造函数,

AdbHandler(Looper looper) {
            super(looper);
            try {
                /*
                 * Use the normal bootmode persistent prop to maintain state of adb across
                 * all boot modes.
                 */
                mAdbEnabled = containsFunction(
                        SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, ""),
                        UsbManager.USB_FUNCTION_ADB);

                // register observer to listen for settings changes
                mContentResolver.registerContentObserver(
                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
                        false, new AdbSettingsObserver());
            } catch (Exception e) {
                Slog.e(TAG, "Error initializing AdbHandler", e);
            }
        }

首先判断 persist.sys.usb.config 属性的值,是否包含 “adb” 字段,如果包含则将 mAdbEnabled 设置为 true。AMS 启动后,会调用所有系统服务的 systemReady 函数:

public void systemReady() {
        if (DEBUG) Slog.d(TAG, "systemReady");

        // make sure the ADB_ENABLED setting value matches the current state
        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.");
        }
    }

这里会将 mAdbEnabled 的值,设置到 Settings.Global.ADB_ENABLED 设置项,之后会执行打开 “USB调试” 开关流程。persist.sys.usb.config 保存的是上一次开机最后一次 setUsbConfig 的值,默认情况下会恢复上一次的 usb 状态。

高通进行了定制化,在 init.qcom.usb.rc 中有以下配置:

on property:persist.vendor.usb.config=*
    setprop persist.sys.usb.config ${persist.vendor.usb.config}

persist.vendor.usb.config 的值在 init.qcom.usb.sh 设置:

#
# Override USB default composition
#
# If USB persist config not set, set default configuration
if [ "$(getprop persist.vendor.usb.config)" == "" -a \
	"$(getprop init.svc.vendor.usb-gadget-hal-1-0)" != "running" ]; then
    if [ "$esoc_name" != "" ]; then
	  setprop persist.vendor.usb.config diag,diag_mdm,qdss,qdss_mdm,serial_cdev,dpl,rmnet,adb
    else
	  case "$(getprop ro.baseband)" in
	      "apq")
	          setprop persist.vendor.usb.config diag,adb
	      ;;
	      *)
	      case "$soc_hwplatform" in
	          "Dragon" | "SBC")
	              setprop persist.vendor.usb.config diag,adb
	          ;;
                  *)
		  case "$soc_machine" in
		    "SA")
			if [ "$product" == "gvmq" ]; then
				setprop persist.vendor.usb.config adb
			else
				setprop persist.vendor.usb.config diag,adb
			fi
		    ;;
		    *)
	            case "$target" in
	              "msm8996")
	                  setprop persist.vendor.usb.config diag,serial_cdev,serial_tty,rmnet_ipa,mass_storage,adb
		      ;;
	              "msm8909")
		          setprop persist.vendor.usb.config diag,serial_smd,rmnet_qti_bam,adb
		      ;;
	              "msm8937")
			    if [ -d /config/usb_gadget ]; then
				       setprop persist.vendor.usb.config diag,serial_cdev,rmnet,dpl,adb
			    else
			               case "$soc_id" in
				               "313" | "320")
				                  setprop persist.vendor.usb.config diag,serial_smd,rmnet_ipa,adb
				               ;;
				               *)
				                  setprop persist.vendor.usb.config diag,serial_smd,rmnet_qti_bam,adb
				               ;;
			               esac
			    fi
		      ;;
	              "msm8953")
			      if [ -d /config/usb_gadget ]; then
				      setprop persist.vendor.usb.config diag,serial_cdev,rmnet,dpl,adb
			      else
				      setprop persist.vendor.usb.config diag,serial_smd,rmnet_ipa,adb
			      fi
		      ;;
	              "msm8998" | "sdm660" | "apq8098_latv")
		          setprop persist.vendor.usb.config diag,serial_cdev,rmnet,adb
		      ;;
	              "sdm845" | "sdm710")
		          setprop persist.vendor.usb.config diag,adb,serial_cdev
		      ;;
	              "msmnile" | "sm6150" | "trinket" | "lito" | "atoll" | "bengal")
			  setprop persist.vendor.usb.config diag,serial_cdev,rmnet,dpl,qdss
		      ;;
	              *)
		          setprop persist.vendor.usb.config diag,adb
		      ;;
                    esac
		    ;;
		  esac
	          ;;
	      esac
	      ;;
	  esac
      fi
fi

因此每次开机都会还原成默认设置。