← Docs hub

DeviceAgent / SoC Domain Map

이 문서는 Cloud A2A와 온디바이스 브릿지가 실제 기기 실행으로 내려갈 때, DeviceAgent 내부의 어떤 도메인이 실행 권한을 가져야 하는지 정리한다.

핵심 결론은 단순하다.

DeviceAgent / SoC Domain Map

TaskManager 자체를 SoC 실행 오케스트레이션 기능 범주로 자세히 보려면 SoC TaskManager Execution Subsystem을 먼저 본다.

1. 왜 이 지도가 필요한가

복합명령 예시는 아래처럼 보인다.

거실로 가서 청정하고 안방으로 이동해줘

Cloud A2A 관점에서는 2~3개의 ODL step으로 계획할 수 있다.

{
  "steps": [
    {"route": "ODL", "purpose": "거실 이동"},
    {"route": "ODL", "purpose": "거실 청정"},
    {"route": "ODL", "purpose": "안방 이동"}
  ]
}

하지만 실제 실행 시점에는 아래 조건들이 계속 바뀐다.

따라서 Cloud가 처음에 모든 실행 조건을 확정하는 구조가 아니라, DeviceAgent가 각 task 실행 직전에 도메인 매니저를 통해 다시 확인해야 한다.

2. 계층별 책임

계층 책임 하지 말아야 할 일
Cloud A2A Planner route family, multi-step plan, step dependency, replan 판단 기기 내부 상태를 추측해서 강제 실행
Cloud Runtime ODL step을 device_task_requests로 변환, 정상 event는 저장만 하고 replan event만 판단 모든 PROGRESS/COMPLETED마다 LLM 재호출
On-device Bridge Cloud request를 DeviceAgent method/token/task 형태로 변환, 순차 실행, event relay 기존 음성 명령 안전 조건 우회
DeviceAgent TaskManager submitTask, submitWorkflow, queue, timeout, cancel, event, reason code 관리 도메인별 실행 가능 조건을 자체 추측으로 대체
DeviceAgent Domain Managers 이동/청정/맵/스케줄/상태의 실제 조건 판단과 실행 Cloud plan 전체를 재해석
MCU/AMR/Wrapper 실제 모터, 팬, 센서, 설정 제어 사용자 의도 판단

3. DeviceAgent 핵심 도메인

3.1 task/

역할:

주요 근거:

파일 근거
TaskManager.java METHOD_SUBMIT_TASK, METHOD_SUBMIT_WORKFLOW, METHOD_GET_DEVICE_PLANNING_CONTEXT, METHOD_CLASSIFY_INGRESS를 정의한다.
TaskManager.java submitTask(...)에서 enabled, validation, caller policy, state condition, resource policy, command 생성, execution mode를 처리한다.
TaskManager.java submitWorkflow(...)에서 subTasks를 순차 실행하고 WORKFLOW_STEP_STARTED, WORKFLOW_STEP_COMPLETED event를 발생시킨다.
TaskReasonContract.java PATH_BLOCKED, ROOM_NOT_FOUND, LOW_BATTERY, STATE_CONDITION_FAILED 등을 Cloud가 이해 가능한 reason으로 정규화한다.
DevicePlanningContextProvider.java 계획 전 snapshot으로 battery, map, location, cleaning, movement, task_manager, capabilities를 만든다.

설계상 의미:

3.2 cleaning/

역할:

주요 근거:

파일 근거
AirCleaningManager.java start(), stop(), pause(), resume()를 통해 팬 제어와 callback을 처리한다.
CleaningTransaction.java isAirClearingProcessing(), isAirClearFunctionPaused(), getLastAction(), getAreaInfo()가 planning context에서 사용된다.
MovingCleaningManager.java 이동 청정 중 MapManager.INSTANCE.getAllSplitSpaceList(...), RobotMovementController.getInstance().onCleaningMove(...)를 사용한다.
BaseCleaningManager.java 청정 중 InterScheduleManager, MapManager.isEditMap() 같은 조건을 함께 본다.

설계상 의미:

3.3 moving/

역할:

주요 근거:

파일 근거
MovingLocationManager.java move(String target_areaid)MapManager.INSTANCE.getAreaById(...)로 target area 좌표를 찾는다.
MovingLocationManager.java move(Position)와 private move(Position, int)가 실제 AMRMotor.INSTANCE.setMoveTo(...) 또는 returnToStation()으로 이어진다.
MovingLocationManager.java stop(), pause(), resume()이 이동 lifecycle을 담당한다.
MovingLocationManager.java notifyArrived(...)에서 cleaning, interaction schedule, mapping, robot movement callback으로 분기한다.
MovingController.java isOnStation(), return/docking 상태와 target area 상태를 제공한다.
RobotMovementController.java moving status, pause 상태, priority를 제공한다.

설계상 의미:

3.4 map/

역할:

주요 근거:

파일 근거
MapManager.java getStationAreaId()가 station area 기준을 제공한다.
MapManager.java getAllSplitSpaceList(String areaid)가 공기질 scan/선택청정용 split space를 반환한다.
MapManager.java deleteMap()에서 ScheduleDao.deleteAllSchedules()와 공기질 link setting reset을 수행한다.
MapManager.java loadAreaList(...)가 encrypted map json에서 room id/name/polygon을 구성한다.
MapManager.java getAreaByPosition(...), setEditMap(...), isEditMap()이 위치/편집 상태를 제공한다.

설계상 의미:

3.5 schedule/interaction/

역할:

주요 근거:

파일 근거
ScheduleAlarmReceiver.java canExecuteSchedule(...)에서 active 여부, mapping, privacy mode, off-station, night mode, lock mode, area id validity, movement priority를 확인한다.
ScheduleAlarmReceiver.java interaction schedule이면 InterScheduleManager와 연결된다.
InterScheduleManager.java pause/resume/stop, move, sub-action complete callback, notify callback을 가진다.
ScheduleDao.java schedule CRUD와 delete all을 담당한다.
Schedule.java schedule task와 time parsing 모델을 가진다.

설계상 의미:

4. getset의 분리

복합명령 설계에서 중요한 분리는 getset이다.

유형 권장 처리
get / 상태조회 배터리, 현재 위치, 맵 편집 여부, queue 상태 DevicePlanningContextProvider 또는 domain manager snapshot으로 읽는다. 보통 task queue에 넣지 않는다.
set / 실행명령 이동, 청정 시작, 청정 정지, 스케줄 등록/취소 TaskManager.submitTask 또는 submitWorkflow로 관리한다.
long-running set 방 이동 후 청정, 스케줄 기반 이동, 공기질 스캐닝 workflow/subtask로 만들고 callback/event로 다음 step을 진행한다.
실패/차단 경로 막힘, 방 없음, 배터리 부족, 센서 오류 reason code를 올리고 필요 시 Cloud replan을 연다.

따라서 “현재 공기질 알려줘” 같은 조회는 task로 만들 필요가 약하다. 반대로 “거실로 가서 청정해줘”는 이동/청정의 실행 lifecycle이 있으므로 task/workflow로 관리해야 한다.

5. 안전한 실행 모델

권장 구조:

  1. Cloud가 recognized_text + voice_context + device_context를 보고 plan을 만든다.
  2. ODL step은 Cloud runtime에서 device_task_requests로 변환된다.
  3. 온디바이스 브릿지는 요청을 DeviceAgent의 submitWorkflow 또는 submitTask로 전달한다.
  4. DeviceAgent TaskManager는 queue에 등록하되, 각 subtask 실행 시점에 기존 domain manager 조건을 탄다.
  5. 정상 이벤트는 DeviceAgent/온디바이스가 이어서 처리한다.
  6. 판단이 필요한 실패 이벤트만 Cloud에 올려 replan한다.

피해야 할 구조:

  1. Cloud가 setAirCleanerOperation 같은 내부 함수를 직접 고른다.
  2. 온디바이스가 기존 token/조건 판단을 거치지 않고 wrapper만 호출한다.
  3. TaskManager가 도메인별 조건을 모른 채 함수 호출만 순서대로 실행한다.
  4. 모든 PROGRESS/COMPLETED event마다 Cloud LLM을 다시 돌린다.

6. 예시: 이동 후 청정 workflow

발화:

거실로 가서 청정하고 안방으로 이동해줘

Cloud plan:

{
  "turn_mode": "multi_turn",
  "steps": [
    {
      "id": "step_1",
      "route": "ODL",
      "purpose": "거실로 이동",
      "output": "arrival_state"
    },
    {
      "id": "step_2",
      "route": "ODL",
      "purpose": "거실 청정 시작",
      "input_from": ["step_1"]
    },
    {
      "id": "step_3",
      "route": "ODL",
      "purpose": "안방으로 이동",
      "input_from": ["step_2"]
    }
  ]
}

On-device request:

{
  "method": "submitWorkflow",
  "workflowName": "device_intent_workflow",
  "source": "cloud_a2a",
  "subTasks": [
    {
      "taskMethod": "moveToRoom",
      "roomName": "거실"
    },
    {
      "taskMethod": "startAirCleaning",
      "roomName": "거실",
      "dependsOnPrevious": true
    },
    {
      "taskMethod": "moveToRoom",
      "roomName": "안방",
      "dependsOnPrevious": true
    }
  ]
}

DeviceAgent 내부 실행:

  1. TaskManager.submitWorkflow(...)가 workflow를 등록한다.
  2. 첫 subtask 실행 직전에 moveToRoom adapter가 MapManager로 room id/position을 resolve한다.
  3. MovingLocationManager.move(...)가 이동을 시작한다.
  4. 도착 callback이 오면 subtask 1을 COMPLETED로 표시한다.
  5. subtask 2 실행 직전에 CleaningTransaction, MapManager, device policy를 다시 확인한다.
  6. 청정 시작이 가능하면 기존 cleaning manager를 통해 실행한다.
  7. 실패하면 TaskReasonContract에 맞춘 reason event를 발생시킨다.

7. 업체 전달 포인트

DeviceAgent/SoC 담당 업체에는 아래를 명확히 요청해야 한다.

요청 이유
Cloud에서 내려온 task method와 기존 token/function handler의 1:1 또는 1:N mapping 표 기존 음성 조건 판단을 우회하지 않기 위해
각 task method별 실행 직전 조건 체크 위치 1번 task 완료 후 상태가 바뀌는 문제를 해결하기 위해
reason_code와 legacy error/status code mapping Cloud replan 판단을 안정화하기 위해
DevicePlanningContextProvider의 rooms/current room/battery/map 필드 보강 Cloud가 불가능한 plan을 처음부터 줄이기 위해
workflow/subtask callback 기준 다음 task 시작 시점을 정확히 잡기 위해
instrumented test와 dumpsys evidence 실제 단말에서 queue/event/context가 동작하는지 확인하기 위해

8. 남은 공백

현재 문서화된 구조는 DeviceAgent 앱 내부 도메인 중심이다. 아직 full AOSP 관점의 init.rc, Binder service 등록, HAL/AIDL, SELinux, partition 배치까지는 검증하지 않았다.

따라서 다음 단계는 둘로 나뉜다.

  1. 단기: DeviceAgent task/domain adapter를 완성하고 fake/instrumented test로 workflow event를 검증한다.
  2. 중기: SoC/AOSP 빌드 산출물 관점에서 DeviceAgent가 어떤 partition, permission, service boundary로 배치되는지 별도 분석한다.