1.setting中改变USB状态
在setting中关于改变USB状态的有两个重要的类:UsbSettings和UsbSettingsExts。UsbSettings实际上是一个PreferenceFragment,它负责展示界面;UsbSettingsExts负责保存USB状态的。
UsbSettings.java
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// Don't allow any changes to take effect as the USB host will be disconnected, killing
// the monkeys
if (Utils.isMonkeyRunning()) {
return true;
}
// If this user is disallowed from using USB, don't handle their attempts to change the
// setting.
UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
if (um.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
return true;
}
String function = mUsbExts.getFunction(preference);
boolean makeDefault = mUsbExts.isMakeDefault(preference);
mUsbManager.setCurrentFunction(function, makeDefault);//改变USB状态
updateToggles(function);
mUsbExts.setNeedUpdate(false);
return true;
}
UsbSettingsExts.java
public String getFunction(Preference preference) {
String function = FUNCTION_NONE;
if (preference == mMtp && mMtp.isChecked()) {
function = UsbManager.USB_FUNCTION_MTP;
} else if (preference == mPtp && mPtp.isChecked()) {
function = UsbManager.USB_FUNCTION_PTP;
} else if (preference == mUms && mUms.isChecked()) {
function = UsbManager.USB_FUNCTION_MASS_STORAGE;
} else if (preference == mCharge && mCharge.isChecked()) {
function = UsbManager.USB_FUNCTION_CHARGING_ONLY;
} else if (preference == mBicr && mBicr.isChecked()) {
function = UsbManager.USB_FUNCTION_BICR;
}
return function;
}
下面来看下USB的管理类UsbManager.java
public void setCurrentFunction(String function, boolean makeDefault) {
try {
mService.setCurrentFunction(function, makeDefault);//调用usbservice,改变USB状态
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in setCurrentFunction", e);
}
}
UsbService.java
@Override
public void setCurrentFunction(String function, boolean makeDefault) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
// If attempt to change USB function while file transfer is restricted, ensure that
// the current function is set to "none", and return.
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
if (mDeviceManager != null) mDeviceManager.setCurrentFunctions("none", false);
return;
}
if (mDeviceManager != null) {
mDeviceManager.setCurrentFunctions(function, makeDefault);
} else {
throw new IllegalStateException("USB device mode not supported");
}
}
UsbDeviceManager.java
public void setCurrentFunctions(String functions, boolean makeDefault) {
if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ") default: " + makeDefault);
mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, makeDefault);
}
case MSG_SET_CURRENT_FUNCTIONS:
String functions = (String)msg.obj;
boolean makeDefault = (msg.arg1 == 1);
mSettingUsbCharging = false;
mSettingUsbBicr = false;
/* In BICR evo, it's hard to confirm that the current disconnect is caused by switching usb function or unplugging usb cable*/
/* So add a flag to know it*/
mIsUserSwitch = true;
if (functions != null && functions.equals(UsbManager.USB_FUNCTION_CHARGING_ONLY)) {
mSettingUsbCharging = true;
mCurrentFunctions = removeFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP);
mCurrentFunctions = removeFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
updateUsbState();
Slog.d(TAG, "handleMessage - MSG_SET_CURRENT_FUNCTION - CHARGING_ONLY - makeDefault: " + makeDefault);
} else if (functions != null && functions.equals(UsbManager.USB_FUNCTION_BICR)) {
mSettingUsbBicr = true;
Slog.d(TAG, "handleMessage - MSG_SET_CURRENT_FUNCTION - BICR - makeDefault: " + makeDefault);
} else if (functions == null && mDefaultFunctions.equals(UsbManager.USB_FUNCTION_CHARGING_ONLY)) {
functions = mDefaultFunctions;
mSettingUsbCharging = true;
makeDefault = true;
updateUsbState();
Slog.d(TAG, "handleMessage - MSG_SET_CURRENT_FUNCTION - [Tethering Off] USB_FUNCTION_CHARGING_ONLY - makeDefault: " + makeDefault);
}
setEnabledFunctions(functions, makeDefault);
mIsUserSwitch = false;
//ALPS00428998
if(mMtpAskDisconnect) mMtpAskDisconnect = false;
//ALPS00428998
Slog.d(TAG, "handleMessage - MSG_SET_CURRENT_FUNCTION - functions: " + functions);
break;
private void setEnabledFunctions(String functions, boolean makeDefault) {
if (DEBUG) {
Slog.d(TAG, "setEnabledFunctions - functions: " + functions);
Slog.d(TAG, "setEnabledFunctions - mDefaultFunctions: " + mDefaultFunctions);
Slog.d(TAG, "setEnabledFunctions - mCurrentFunctions: " + mCurrentFunctions);
Slog.d(TAG, "setEnabledFunctions - mSettingFunction: " + mSettingFunction);
}
if (mCurrentFunctions.equals(UsbManager.USB_FUNCTION_CHARGING_ONLY)) {
Slog.d(TAG, "setEnabledFunctions - [Disable USB Charging]");
SystemProperties.set("sys.usb.charging","no");
}
if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_BICR)) {
if (mIsUsbBicrEvo) {
Slog.w(TAG, "====mIsPcKnowMe:" + mIsPcKnowMe + ", mIsBicrSet:" + mIsBicrSet + ", mHwDisconnected:" + mHwDisconnected);
if (mIsBicrSet && mHwDisconnected) {
Slog.d(TAG, "Do not set sys.usb.bicr=no again!!!");
} else {
Slog.d(TAG, "setEnabledFunctions1 - [Disable USB BICR]");
SystemProperties.set("sys.usb.bicr","no");//设置为光驱
}
} else {
Slog.d(TAG, "setEnabledFunctions2 - [Disable USB BICR]");
SystemProperties.set("sys.usb.bicr","no");
}
}
if (mIsUsbBicrEvo && functions != null) {
if( containsFunction(functions, UsbManager.USB_FUNCTION_RNDIS) || containsFunction(functions, UsbManager.USB_FUNCTION_EEM) ) {
mDefaultFunctions = mSettingFunction;
}
}
// Do not update persystent.sys.usb.config if the device is booted up
// with OEM specific mode.
if (functions != null && makeDefault && !needsOemUsbOverride() && !mIsUsbBicrEvo) {
if(bEvdoDtViaSupport == true) {
//VIA-START VIA USB
if(Settings.Secure.getInt(mContentResolver,
Settings.Secure.ADB_ENABLED, 0) > 0){
mAdbEnabled = true;
updateAdbNotification();
}
//VIA-END VIA USB
}
mSettingFunction = functions;
if (mAdbEnabled && !mSettingUsbCharging) {
functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
} else {
functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
}
String acm_idx = SystemProperties.get("sys.usb.acm_idx", "");
Slog.d(TAG, "sys.usb.acm_idx=" + acm_idx + ",mAcmPortIdx=" + mAcmPortIdx);
if ((mAcmEnabled || ((acm_idx!=null) && !acm_idx.isEmpty()) ||
((mAcmPortIdx!=null) && !mAcmPortIdx.isEmpty())) &&
!mSettingUsbCharging && !mSettingUsbBicr) {
int port_num = 0;
String port_str = "";
if(!acm_idx.isEmpty()) {
port_num = validPortNum(acm_idx);
if(port_num > 0 ) {
port_str = acm_idx;
mAcmPortIdx = acm_idx;
}
} else if(!mAcmPortIdx.isEmpty()) {
port_num = validPortNum(mAcmPortIdx);
if(port_num > 0 )
port_str = mAcmPortIdx;
}
Slog.d(TAG, "port_num=" + port_num);
if (port_num > 0) {
Slog.d(TAG, "Write port_str=" + port_str);
writeFile(ACM_PORT_INDEX_PATH, port_str);
}
/*Add ACM or Dual ACM at the tail. Even with ADB.*/
functions = removeFunction(functions, UsbManager.USB_FUNCTION_ACM);
functions = removeFunction(functions, UsbManager.USB_FUNCTION_DUAL_ACM);
String tmp = ( (port_num == 2) ? UsbManager.USB_FUNCTION_DUAL_ACM : UsbManager.USB_FUNCTION_ACM);
functions = addFunction(functions, tmp);
//Slog.d(TAG, "set persist.sys.port_index=" + port_str);
/*Keep the port info. We need it when reboot.*/
//SystemProperties.set("persist.sys.port_index", port_str);
} else {
functions = removeFunction(functions, UsbManager.USB_FUNCTION_ACM);
functions = removeFunction(functions, UsbManager.USB_FUNCTION_DUAL_ACM);
SystemProperties.set("persist.sys.port_index", "");
}
Slog.d(TAG, "setEnabledFunctions - functions: " + functions);
if (!mDefaultFunctions.equals(functions) || containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_BICR) || containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
if (!setUsbConfig("none")) {
Slog.e(TAG, "Failed to disable USB");
// revert to previous configuration if we fail
setUsbConfig(mCurrentFunctions);
return;
}
// setting this property will also change the current USB state
// via a property trigger
SystemProperties.set("persist.sys.usb.config", functions);
if (mSettingFunction.equals(UsbManager.USB_FUNCTION_CHARGING_ONLY)) {
if (mAdbEnabled) {
SystemProperties.set("persist.service.adb.enable", "1");
} else {
SystemProperties.set("persist.service.adb.enable", "0");
}
} else {
SystemProperties.set("persist.service.adb.enable", "");
}
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);
}
} else {
//VIA-START VIA USB
if(bEvdoDtViaSupport == true) {
if(mDefaultFunctions.equals(functions) &&
(mCurrentFunctions.contains(UsbManager.USB_FUNCTION_VIA_CDROM)
||mCurrentFunctions.contains(Bypass.USB_FUNCTION_BYPASS))){
Slog.i(TAG, "reset DefaultFunctions!");
if (!setUsbConfig("none")) {
Slog.e(TAG, "Failed to disable USB");
// revert to previous configuration if we fail
setUsbConfig(mCurrentFunctions);
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);
}
}
}
//VIA-END VIA USB
}
} else {
if (functions == null) {
functions = mDefaultFunctions;
if(bEvdoDtViaSupport == true){
mUsbSetBypassWithTether=false ;
}
}
//VIA-START VIA USB
if(bEvdoDtViaSupport == true) {
//adb can't be open with bypass and via cdrom
if(Settings.Secure.getInt(mContentResolver,
Settings.Secure.ADB_ENABLED, 0) > 0){
mAdbEnabled = true;
updateAdbNotification();
}
}
//VIA-END VIA USB
// Override with bootmode specific usb mode if needed
functions = processOemUsbOverride(functions);
mSettingFunction = functions;
if(bEvdoDtViaSupport == true){
if ((containsFunction(functions, UsbManager.USB_FUNCTION_RNDIS) || containsFunction(functions, UsbManager.USB_FUNCTION_EEM)) && mUsbSetBypassWithTether){
functions = addFunction(functions, Bypass.USB_FUNCTION_BYPASS);
Slog.d(TAG, "add the bypass functions to tethering : " + functions);
}
}
if (mIsUsbBicrEvo && !mIsPcKnowMe && !mSettingUsbCharging) {
functions = UsbManager.USB_FUNCTION_BICR;
mSettingFunction = functions;
}
if (mAdbEnabled && !mSettingUsbCharging) {
functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
} else {
functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
}
String acm_idx = SystemProperties.get("sys.usb.acm_idx", "");
Slog.d(TAG, "sys.usb.acm_idx=" + acm_idx);
if ((mAcmEnabled || ((acm_idx!=null) && !acm_idx.isEmpty()) ||
((mAcmPortIdx!=null) && !mAcmPortIdx.isEmpty())) &&
!mSettingUsbCharging && !mSettingUsbBicr) {
int port_num = 0;
String port_str = "";
if(!acm_idx.isEmpty()) {
port_num = validPortNum(acm_idx);
if(port_num > 0 ) {
port_str = acm_idx;
mAcmPortIdx = acm_idx;
}
} else if(!mAcmPortIdx.isEmpty()) {
port_num = validPortNum(mAcmPortIdx);
if(port_num > 0 )
port_str = mAcmPortIdx;
}
Slog.d(TAG, "port_num=" + port_num);
if (port_num > 0) {
Slog.d(TAG, "Write port_str=" + port_str);
writeFile(ACM_PORT_INDEX_PATH, port_str);
}
/*Add ACM or Dual ACM at the tail. Even with ADB.*/
functions = removeFunction(functions, UsbManager.USB_FUNCTION_ACM);
functions = removeFunction(functions, UsbManager.USB_FUNCTION_DUAL_ACM);
String tmp = ( (port_num == 2) ? UsbManager.USB_FUNCTION_DUAL_ACM : UsbManager.USB_FUNCTION_ACM);
functions = addFunction(functions, tmp);
} else {
functions = removeFunction(functions, UsbManager.USB_FUNCTION_ACM);
functions = removeFunction(functions, UsbManager.USB_FUNCTION_DUAL_ACM);
}
Slog.d(TAG, "else setEnabledFunctions, functions: " + functions + ", mCurrentFunctions: " + mCurrentFunctions);
if (!mCurrentFunctions.equals(functions) || containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_BICR) || (mIsUsbBicrEvo && !mIsPcKnowMe) || mMtpAskDisconnect) {
if (mIsUsbBicrEvo) {
Slog.w(TAG, "====mIsPcKnowMe:" + mIsPcKnowMe + ", mIsBicrSet:" + mIsBicrSet + ", mHwDisconnected:" + mHwDisconnected);
if (mIsBicrSet && !mIsPcKnowMe && mHwDisconnected && mCurrentFunctions.equals(functions) && containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_BICR)) {
Slog.e(TAG, "Do not do setUsbConfig() again!!!");
return;
} else {
mIsBicrSet = true;
}
}
if (!setUsbConfig("none")) {
Slog.e(TAG, "Failed to disable USB");
// revert to previous configuration if we fail
setUsbConfig(mCurrentFunctions);
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);
}
}
}
/* reset this value after trigger setconfig, i.e. one time JOB */
if(bEvdoDtViaSupport == true){
mUsbSetBypassWithTether=false ;
}
}
下面我们来看下init.usb.rc
on property:sys.usb.config=none
stop adbd
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/bDeviceClass 0
setprop sys.usb.state ${sys.usb.config}
# adb only USB configuration
# This is the fallback configuration if the
# USB manager fails to set a standard configuration
on property:sys.usb.config=adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18d1
write /sys/class/android_usb/android0/idProduct 4EE7
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
start adbd
setprop sys.usb.state ${sys.usb.config}
# USB accessory configuration
on property:sys.usb.config=accessory
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18d1
write /sys/class/android_usb/android0/idProduct 2d00
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
setprop sys.usb.state ${sys.usb.config}
# USB accessory configuration, with adb
on property:sys.usb.config=accessory,adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18d1
write /sys/class/android_usb/android0/idProduct 2d01
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
start adbd
setprop sys.usb.state ${sys.usb.config}
# audio accessory configuration
on property:sys.usb.config=audio_source
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18d1
write /sys/class/android_usb/android0/idProduct 2d02
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
setprop sys.usb.state ${sys.usb.config}
# audio accessory configuration, with adb
on property:sys.usb.config=audio_source,adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18d1
write /sys/class/android_usb/android0/idProduct 2d03
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
start adbd
setprop sys.usb.state ${sys.usb.config}
# USB and audio accessory configuration
on property:sys.usb.config=accessory,audio_source
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18d1
write /sys/class/android_usb/android0/idProduct 2d04
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
setprop sys.usb.state ${sys.usb.config}
# USB and audio accessory configuration, with adb
on property:sys.usb.config=accessory,audio_source,adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18d1
write /sys/class/android_usb/android0/idProduct 2d05
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
start adbd
setprop sys.usb.state ${sys.usb.config}
# Used to set USB configuration at boot and to switch the configuration
# when changing the default configuration
on property:persist.sys.usb.config=*
setprop sys.usb.config ${persist.sys.usb.config}
从上面可以看出,设置persist.sys.usb.config后sys.usb,config跟着改变,然后向节点写入数据改变状态