项目地址

目标

首先解释一下为什么会有这个需求:

在全自动化管理中,对于 adb 的依赖程度是非常高的。然而,一般来说我们将设备管理逻辑放在比较高的层级来解决:

但显而易见的,由应用来管控 adb 命令实际上是非常软性的(很可能会因为疏忽而影响到其他设备),并没有硬性隔离设备。软件操作的边界不明显将很容易导致管理的越界与混乱。在 jenkins 构建中官方推荐用 lockable resource 来管理资源而不是流水线中用代码进行管理已经说明了很多问题。

然而在日常开发中,使用场景远不局限于 jenkins。那么,有没有一种更加通用的方案?答案就是lockadb

像 adb 一样操作

在命令行中,直接用 ladb 替代 adb 。

lockadb 是 adb 的超集,保留了所有的 adb 功能。理论上所有 adb 支持的功能都可以无缝切换到 ladb。

防冲突机制

lockadb 最关键的特性就是从 adb 层面避免了设备操作冲突。

连入一个设备123456F,我们先让该设备忙碌 20 秒:

ladb -s 123456F shell sleep 20

这样做之后,该设备将被标记为 BUSY 状态。此时你如果想操作它是被禁止的:

ladb -s 123456F shell echo hello

Traceback (most recent call last):
  File "C:\Python37\Scripts\ladb-script.py", line 11, in <module>
    load_entry_point('lockadb', 'console_scripts', 'ladb')()
  File "f:\lockadb\lockadb\client.py", line 106, in main
    LockAdbRunner.run(command)
  File "f:\lockadb\lockadb\client.py", line 95, in run
    with lock_device(device_id):
  File "c:\python37\lib\contextlib.py", line 112, in __enter__
    return next(self.gen)
  File "f:\lockadb\lockadb\client.py", line 39, in lock_device
    assert acquire_device(device_id), 'device {} is busy'.format(device_id)
AssertionError: device 123456F is busy

主动锁定

除了自动模式,你也可以手动给设备加锁,更加自由地管理设备。

# 上锁
ladb acquire 123456F
# 解锁
ladb release 123456F

在你上锁之后,除了主动释放设备,该设备将一直保持在 BUSY 状态。

python API

除了命令行的模式,你也可以直接调用 python API 来管理设备。

from lockadb.client import LockAdbRunner, acquire_device, release_device


DEVICE_ID = '123456F'

acquire_result = acquire_device(DEVICE_ID)
print('acquire result is: {}'.format(acquire_result))
LockAdbRunner.run(['devices'])

# ...

release_result = release_device(DEVICE_ID)
print('release result is: {}'.format(release_result))
LockAdbRunner.run(['devices'])

设计

使用 C/S 架构,S 端启动常驻服务器用于设备的管理,通过 API 提供给 C 端使用。

提供两种形式的 CLI 用法:

Bug 与建议

这个项目是一个个人想法的实践,不一定是最好的解决方案。欢迎交流 :)


↙↙↙阅读原文可查看相关链接,并与作者交流