Android版本:7.1.2
内核版本:3.18
要求:手机默认不开adb,只有手动打开时,以后每次开机才会打开adb,并且adb在system server启动之前打开。
控制adb是否打开和USB功能的主要是两个属性:persist.sys.usb.config 和 sys.usb.config。
sys.usb.config是一个临时的属性,每次关机后,都不存在了。但是,该属性主管usb功能,包括adb是否打开。该属性会设置为mtp,ptp等。
persist.sys.usb.config是一个persist属性,会存在磁盘中目录为/data/property/中。该属性的作用主要是保持上次关机前的adb功能,该属性不会设置为mtp,ptp等,但会设置为adb。
这两个属性关联的地方再system\core\rootdir\init.usb.rc中,代码如下:
# Used to set USB configuration at boot and to switch the configuration
# when changing the default configuration
on boot && property:persist.sys.usb.config=*
setprop sys.usb.config ${persist.sys.usb.config}
当开机时,发生trigger boot,将 sys.usb.config设置为persist.sys.usb.config。
按道理来说,当发生trigger boot时,这两个属性的值应该一样了。
我们设置adb打开与否,都会写入persist.sys.usb.config。
persist.sys.usb.config在很多地方都有赋值。例如,默认adb不开,在*.prop文件中(也可能是在python编译文件中),会设置persist.sys.usb.config=none。
*.prop中的属性是默认属性,会被后加载的相同属性覆盖。
加载上次关机前设置的persist属性是在 system\core\init\property_service.cpp中,代码如下:
static void load_persistent_properties() {
persistent_properties_loaded = 1;
std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(PERSISTENT_PROPERTY_DIR), closedir);
if (!dir) {
ERROR("Unable to open persistent property directory \"%s\": %s\n",
PERSISTENT_PROPERTY_DIR, strerror(errno));
return;
}
struct dirent* entry;
while ((entry = readdir(dir.get())) != NULL) {
if (strncmp("persist.", entry->d_name, strlen("persist."))) {
continue;
}
if (entry->d_type != DT_REG) {
continue;
}
// Open the file and read the property value.
int fd = openat(dirfd(dir.get()), entry->d_name, O_RDONLY | O_NOFOLLOW);
if (fd == -1) {
ERROR("Unable to open persistent property file \"%s\": %s\n",
entry->d_name, strerror(errno));
continue;
}
struct stat sb;
if (fstat(fd, &sb) == -1) {
ERROR("fstat on property file \"%s\" failed: %s\n", entry->d_name, strerror(errno));
close(fd);
continue;
}
// File must not be accessible to others, be owned by root/root, and
// not be a hard link to any other file.
if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0) || (sb.st_uid != 0) || (sb.st_gid != 0) ||
(sb.st_nlink != 1)) {
ERROR("skipping insecure property file %s (uid=%u gid=%u nlink=%u mode=%o)\n",
entry->d_name, (unsigned int)sb.st_uid, (unsigned int)sb.st_gid,
(unsigned int)sb.st_nlink, sb.st_mode);
close(fd);
continue;
}
char value[PROP_VALUE_MAX];
int length = read(fd, value, sizeof(value) - 1);
if (length >= 0) {
value[length] = 0;
property_set(entry->d_name, value);//设置属性
} else {
ERROR("Unable to read persistent property file %s: %s\n",
entry->d_name, strerror(errno));
}
close(fd);
}
}
trigger boot是在system\core\rootdir\init.rc中,代码如下:
on late-init
trigger early-fs
# Mount fstab in init.{$device}.rc by mount_all command. Optional parameter
# '--early' can be specified to skip entries with 'latemount'.
# /system and /vendor must be mounted by the end of the fs stage,
# while /data is optional.
trigger fs
trigger post-fs
# Load properties from /system/ + /factory after fs mount. Place
# this in another action so that the load will be scheduled after the prior
# issued fs triggers have completed.
trigger load_system_props_action
# Mount fstab in init.{$device}.rc by mount_all with '--late' parameter
# to only mount entries with 'latemount'. This is needed if '--early' is
# specified in the previous mount_all command on the fs stage.
# With /system mounted and properties form /system + /factory available,
# some services can be started.
trigger late-fs
# Now we can mount /data. File encryption requires keymaster to decrypt
# /data, which in turn can only be loaded when system properties are present.
trigger post-fs-data
# Load persist properties and override properties (if enabled) from /data.
trigger load_persist_props_action
# Remove a file to wake up anything waiting for firmware.
trigger firmware_mounts_complete
trigger early-boot
trigger boot
尽管trigger load_system_props_action在trigger boot之前,但是log发现,trigger boot却是在load_persistent_properties()函数之前,导致persist.sys.usb.config还未加载上次保存的值,就已经trigger boot了,这会使perisist.sys.usb.config和sys.usb.config的值不一致。直到框架设置(UsbDeviceManager.java),这必然不符合要求。代码如下:
private void setAdbEnabled(boolean enable) {
if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
if (enable != mAdbEnabled) {
mAdbEnabled = enable;
String oldFunctions = mCurrentFunctions;
// Persist the adb setting
String newFunction = applyAdbFunction(SystemProperties.get(
USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE));
SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunction);//设置persist属性
// Remove mtp from the config if file transfer is not enabled
if (oldFunctions.equals(UsbManager.USB_FUNCTION_MTP) &&
!mUsbDataUnlocked && enable) {
oldFunctions = UsbManager.USB_FUNCTION_NONE;
}
setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked);
updateAdbNotification();
}
if (mDebuggingManager != null) {
mDebuggingManager.setAdbEnabled(mAdbEnabled);
}
}
private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
if (functions == null || applyAdbFunction(functions)
.equals(UsbManager.USB_FUNCTION_NONE)) {
functions = getDefaultFunctions();
}
functions = applyAdbFunction(functions);
functions = applyOemOverrideFunction(functions);
if (!mCurrentFunctions.equals(functions) || !mCurrentFunctionsApplied
|| forceRestart) {
Slog.i(TAG, "Setting USB config to " + functions);
mCurrentFunctions = functions;
mCurrentFunctionsApplied = false;
// Kick the USB stack to close existing connections.
setUsbConfig(UsbManager.USB_FUNCTION_NONE);
// Set the new USB configuration.
if (!setUsbConfig(functions)) {//设置非perisist属性
Slog.e(TAG, "Failed to switch USB config to " + functions);
return false;
}
mCurrentFunctionsApplied = true;
}
return true;
}
修改方法:去掉init.usb.rc中的on boot,(Android M就没有on boot这个东西)。当然也可以有别的改法,只要sys.usb.config与persist.sys.usb.config即时同步即可。