user版本不能使用adb问题

最近碰到一个问题user版本不能使用adb问题。这个问题涉及到adbd和Usb相关的service代码。


一、adbd

我们先看看adbd对user版本的代码:

首先在adb_main函数中有如下代码,当ro.adb.secure属性为0的时候auth_required 变量为false。这个时候一般是debug版本(不会设置这个属性或者这个属性为0)

    if (ALLOW_ADBD_NO_AUTH && property_get_bool("ro.adb.secure", 0) == 0) {
        auth_required = false;
    }

然后我们再来看adb.cpp中handle_packet函数,来处理pc侧发过来的数据包,当是debug版本时,直接会调用send_connect和pc侧连接,而当user版本时会调用send_auth_request验证。

    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
            /* XXX verify version, etc */
        if(t->connection_state != CS_OFFLINE) {
            t->connection_state = CS_OFFLINE;
            handle_offline(t);
            LOG("%s: A_CNXN handle_offline\n", __FUNCTION__);
        }

        parse_banner(reinterpret_cast<const char*>(p->data), t);

        if (HOST || !auth_required) {//HOST侧或者debug版本
            handle_online(t);
            LOG("%s: A_CNXN handle_online\n", __FUNCTION__);
            if (!HOST) {
                send_connect(t);
                LOG("%s: A_CNXN send_connect\n", __FUNCTION__);
            }
        } else {
            send_auth_request(t);
        }
        break;
我们来看下send_auth_request函数,发送了command是A_AUTH,arg0 = ADB_AUTH_TOKEN

void send_auth_request(atransport *t)
{
    D("Calling send_auth_request\n");
    apacket *p;
    int ret;

    ret = adb_auth_generate_token(t->token, sizeof(t->token));
    if (ret != sizeof(t->token)) {
        D("Error generating token ret=%d\n", ret);
        return;
    }

    p = get_apacket();
    memcpy(p->data, t->token, ret);
    p->msg.command = A_AUTH;
    p->msg.arg0 = ADB_AUTH_TOKEN;
    p->msg.data_length = ret;
    send_packet(p, t);
}


再来看ADB_AUTH_TOKEN的处理,正常会调用send_auth_publickey函数

    case A_AUTH:
        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
            t->connection_state = CS_UNAUTHORIZED;
            t->key = adb_auth_nextkey(t->key);
            if (t->key) {
                send_auth_response(p->data, p->msg.data_length, t);
            } else {
                /* No more private keys to try, send the public key */
                send_auth_publickey(t);
            }
        } 

send_auth_publickey如下,会发送ADB_AUTH_RSAPUBLICKEY

void send_auth_publickey(atransport *t)
{
    D("Calling send_auth_publickey\n");
    apacket *p = get_apacket();
    int ret;

    ret = adb_auth_get_userkey(p->data, sizeof(p->data));
    if (!ret) {
        D("Failed to get user public key\n");
        put_apacket(p);
        return;
    }

    p->msg.command = A_AUTH;
    p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
    p->msg.data_length = ret;
    send_packet(p, t);
}

处理ADB_AUTH_RSAPUBLICKEY会调用adb_auth_confirm_key函数

        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
            adb_auth_confirm_key(p->data, p->msg.data_length, t);
        }

adb_auth_confirm_key会通过socket往上层发送key,然后会触发adb_auth_event事件

void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
{
    char msg[MAX_PAYLOAD];
    int ret;

    if (!usb_transport) {
        usb_transport = t;
        add_transport_disconnect(t, &usb_disconnect);
    }

    if (framework_fd < 0) {
        D("Client not connected\n");
        needs_retry = true;
        return;
    }

    if (key[len - 1] != '\0') {
        D("Key must be a null-terminated string\n");
        return;
    }

    ret = snprintf(msg, sizeof(msg), "PK%s", key);//key数据
    if (ret >= (signed)sizeof(msg)) {
        D("Key too long. ret=%d", ret);
        return;
    }
    D("Sending '%s'\n", msg);

    ret = unix_write(framework_fd, msg, ret);//往上层socket写数据
    if (ret < 0) {
        D("Failed to write PK, errno=%d\n", errno);
        return;
    }

    fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t);//注册事件
    fdevent_add(&t->auth_fde, FDE_READ);
}
我们先来看下adb_auth_event的注册事件,如果有数据最终会调用adb_auth_verified函数

static void adb_auth_event(int fd, unsigned events, void *data)
{
    char response[2];
    int ret;

    if (events & FDE_READ) {
        ret = unix_read(fd, response, sizeof(response));
        if (ret <= 0) {
            D("Framework disconnect\n");
            if (usb_transport)
                fdevent_remove(&usb_transport->auth_fde);
            framework_fd = -1;
        }
        else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
            if (usb_transport)
                adb_auth_verified(usb_transport);
        }
    }
}

而在adb_auth_verified函数中会和pc侧连接。

void adb_auth_verified(atransport *t)
{
    handle_online(t);
    send_connect(t);
}


二、Usb相关service

我们再来看下framework层

在UsbDeviceManager的构造函数有如下代码,当ro.adb.secure为true时(user版本)会创建UsbDebuggingManager对象

        boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
        boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
        if (secureAdbEnabled && !dataEncrypted) {
            mDebuggingManager = new UsbDebuggingManager(context);
        }
而当调用UsbDeviceManager的setAdbEnabled函数,最终会调用mDebuggingManager.setAdbEnabled函数
        private void setAdbEnabled(boolean enable) {
            if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
            if (enable != mAdbEnabled) {
                mAdbEnabled = enable;
                // Due to the persist.sys.usb.config property trigger, changing adb state requires
                // persisting default function
                if(!mCurrentFunctions.equals(UsbManager.USB_FUNCTION_CHARGING)){
                    String oldFunctions = getDefaultFunctions();
                    String newFunctions = applyAdbFunction(oldFunctions);
                    if (!oldFunctions.equals(newFunctions)) {
                        setUsbPersistConfig(newFunctions);
                    }
                    // After persisting them use the lock-down aware function set
                    setEnabledFunctions(mCurrentFunctions, false);
                    updateAdbNotification();
                }
            }
            if (mDebuggingManager != null) {
                mDebuggingManager.setAdbEnabled(mAdbEnabled);
            }
        }
UsbDeviceManager会检测Settings的数据库Settings.Global.ADB_ENABLED值,发生变化会调用MSG_ENABLE_ADB消息,在这个消息中就会调用setAdbEnabled函数
    private class AdbSettingsObserver extends ContentObserver {
        public 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);
        }
    }
我们再来看UsbDebuggingManager的setAdbEnabled函数,会发送一个MESSAGE_ADB_ENABLED消息
    public void setAdbEnabled(boolean enabled) {
        mHandler.sendEmptyMessage(enabled ? UsbDebuggingHandler.MESSAGE_ADB_ENABLED
                                          : UsbDebuggingHandler.MESSAGE_ADB_DISABLED);
    }
这个消息的处理,会启动UsbDebuggingThread线程

                case MESSAGE_ADB_ENABLED:
                    if (mAdbEnabled)
                        break;

                    mAdbEnabled = true;

                    mThread = new UsbDebuggingThread();
                    mThread.start();

                    break;

UsbDebuggingThread线程的run函数如下,先会调用openSocketLocked函数和adbd的socket进行连接,然后调用listenToSocket函数读取adbd socket的数据

        public void run() {
            if (DEBUG) Slog.d(TAG, "Entering thread");
            while (true) {
                synchronized (this) {
                    if (mStopped) {
                        if (DEBUG) Slog.d(TAG, "Exiting thread");
                        return;
                    }
                    try {
                        openSocketLocked();
                    } catch (Exception e) {
                        /* Don't loop too fast if adbd dies, before init restarts it */
                        SystemClock.sleep(1000);
                    }
                }
                try {
                    listenToSocket();
                } catch (Exception e) {
                    /* Don't loop too fast if adbd dies, before init restarts it */
                    SystemClock.sleep(1000);
                }
            }
        }

openSocketLocked函数就是建立一个socket和adbd的socket连接

        private void openSocketLocked() throws IOException {
            try {
                LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
                        LocalSocketAddress.Namespace.RESERVED);
                mInputStream = null;

                if (DEBUG) Slog.d(TAG, "Creating socket");
                mSocket = new LocalSocket();
                mSocket.connect(address);

                mOutputStream = mSocket.getOutputStream();
                mInputStream = mSocket.getInputStream();
            } catch (IOException ioe) {
                closeSocketLocked();
                throw ioe;
            }
        }

listenToSocket函数,就是获取adbd 发过来的key值,然后发送MESSAGE_ADB_CONFIRM消息

        private void listenToSocket() throws IOException {
            try {
                byte[] buffer = new byte[BUFFER_SIZE];
                while (true) {
                    int count = mInputStream.read(buffer);
                    if (count < 0) {
                        break;
                    }

                    if (buffer[0] == 'P' && buffer[1] == 'K') {
                        String key = new String(Arrays.copyOfRange(buffer, 2, count));
                        Slog.d(TAG, "Received public key: " + key);
                        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
                        msg.obj = key;
                        mHandler.sendMessage(msg);
                    } else {
                        Slog.e(TAG, "Wrong message: "
                                + (new String(Arrays.copyOfRange(buffer, 0, 2))));
                        break;
                    }
                }
            } finally {
                synchronized (this) {
                    closeSocketLocked();
                }
            }
        }

这个消息处理,如果没有问题会调用startConfirmation函数,这个函数最后会启动UsbDebuggingActivity,这个Activity就是是否允许这台pc和手机连接等。

    private void startConfirmation(String key, String fingerprints) {
        int currentUserId = ActivityManager.getCurrentUser();
        UserHandle userHandle =
                UserManager.get(mContext).getUserInfo(currentUserId).getUserHandle();
        String componentString;
        if (currentUserId == UserHandle.USER_OWNER) {
            componentString = Resources.getSystem().getString(
                    com.android.internal.R.string.config_customAdbPublicKeyConfirmationComponent);
        } else {
            // If the current foreground user is not the primary user we send a different
            // notification specific to secondary users.
            componentString = Resources.getSystem().getString(
                    R.string.config_customAdbPublicKeyConfirmationSecondaryUserComponent);
        }
        ComponentName componentName = ComponentName.unflattenFromString(componentString);
        if (startConfirmationActivity(componentName, userHandle, key, fingerprints)
                || startConfirmationService(componentName, userHandle, key, fingerprints)) {
            return;
        }
        Slog.e(TAG, "unable to start customAdbPublicKeyConfirmation[SecondaryUser]Component "
                + componentString + " as an Activity or a Service");
    }

而在UsbDebuggingActivity最终调用点击允许,会调用UsbService的allowUsbDebugging函数,然后调用UsbDevicemanager的allowUsbDebugging函数,再到UsbDebuggingManager的allowUsbDebugging函数

    @Override
    public void onClick(DialogInterface dialog, int which) {
        boolean allow = (which == AlertDialog.BUTTON_POSITIVE);
        boolean alwaysAllow = allow && mAlwaysAllow.isChecked();
        try {
            IBinder b = ServiceManager.getService(USB_SERVICE);
            IUsbManager service = IUsbManager.Stub.asInterface(b);
            if (allow) {
                service.allowUsbDebugging(alwaysAllow, mKey);
            } else {
                service.denyUsbDebugging();
            }
        } catch (Exception e) {
            Log.e(TAG, "Unable to notify Usb service", e);
        }
        finish();
    }

我们来看下UsbDebuggingManager的allowUsbDebugging函数,就是发送一个MESSAGE_ADB_ALLOW消息

    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_ALLOW);
        msg.arg1 = alwaysAllow ? 1 : 0;
        msg.obj = publicKey;
        mHandler.sendMessage(msg);
    }

我们来看下MESSAGE_ADB_ALLOW消息的处理,先调用writeKey,把key保存在文件中,然后调用thread的sendRespose给adbd发送ok消息。

                case MESSAGE_ADB_ALLOW: {
                    String key = (String)msg.obj;
                    String fingerprints = getFingerprints(key);

                    if (!fingerprints.equals(mFingerprints)) {
                        Slog.e(TAG, "Fingerprints do not match. Got "
                                + fingerprints + ", expected " + mFingerprints);
                        break;
                    }

                    if (msg.arg1 == 1) {
                        writeKey(key);
                    }

                    if (mThread != null) {
                        mThread.sendResponse("OK");
                    }
                    break;
                }

我们先来看writeKey函数,先调用getUserKeyFile来获取文件,然后写入。

    private void writeKey(String key) {
        try {
            File keyFile = getUserKeyFile();

            if (keyFile == null) {
                return;
            }

            if (!keyFile.exists()) {
                keyFile.createNewFile();
                FileUtils.setPermissions(keyFile.toString(),
                    FileUtils.S_IRUSR | FileUtils.S_IWUSR |
                    FileUtils.S_IRGRP, -1, -1);
            }

            FileOutputStream fo = new FileOutputStream(keyFile, true);
            fo.write(key.getBytes());
            fo.write('\n');
            fo.close();
        }
        catch (IOException ex) {
            Slog.e(TAG, "Error writing key:" + ex);
        }
    }

getUserKeyFile函数最终生成data/misc/adb/adb_keys文件

    private File getUserKeyFile() {
        File dataDir = Environment.getDataDirectory();
        File adbDir = new File(dataDir, ADB_DIRECTORY);

        if (!adbDir.exists()) {
            Slog.e(TAG, "ADB data directory does not exist");
            return null;
        }

        return new File(adbDir, ADB_KEYS_FILE);
    }

然后我们再来看UsbDebuggingThread的sendResponse函数,就是给adbd发送一个ok消息。

        void sendResponse(String msg) {
            synchronized (this) {
                if (!mStopped && mOutputStream != null) {
                    try {
                        mOutputStream.write(msg.getBytes());
                    }
                    catch (IOException ex) {
                        Slog.e(TAG, "Failed to write response:", ex);
                    }
                }
            }
        }


三、adbd的socket

我们先来看初始化,初始化当adbd socket有数据来(就是连接),调用adb_auth_listener函数

void adbd_auth_init(void) {
    int fd = android_get_control_socket("adbd");
    if (fd == -1) {
        D("Failed to get adbd socket\n");
        return;
    }

    if (listen(fd, 4) == -1) {
        D("Failed to listen on '%d'\n", fd);
        return;
    }

    fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
    fdevent_add(&listener_fde, FDE_READ);
}
adb_auth_listener函数就是accept usb service过来的socket,然后把其fd保存在framework_fd中。
static void adb_auth_listener(int fd, unsigned events, void *data)
{
    struct sockaddr addr;
    socklen_t alen;
    int s;

    alen = sizeof(addr);

    s = adb_socket_accept(fd, &addr, &alen);
    if (s < 0) {
        D("Failed to accept: errno=%d\n", errno);
        return;
    }

    framework_fd = s;

    if (needs_retry) {
        needs_retry = false;
        send_auth_request(usb_transport);
    }
}
当有key要发送给UsbDebuggingManager时,就调用adb_auth_confirm_key函数

void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
{
    char msg[MAX_PAYLOAD];
    int ret;

    if (!usb_transport) {
        usb_transport = t;
        add_transport_disconnect(t, &usb_disconnect);
    }

    if (framework_fd < 0) {
        D("Client not connected\n");
        needs_retry = true;
        return;
    }

    if (key[len - 1] != '\0') {
        D("Key must be a null-terminated string\n");
        return;
    }

    ret = snprintf(msg, sizeof(msg), "PK%s", key);
    if (ret >= (signed)sizeof(msg)) {
        D("Key too long. ret=%d", ret);
        return;
    }
    D("Sending '%s'\n", msg);

    ret = unix_write(framework_fd, msg, ret);//发送到UsbDebuggingManager
    if (ret < 0) {
        D("Failed to write PK, errno=%d\n", errno);
        return;
    }

    fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t);//注册UsbDebuggingManager的socket fd事件
    fdevent_add(&t->auth_fde, FDE_READ);
}

而且当UsbDebuggingManager的socket发来数据,我们会调用adb_auth_event函数。

这个函数最终读到UsbDebuggingManager的socket发来的消息是“OK”,就会调用adb_auth_verified函数,而这个函数最终会连接pc侧。

static void adb_auth_event(int fd, unsigned events, void *data)
{
    char response[2];
    int ret;

    if (events & FDE_READ) {
        ret = unix_read(fd, response, sizeof(response));
        if (ret <= 0) {
            D("Framework disconnect\n");
            if (usb_transport)
                fdevent_remove(&usb_transport->auth_fde);
            framework_fd = -1;
        }
        else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
            if (usb_transport)
                adb_auth_verified(usb_transport);
        }
    }
}


四、问题解决

这样原理我们很清楚裂,问题也就迎刃而解了,我在手机收直接dumpsys usb,发现没有UsbDebuggingManager的dump数据,那只有一种可能,没有UsbDebuggingManager对象,也就是ro.adb.secure为false,按理说user版本这个属性为true。

这样我们就只用看相关编译的mk文件,有没有在user版本的时候,定义这个属性为1.发现没有,就修改device.mk如下,

ifeq ($(TARGET_BUILD_VARIANT),user)
PRODUCT_DEFAULT_PROPERTY_OVERRIDES+= \
     ro.adb.secure=1
endif
这样问题就搞定了。



  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值