【BUG分析】手机启动时,adb打开较晚

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即时同步即可。
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值