Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
b595b54
Add platform-independent tablet input core
LightChainr Jul 16, 2026
a2d69ce
Define tablet input ownership and interaction session APIs
LightChainr Jul 16, 2026
e636e4e
Implement deterministic tablet input routing
LightChainr Jul 16, 2026
e0931e6
Test tablet input ownership and abort invariants
LightChainr Jul 16, 2026
2fed9b7
Define versioned input probe JSONL contract
LightChainr Jul 16, 2026
06d15f0
Add input probe log validator and summary tool
LightChainr Jul 16, 2026
b2bd456
Test input probe log validation
LightChainr Jul 16, 2026
2a74702
Document Android target dependency tiers
LightChainr Jul 16, 2026
88c940d
Add Android sysroot preflight checks
LightChainr Jul 16, 2026
f2acfaa
Record immutable upstream research candidates
LightChainr Jul 16, 2026
8927114
Add upstream candidate verification tool
LightChainr Jul 16, 2026
f1a9bfc
Add evidence-based pre-engineering assessment
LightChainr Jul 16, 2026
b084841
Expose pre-engineering validation commands
LightChainr Jul 16, 2026
1134162
Add cross-platform pre-engineering CI
LightChainr Jul 16, 2026
ba4a3a4
Add upstream source reachability verification
LightChainr Jul 16, 2026
234ba3f
Capture input events as immutable primitive snapshots
LightChainr Jul 16, 2026
406eb44
Move input probe JSON encoding and writes off the UI thread
LightChainr Jul 16, 2026
c276723
Record device and input capability metadata per probe session
LightChainr Jul 16, 2026
f907999
Refactor input probe to asynchronous schema-versioned capture
LightChainr Jul 16, 2026
d5ee3d9
Bound probe data loss and periodic flushing
LightChainr Jul 16, 2026
67fac68
Document trustworthy input probe capture workflow
LightChainr Jul 16, 2026
d7064f4
Strengthen input probe build validation
LightChainr Jul 16, 2026
fbdc398
Preserve Gradle diagnostics on probe build failures
LightChainr Jul 16, 2026
cac3532
Separate probe and native Android SDK requirements
LightChainr Jul 16, 2026
f3462b8
Align Mac bootstrap guidance with locked SDK packages
LightChainr Jul 16, 2026
820057a
Expand Mac environment and SDK diagnostics
LightChainr Jul 16, 2026
61ed7b1
Document tablet input core integration contract
LightChainr Jul 16, 2026
0d79251
Define explicit pre-engineering sub-gates
LightChainr Jul 16, 2026
10aa24b
Surface executable pre-engineering checks
LightChainr Jul 16, 2026
3450a4a
Read display identity from the hosting view
LightChainr Jul 16, 2026
4f8b69b
Pass the hosting display ID into captured events
LightChainr Jul 16, 2026
108e39f
Add deterministic upstream candidate materializer
LightChainr Jul 16, 2026
e394006
Add machine-readable upstream architecture audit
LightChainr Jul 16, 2026
02a88c3
Audit upstream source assumptions in CI
LightChainr Jul 16, 2026
0a97152
Propagate session metadata JSON errors
LightChainr Jul 16, 2026
0769429
Define reproducible Xiaomi device input protocol
LightChainr Jul 16, 2026
7df98ac
Add P1 device test notes template
LightChainr Jul 16, 2026
43cebb2
Add JVM tests for input probe persistence
LightChainr Jul 16, 2026
e748753
Test asynchronous probe writer and drop reporting
LightChainr Jul 16, 2026
d8af686
Distinguish canceled pointers and pointer ID reuse
LightChainr Jul 16, 2026
56116ee
Require the complete input probe event contract
LightChainr Jul 16, 2026
cd521b5
Align analyzer with the complete probe event schema
LightChainr Jul 16, 2026
e40691b
Test complete event schema and canceled pointer analysis
LightChainr Jul 16, 2026
41dc398
Embed probe source revision in session metadata
LightChainr Jul 16, 2026
a0bb0a9
Persist the probe build revision in session logs
LightChainr Jul 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions .github/workflows/input-probe-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,28 @@ name: Input probe build
on:
workflow_dispatch:
push:
branches:
- main
- "agent/**"
paths:
- "android/input-probe/**"
- "schemas/input-probe-v1.schema.json"
- "tools/analyze_input_probe.py"
- ".github/workflows/input-probe-build.yml"
pull_request:
paths:
- "android/input-probe/**"
- "schemas/input-probe-v1.schema.json"
- "tools/analyze_input_probe.py"
- ".github/workflows/input-probe-build.yml"

permissions:
contents: read

concurrency:
group: input-probe-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -35,9 +49,34 @@ jobs:
with:
gradle-version: "9.4.1"

- name: Build debug APK
- name: Lint, test and build debug APK
working-directory: android/input-probe
run: gradle :app:assembleDebug --stacktrace
shell: bash
run: |
set -o pipefail
gradle \
:app:lintDebug \
:app:testDebugUnitTest \
:app:assembleDebug \
--stacktrace \
--warning-mode all \
2>&1 | tee ../../input-probe-gradle.log

- name: Verify APK output
run: |
test -s android/input-probe/app/build/outputs/apk/debug/app-debug.apk
unzip -l android/input-probe/app/build/outputs/apk/debug/app-debug.apk | tee input-probe-apk-contents.txt
grep -q 'classes.dex' input-probe-apk-contents.txt

- uses: actions/upload-artifact@v4
if: always()
with:
name: input-probe-reports
path: |
input-probe-gradle.log
android/input-probe/app/build/reports/
input-probe-apk-contents.txt
if-no-files-found: warn

- uses: actions/upload-artifact@v4
with:
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/pre-engineering.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Pre-engineering checks

on:
push:
branches:
- main
- "agent/**"
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: pre-engineering-${{ github.ref }}
cancel-in-progress: true

jobs:
host-checks:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Ensure Ninja is available
run: |
if ! command -v ninja >/dev/null 2>&1; then
python3 -m pip install ninja
fi

- name: Validate manifests and candidate SHAs
run: |
bash scripts/dev lock-check
bash scripts/dev candidates-check
python3 - <<'PY'
import json, tomllib
from pathlib import Path
json.loads(Path('schemas/input-probe-v1.schema.json').read_text(encoding='utf-8'))
with Path('deps/android-target-dependencies.toml').open('rb') as handle:
manifest = tomllib.load(handle)
assert manifest['format_version'] == 1
assert manifest['required_pkg_config']['packages']
PY

- name: Run Python analyzer tests
run: python3 -m unittest discover -s tools/tests -p 'test_*.py' -v

- name: Build and test C++ tablet input core
run: bash scripts/dev core-test

- name: Validate repository tracking policy
run: bash scripts/dev repo-check
42 changes: 42 additions & 0 deletions .github/workflows/source-candidates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Source candidate verification

on:
workflow_dispatch:
schedule:
- cron: "23 4 * * 1"
pull_request:
paths:
- sources.candidates.toml
- scripts/verify-source-candidates.py
- .github/workflows/source-candidates.yml

permissions:
contents: read

concurrency:
group: source-candidates-${{ github.ref }}
cancel-in-progress: true

jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Fetch immutable SHAs from official remotes
run: |
bash scripts/dev candidates-check --network \
--json-out source-candidates-report.json

- uses: actions/upload-artifact@v4
if: always()
with:
name: source-candidates-report
path: source-candidates-report.json
if-no-files-found: warn
50 changes: 50 additions & 0 deletions .github/workflows/upstream-contract-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Upstream contract audit

on:
workflow_dispatch:
schedule:
- cron: "41 4 * * 1"
pull_request:
paths:
- sources.candidates.toml
- scripts/materialize-source-candidates.py
- scripts/audit-upstream-contracts.py
- .github/workflows/upstream-contract-audit.yml

permissions:
contents: read

concurrency:
group: upstream-contract-${{ github.ref }}
cancel-in-progress: true

jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Materialize immutable upstream candidates
run: |
python3 scripts/materialize-source-candidates.py \
--output .out/upstream \
--json-out upstream-materialization.json

- name: Audit architecture contracts
run: |
python3 scripts/audit-upstream-contracts.py \
--workspace .out/upstream \
--json-out upstream-contract-audit.json

- uses: actions/upload-artifact@v4
if: always()
with:
name: upstream-contract-audit
path: |
upstream-materialization.json
upstream-contract-audit.json
if-no-files-found: warn
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

## 当前状态

本仓库处于 **P0:框架初始化**,并已加入 P1 输入探针工程
本仓库处于 **P0:前期工程基线**。P0 被拆成仓库/CI、输入事务核心、源码与依赖边界、可信输入采集四个子关卡;全部通过后才进入小米真机事件采集

已定义的首个编辑闭环:

Expand Down Expand Up @@ -47,21 +47,24 @@ SVG 文档模型与序列化

## 文档

- [前期工程评估](docs/pre-engineering-assessment.md)
- [完整迁移方案](docs/migration-plan.zh-CN.md)
- [开源项目参考评估](docs/open-source-reference-assessment.zh-CN.md)
- [分阶段技术关卡](docs/stage-gates.md)
- [Mac 操作基线](docs/build-macos.md)
- [架构边界](docs/architecture.md)
- [输入核心契约](core/tablet-input/README.md)

## 从 Mac 开始

```sh
git clone https://github.com/LightChainr/InkscapeAndroid.git
cd InkscapeAndroid
bash scripts/dev doctor
bash scripts/dev test
```

`doctor` 只检查环境,不修改系统。
`doctor` 只检查环境,不修改系统。`test` 运行锁文件、候选 SHA、Python analyzer、C++ input core 和仓库策略检查。

## P1 输入探针

Expand All @@ -73,7 +76,28 @@ gradle :app:assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
```

GitHub Actions 工作流 `Input probe build` 会使用 JDK 17、AGP 9.2.0 和 Gradle 9.4.1 构建 debug APK。探针日志写入应用私有目录的 `input-probe/events.jsonl`。
探针采用有界后台写盘,队列溢出会产生显式 `drop` 记录。日志写入应用私有目录:

```text
files/input-probe/events.jsonl
```

导出并验证:

```sh
PACKAGE=io.github.lightchainr.inkscapeandroid.inputprobe
adb exec-out run-as "$PACKAGE" \
cat files/input-probe/events.jsonl > events.jsonl
bash scripts/dev probe-analyze events.jsonl
```

存在 schema 错误或 dropped records 的日志不能作为完整事件序列证据。

## 研究版本

- `sources.candidates.toml`:可从官方远端取得的研究候选 SHA;
- `sources.lock.toml`:只有兼容构建和证据包完成后才能标记 `validated`;
- `deps/android-target-dependencies.toml`:目标 sysroot 的依赖分层和硬性约束。

## 开发原则

Expand Down
88 changes: 82 additions & 6 deletions android/input-probe/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,93 @@
# Android Input Probe

P1 的独立 Gradle 应用。只记录 `MotionEvent`,不依赖 GTK 或 Inkscape。
P1 的独立 Android 应用。它只记录 `MotionEvent`,不依赖 GTK 或 Inkscape。

最低日志字段:event time、arrival time、action、pointer ID、tool type、source、坐标、pressure、tilt、orientation、distance、buttons、flags、history size、device ID。
## 设计目标

输出为 JSON Lines,并附设备型号、系统版本和应用 build ID。探针不得推断手掌或触控笔语义,原始事件和解释报告分开保存。
探针用于回答三个问题:

必须覆盖:
1. 小米焦点触控笔向第三方应用实际暴露哪些标准 Android 字段;
2. pen、finger、palm 和 canceled pointer 的事件顺序是什么;
3. GTK adapter 后续必须保留哪些原始语义。

探针不负责推断“这是手掌”或“这是点击”。原始日志与解释报告必须分开保存。

## 数据路径

```text
MotionEvent callback
↓ 复制 primitive snapshot
有界队列(8192 records)
后台线程 JSON 编码与 UTF-8 JSONL 写盘
```

若队列溢出,日志会写入 `recordType=drop`,并记录丢失数量。存在 drop 的日志不能用于采样率或完整序列结论。

数据契约:[`schemas/input-probe-v1.schema.json`](../../schemas/input-probe-v1.schema.json)。

每次启动写入一条 session 记录,包括:

- 应用版本和 build type;
- 设备型号、Android/HyperOS fingerprint;
- 屏幕密度与刷新率;
- 已连接 input devices;
- 每个 input device 的 motion ranges。

每个 event sample 至少包括:

- current/historical 标记;
- event time、capture monotonic time、capture uptime;
- action、action pointer、pointer ID/index/count;
- tool type、source、device ID、display ID;
- pressure、tilt、orientation、distance;
- size、touch/tool major/minor;
- button、meta、flags、classification;
- raw/local coordinates 和 precision。

`System.nanoTime()` 与 MotionEvent event time 不应直接相减,除非先确认时钟基准。分析器默认只对明确可比较的数据做统计。

## 构建

CI 使用 JDK 17、AGP 9.2.0、Gradle 9.4.1 和 Android 36 SDK:

```sh
cd android/input-probe
gradle :app:assembleDebug --stacktrace
```

安装:

```sh
adb install -r app/build/outputs/apk/debug/app-debug.apk
adb shell am start \
-n io.github.lightchainr.inkscapeandroid.inputprobe/.MainActivity
```

## 导出

```sh
PACKAGE=io.github.lightchainr.inkscapeandroid.inputprobe
adb exec-out run-as "$PACKAGE" \
cat files/input-probe/events.jsonl > events.jsonl
```

验证:

```sh
bash scripts/dev probe-analyze events.jsonl
```

## 必测场景

- 轻点、慢拖、快拖;
- hover、压力和侧键;
- 一指、两指、两指变一指;
- pen 与手掌同时接触;
- pen 先落下后放手掌;
- finger 先落下后落笔;
- 双指过程中落笔;
- `ACTION_CANCEL`;
- Android 13+ `FLAG_CANCELED`;
- 切后台、系统面板、锁屏和 Surface 变化。
- 切后台、系统面板、锁屏和窗口失焦。

每个场景开始前记录操作说明和时间,原始 JSONL 不做人工编辑。
Loading
Loading