# QSJNIC Service 多用户配置说明

## 问题现象
Radio Demo、OTA Demo 等应用点击按钮后响应极慢或无响应，根本原因是：

**多个 `com.qsjnic.mcu.service` 进程同时竞争同一个串口 `/dev/ttyS7`**。

串口只能被一个进程独占读写，多个 service 同时打开时，命令和 ACK 互相干扰，导致 `sendAndWaitAck` 超时（1500ms 超时返回 ERR_TIMEOUT）。

## 根本原因

当前车机镜像中，`com.qsjnic.mcu.service` 和 `com.qsjnic.mcu.service.dev` 在 **u0 和 u10 两个用户下都安装了**，且都有 `BOOT_COMPLETED` 开机自启。重启后会出现：

- `com.qsjnic.mcu.service`（u0，PID xxxx）
- `com.qsjnic.mcu.service`（u10，PID xxxx）
- `com.qsjnic.mcu.service.dev`（u10，PID xxxx）

三个进程同时打开 `/dev/ttyS7`，串口竞争。

此外，当 u10 下的 App（如 radio demo）通过 `McuClient.bindService()` 绑定 service 时，由于使用了 `BIND_AUTO_CREATE`，会自动拉起 u10 下的 service，进一步加剧竞争。

## 解决方案

### 1. 修改 Service 代码（青手负责）

在 `BootCompletedReceiver.onReceive()` 中增加主用户过滤，**只在 u0（主用户）下自启 service**：

```java
@Override
public void onReceive(Context context, Intent intent) {
    String action = intent != null ? intent.getAction() : null;
    Log.i(TAG, "onReceive action=" + action);

    // 只在主用户（u0）下启动，避免多用户串口竞争
    if (android.os.UserHandle.myUserId() != 0) {
        Log.i(TAG, "Skip non-primary user, uid=" + android.os.UserHandle.myUserId());
        return;
    }

    if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
        Intent svc = new Intent(context, QsMcuSystemService.class);
        context.startForegroundService(svc);
        Log.i(TAG, "startService(QsMcuSystemService) issued");
    }
}
```

同时建议在 `QsMcuSystemService.onCreate()` 中也加一层保护：

```java
@Override
public void onCreate() {
    super.onCreate();
    if (android.os.UserHandle.myUserId() != 0) {
        Log.w(TAG, "Service should only run in primary user, stopping");
        stopSelf();
        return;
    }
    // ... 原有初始化逻辑
}
```

### 2. 镜像配置要求（yi ren负责）

| 包名 | 用户范围 | 说明 |
|------|---------|------|
| `com.qsjnic.mcu.service` | **仅 u0** | 正式版 MCU Service，唯一串口持有者 |
| `com.qsjnic.demo.radio` | **仅 u0** | Radio Demo，绑定 u0 的 service |
| `com.qsjnic.demo.ota` | **仅 u0** | OTA Demo，绑定 u0 的 service |
| `com.qsjnic.mcu.service.dev` | **不进正式镜像** | 开发版 service，正式镜像中删除 |

**具体要求**：

1. **`com.qsjnic.mcu.service` 不应在 u10 用户下安装**
   - 如果是通过 `android_build` 的 `Android.bp`/`Android.mk` 预装，请确保不推送到 u10 用户空间
   - 或预装后通过 `pm uninstall --user 10 com.qsjnic.mcu.service` 在首次启动脚本中清理

2. **`com.qsjnic.mcu.service.dev` 不要预装到正式镜像**
   - 该包是开发调试用途，正式镜像中只保留 `com.qsjnic.mcu.service`

3. **qsjnic 相关 App 的 Launcher 默认绑定到 u0**
   - 确保 radio demo、ota demo 等从 launcher 启动时默认在主用户（u0）下运行
   - 如果车机当前活跃用户在 u10，建议引导用户切回 u0，或限制这些 App 只能在 u0 启动

4. **不要给 u10 用户配置 qsjnic service 的开机自启**
   - 即使 service 预装在 u10，也应禁用其 `BOOT_COMPLETED` receiver：
     ```bash
     pm disable-user --user 10 com.qsjnic.mcu.service/.BootCompletedReceiver
     ```

## 验证方法

镜像刷完后，执行以下命令验证：

```bash
# 查看 qsjnic 进程，应该只有 1 个 service
adb shell ps -A | grep qsjnic
# 期望输出只有：
# system  xxxx  com.qsjnic.mcu.service

# 查看 u10 下是否还有 service
adb shell pm list packages --user 10 | grep mcu.service
# 期望输出为空（或只有 demo，没有 service）
```


