TaskManager 사양 2 · 요청, API와 실행 정책
None요청 유입부터 공개 API, 기본값, 검증, 호출자·기기·자원 정책까지 실행 전 경계를 정의한다.
이 장의 결론: 요청을 접수한 뒤 입력, 호출자, 기기 상태와 자원을 순서대로 검증하고 허용된 작업만 실행 대기열로 보낸다.
4. 요청 유입과 유형 분류
4.1 지원 요청 출처
| 요청 출처 | 의미 | 일반적인 사용 예 |
|---|---|---|
APP |
제품 앱 요청 | 런처·시스템 앱 |
PUI |
물리 UI 요청 | 버튼·터치 제어 |
IOT |
IoT/MQTT 요청 | 원격 명령 |
SCHEDULE |
제품 예약 실행 | Wakeup·Welcome·청정 스케줄 |
SENSOR |
센서 기반 요청 | 안전 이벤트·상태 조건 |
CLOUD |
Cloud Planner 요청 | A2A Workflow |
ONDEVICE |
온디바이스 Agent 요청 | 기기 내 Planner·Bridge |
API |
내부 API 클라이언트 | SDK 호출 |
AUTONOMOUS |
기기 자율 판단 | 기기 내 복구·상태 관찰 |
INTERNAL |
DeviceAgent 내부 요청 | 모듈 전달·생명주기 명령 |
VOICE |
음성 요청 | 온디바이스 음성 Agent |
UNKNOWN |
출처가 없거나 불명확한 요청 | 제한적 호환 입력 |
4.2 신호 유형
TaskIngressClassifier는 들어오는 모든 메서드를 Task로 만들지 않는다.
| 신호 유형 | Task 관리 여부 | 처리 경로 | 의미 |
|---|---|---|---|
COMMAND_TASK |
true | submit_task |
실제 기기 상태를 바꾸는 명령 |
TASK_CONTROL |
false | task_manager_api |
조회, 취소와 대기열 제어 |
PROGRESS_UPDATE |
false | update_task_progress |
실행 중 진행률 갱신 |
RESULT_UPDATE |
false | update_task_result |
기기 도메인 결과 콜백 |
SENSOR_DATA |
false | state_or_resource_update |
상태·센서 스냅숏 갱신 |
TRIGGER |
false | policy_trigger |
정책 판정 후 Task를 만들 수 있는 이벤트 |
EVENT_CALLBACK |
false | event_callback |
기기 도메인 콜백·이벤트 |
UNKNOWN |
false | reject |
분류할 수 없는 입력 |
핵심 원칙은 명령과 관찰을 분리하는 것이다. 센서 콜백을 다시 구동 Task로 감싸면 순환 호출과 중복 실행이 생길 수 있다.
4.3 MainApi의 세 경로
method가 TaskManager 제어 메서드이면handleControlMethod()가 직접 처리한다.forceTaskManager=true이거나 Task 관리 대상 메서드이면 관리 실행 경로를 사용한다.- TaskManager 대상이 아니거나 호환성이 필요한 호출은 기존 경로를 유지한다.
이 구조는 기존 기능을 한 번에 전부 교체하지 않고 점진적으로 Task 계약에 편입하기 위한 호환 경계다.
5. 공개 제어 API
현재 TaskManager.handleControlMethod()와 TaskManagerClient가 공유하는 제어 메서드는 17개다.
| 메서드 | 주요 입력 | 주요 출력 | 역할 |
|---|---|---|---|
submitTask |
taskMethod, 매개변수 |
accepted, taskId, 결과 |
단일 Task 제출 |
submitWorkflow |
workflowName, subTasks |
상위 Task와 단계 상태 | 복합 Workflow 제출 |
scheduleTask |
Task와 trigger |
scheduleId, 상태 |
단일 Task 지연 등록 |
scheduleWorkflow |
Workflow와 trigger |
scheduleId, 상태 |
Workflow 지연 등록 |
getScheduledTasks |
상태·출처·개수 제한 | scheduledTasks |
예약 목록 조회 |
cancelScheduledTask |
scheduleId, 사유 |
취소 상태 | 예약 취소 |
runDueScheduledTasks |
nowMs, 개수 제한 |
실행 허용·건너뜀 결과 | 실행 시점이 된 Task 재진입 |
getTaskStatus |
taskId |
TaskRecord 상세 |
Task 상세 조회 |
listTasks |
조회 조건 | tasks |
Task 목록 조회 |
getQueueStatus |
대기열 | 대기열 스냅숏 | 대기열별 실행·대기 상태 |
updateTaskProgress |
Task ID·진행률·단계·메시지 | 갱신된 기록 | 외부 진행률 반영 |
cancelTask |
Task ID·사유 | 취소 결과 | 개별 Task 취소 |
clearPendingTasks |
대기열 | 처리 건수 | 대기 Task만 정리 |
cancelQueue |
대기열·실행 중 포함 여부 | 처리 건수 | 대기열 단위 취소 |
getTaskManagerStatus |
없음 | 운영 지표·대기열 | TaskManager 상태 조회 |
getDevicePlanningContext |
없음 | 컨텍스트 스냅숏 | 현재 기기 상태 조회 |
classifyTaskIngress |
Task 메서드·신호 유형 | 분류 결과 | 요청 유형 판정 조회 |
위 17개 메서드는 현재
TaskManager의 제어 분기와TaskManagerClient공개 상수에 모두 존재한다. 출시할 때마다 양쪽 목록과 실제 처리 분기를 교차 점검해야 한다.
5.1 submitTask 최소 요청
{
"method": "submitTask",
"forceTaskManager": true,
"taskMethod": "setMoveTo",
"source": "APP",
"requestId": "move-bedroom-001",
"traceId": "trace-001",
"positionId": "5",
"positionName": "안방",
"completionTarget": "movement.arrived",
"timeoutMs": "120000"
}
5.2 submitWorkflow 최소 요청
{
"method": "submitWorkflow",
"forceTaskManager": true,
"workflowName": "room_clean_return",
"source": "APP",
"requestId": "wf-room-clean-001",
"traceId": "wf-room-clean-001",
"subTasks": [
{
"stepId": "move-bedroom",
"taskMethod": "setMoveTo",
"positionId": "5",
"positionName": "안방",
"completionTarget": "movement.arrived"
},
{
"stepId": "clean-bedroom",
"taskMethod": "setAirCleanerOperation",
"action": "1",
"mode": "0",
"completionTarget": "cleaning.stopped"
},
{
"stepId": "return-station",
"taskMethod": "returnToStation",
"completionTarget": "movement.stationCharging"
}
]
}
5.3 공통 요청 필드
| 필드 | 타입 | 필수성 | 의미 |
|---|---|---|---|
method |
String | 필수 | 제어 메서드 |
forceTaskManager |
Boolean | 권장 | 속성과 관계없이 TaskManager 경로를 강제 |
taskMethod |
String | Task 필수 | 실행할 표준 기능 메서드 |
workflowName |
String | Workflow 필수 | Workflow 식별 이름 |
subTasks |
List<Bundle> | Workflow 필수 | 순차 단계 또는 병렬 그룹 |
source |
String | 권장 | 요청 유입원 |
requestId |
String | 강력 권장 | 멱등성과 중복 등록 방지 식별자 |
traceId |
String | 강력 권장 | 계층 간 실행 추적 식별자 |
queue |
String | 선택 | 외부 계약의 queue 필드 |
queueKey |
String | 내부 변경 | 현재 정책 변환기가 읽는 변경 키 |
priority |
String | 선택 | BACKGROUND~EMERGENCY |
executionMode |
String | 선택 | direct, queued_wait, async |
timeoutMs |
String/Long | 선택 | Task 런타임 시간 제한 |
strictValidation |
Boolean | 권장 | 메서드 스키마 강제 여부 |
preemptPolicy |
String | 선택 | 기존 Task 처리 정책 |
cancellable |
Boolean | 선택 | 취소 가능 여부 변경 |
stateAware |
Boolean | 선택 | 상태 기반 실행 허용 판정 적용 여부 |
cancelMethod |
String | 선택 | 취소할 때 실행할 메서드 |
compensationMethod |
String | 선택 | 실패 뒤 실행할 보상 동작 메서드 |
requireMainState |
String/Int | 선택 | 필요한 주 상태 |
checkBlockedStatus |
Boolean | 선택 | 차단 상태 확인 여부 |
resourcePolicyEnabled |
Boolean | 선택 | 시스템 자원 정책 활성화 |
requiredResources |
List<String> | 선택 | 카메라·화면·이동 등 필수 자원 |
completionTarget |
String | 선택 | 실제 완료 증거 종류 |
completionTimeoutMs |
String/Long | 선택 | 완료 증거 대기 시간 제한 |
completionStableMs |
String/Long | 선택 | 완료 증거 안정 유지 시간 |
queue와 queueKey는 계층별 명칭 차이가 남아 있다. AAR builder는 queue를 쓰지만 TaskPolicyRegistry.resolve()는 직접 변경값으로 queueKey를 읽는다. 외부 계약은 queue를 표준 이름으로 유지하고 DeviceAgent 경계에서 별칭을 정규화해야 한다.
5.4 생략 필드의 기본값과 적용 순서
요약: TaskManager의 기본값은 요청 생성기 한 곳에서 일괄 입력되지 않는다. 호출 경로가 자동으로 넣는 값, 메서드 정책 목록이 채우는 값, Workflow·예약 런타임이 계산하는 값과 도메인 실행기가 보완하는 값이 순서대로 결합된다. 따라서 “필드를 생략해도 된다”는 말은 어느 계층이 어떤 값으로 보완하는지 계약에 고정돼 있다는 뜻이어야 한다.
5.4.1 기본값 결정 우선순위
실행값은 다음 순서로 결정된다.
- 호출자가 명시한 값: 허용된 변경 필드는 요청값을 우선 사용한다.
- 호출 경로의 정규화·자동 삽입: AAR, Cloud 어댑터, Task Monitor가 제어 메서드와 일부 메타데이터를 넣는다.
- 메서드별 명시 정책:
TaskPolicyRegistry의 exact policy가 실행 방식, 대기열, 우선순위, 시간 제한, 재시도, 취소와 보상 동작을 제공한다. - 등록되지 않은 메서드의 추정 정책: 메서드 이름으로 임시 fallback policy를 만든다. 이는 호환 안전망이며 출시 기능의 정식 사양으로 사용하면 안 된다.
- Workflow·예약 런타임 기본값: Workflow 이름, 병렬 그룹 정책, 단계 지연, 예약 유형과 실행 허용 옵션을 보완한다.
- 도메인 실행기 기본값: 이동, 청정, Security 등 실제 기능이 안전한 호출 형식이나 완료 조건을 추가로 정규화한다.
- 시스템 속성 기본값: 엄격 검증, 자원 정책, 영속성, 대기열 크기 같은 운영값을 최종 적용한다.
TaskRecord의 taskId는 호출자가 보내지 않아도 <taskMethod>-<sequence> 형식으로 생성된다. 예약 ID도 scheduled-<sequence> 형식으로 생성된다. 반면 requestId와 traceId는 자동 생성되지 않는다. 내부 Task ID가 생긴다는 사실을 외부 멱등성과 분산 추적이 확보된 것으로 해석하면 안 된다.
5.4.2 호출 경로별 자동 입력
| 호출 경로 | 생략 시 자동 입력 | 자동 입력하지 않는 주요 값 | 의미 |
|---|---|---|---|
TaskSubmitRequest AAR |
method=submitTask, forceTaskManager=true, builder 인자의 taskMethod |
source, requestId, traceId, 완료 조건 |
최소 타입 안전성은 제공하지만 운영 메타데이터는 호출자 책임 |
TaskWorkflowRequest AAR |
method=submitWorkflow, forceTaskManager=true, builder 인자의 workflowName, subTasks |
source, requestId, traceId, 단계 ID와 완료 조건 |
빈 단계 목록은 build()에서 거절 |
AAR scheduleTask/Workflow |
위 값과 scheduleKind=deferred_task |
실제 trigger 시각 |
trigger가 없으면 Core에서 missing_schedule_trigger 거절 |
| Cloud Device Task 어댑터 | method=submitTask, forceTaskManager=true, source 인자 생략 시 source=CLOUD |
requestId, traceId, 메서드별 필수 입력 |
Cloud payload를 Task 계약으로 정규화 |
| Task Monitor | forceTaskManager=true, source 생략 시 CLOUD, queue 생략 시 default 또는 routine, dryRun=true, executorDryRun=true |
실제 실행을 위한 dryRun=false |
모니터 기본은 물리 동작 없는 안전 시험 |
raw Bundle |
자동 입력 없음 | 제어 method, taskMethod, source와 상관관계 필드 |
가장 유연하지만 누락·별칭 오류 위험이 가장 큼 |
forceTaskManager를 raw 요청에서 생략하면 요청 자체의 기본값은 false다. 다만 현재 시스템 속성 persist.sys.deviceagent.taskmanager.enable의 기본값이 true이므로 Core는 활성화된다. AAR가 forceTaskManager=true를 넣는 이유는 시스템 속성 상태와 무관하게 관리 경로를 명시하기 위해서다.
5.4.3 공통 실행 정책 기본값
| 필드 | 생략 시 현재 동작 | 적용 주체 | 주의점 |
|---|---|---|---|
source |
일반 raw 요청은 UNKNOWN, Cloud 어댑터·Monitor는 CLOUD |
TaskSource.from() 또는 호출 어댑터 |
UNKNOWN은 호출자 권한과 운영 분석의 의미를 약화시킴 |
executionMode |
메서드별 exact policy 사용 | TaskPolicyRegistry |
조회는 주로 DIRECT, 이동·청정·세션은 주로 ASYNC, 상태 변경은 주로 QUEUED_WAIT |
queueKey |
메서드별 exact policy 사용 | TaskPolicyRegistry |
현재 AAR의 queue 변경값이 Core의 queueKey 읽기와 불일치할 수 있음 |
priority |
메서드별 exact policy 사용 | TaskPolicyRegistry |
잘못된 문자열도 정책값으로 복귀하며 별도 오류를 내지 않음 |
timeoutMs |
exact policy 값, 일반 fallback 30초 | TaskPolicyRegistry |
조회 3~5초, 이동 120초, 청정·interaction 1200초처럼 메서드별 차이가 큼 |
retry |
대부분 0, setConfig 1 |
TaskPolicyRegistry |
자동 재시도 가능 기능은 명시 정책으로 제한해야 함 |
cancellable |
메서드별 정책값 | TaskPolicyRegistry |
이동·청정·AI·일부 장기 세션은 true, 조회·일반 상태 변경은 주로 false |
stateAware |
현재 exact/fallback policy 모두 true | TaskPolicyRegistry |
requireMainState나 checkBlockedStatus가 없으면 추가 상태 조건 검사는 발생하지 않음 |
cancelMethod |
메서드별 정책 또는 대기열별 기본 취소 메서드 | TaskPolicyRegistry |
이동은 stopMovement, AI는 LLM 상태 변경, 청정은 청정 stop 계약 사용 |
compensationMethod |
exact policy에 정의된 경우만 사용, 일반 fallback은 없음 | TaskPolicyRegistry |
취소 동작과 실패 보상 동작은 동일하지 않음 |
preemptPolicy |
append |
TaskManager.applyPreemptPolicy() |
생략하면 기존 대기·실행 Task를 취소하지 않고 뒤에 추가 |
strictValidation |
false | 요청값 또는 시스템 속성 | false이면 메서드 필수 매개변수 오류가 실행기까지 늦게 전달될 수 있음 |
resourcePolicyEnabled |
false | 요청값 또는 시스템 속성 | false여도 Vision·Security 등 명확한 도메인 자원 충돌 검사는 별도로 수행됨 |
bypassCallerPolicy |
false | TaskCallerPolicy |
true는 특권 우회이므로 일반 호출자에게 노출하면 안 됨 |
requireMainState |
조건 없음 | TaskManager |
값이 있을 때만 현재 주 상태와 비교 |
checkBlockedStatus |
false | TaskManager |
생략하면 StateManager.checkBlockedStatus() 추가 검사를 요청하지 않음 |
requiredResources |
빈 목록. 단, rotateInPlace는 movement_base, observeVisionSemantics는 movement_base와 camera를 내부 추가 |
TaskDomainResourcePolicy |
도메인 고정 자원과 호출자 추가 자원을 합쳐 충돌 판정 |
completionTarget |
공통 기본값 없음. 도메인 실행기가 지원 메서드에 한해 결정 | 각 도메인 실행기 | 명시값도 실행기가 지원하지 않으면 도메인 기본값 또는 비대기 동작으로 바뀔 수 있음 |
completionTimeoutMs |
timeoutMs, 그것도 없으면 메서드 정책 시간 제한 |
TaskCompletionWatcher |
최종값은 최소 1초. 0 이하이면 일반 완료 대기 기본 30초로 복귀 |
completionStableMs |
500ms | TaskCompletionWatcher |
0을 명시하면 한 번 관찰된 완료 증거를 즉시 인정 |
completionKey |
공통 기본값 없음 | 도메인 실행기 | TTS와 UI는 일부 대체 키를 찾지만 앱 세션은 명시 키 필수 |
preemptExisting |
Core 해석 없음 | AAR builder에만 필드 존재 | 현재 선점 효과를 원하면 preemptPolicy를 사용해야 함 |
executorDryRun |
실제 AAR/raw 경로 false, Task Monitor 경로 true | 실행기·Monitor 어댑터 | Monitor에서 생략했다고 실기기 동작이 실행되는 것이 아님 |
등록되지 않은 메서드의 fallback은 일반적으로 timeoutMs=30000, retry=0, stateAware=true를 사용한다. 이름이 get, is, Info, Version, Dump 계열이면 DIRECT로, 그 외에는 ASYNC로 추정한다. 이름에 stop, reset, error, emergency가 들어가면 EMERGENCY로 추정할 수 있으므로, 외부의 source 누락은 UNKNOWN이 되어 호출자 정책에서 거절될 수 있다. 이름 기반 fallback은 개발 중 호환용이지 기능 등록을 대신하지 않는다.
5.4.4 Workflow와 예약 기본값
| 필드 | 생략 시 현재 동작 | 적용 주체 | 주의점 |
|---|---|---|---|
workflowName |
raw Core 요청은 workflow; AAR builder는 빈 이름 거절 |
Workflow 런타임 / AAR | 운영에서는 충돌 없는 의미 이름을 명시해야 함 |
| Workflow queue | 항상 workflow로 고정 |
ensureWorkflowPolicy() |
하위 단계는 각자의 도메인 대기열·정책 사용 |
| Workflow 실행 방식·우선순위 | 이름으로 해석한 정책 사용. 일반 이름은 보통 ASYNC·NORMAL | TaskPolicyRegistry |
제품 Workflow는 실행 방식과 반환 시점 계약을 명시적으로 고정해야 함 |
| Workflow timeout | 각 단계 timeout과 after_step.delayMs의 합 이상으로 계산 |
calculateWorkflowTimeoutMs() |
병렬 그룹은 자식 timeout의 최댓값을 사용 |
Workflow cancellable |
true | ensureWorkflowPolicy() |
실제 취소 성공은 실행 중 자식과 취소 메서드의 증거에 달림 |
단계 trigger·conditions |
둘 다 없으면 즉시 실행 | Workflow 런타임 | 조건부 단계가 필요하면 구조화 필드를 명시해야 함 |
after_step.delayMs |
0ms | Workflow 런타임 | 음수는 거절, 0이면 선행 단계 완료 직후 실행 |
조건 step_output_equals.onFalse |
fail |
Workflow 런타임 | skip을 원하면 명시해야 함 |
병렬 groupId |
parallelGroup-<stepIndex> |
병렬 그룹 런타임 | 관측성과 재시도 추적을 위해 명시 권장 |
병렬 joinPolicy |
all_success |
병렬 그룹 런타임 | 현재 구현은 모든 자식 종료를 기다리며 다른 join 동작을 별도로 분기하지 않음 |
병렬 failurePolicy |
fail_parent |
병렬 그룹 런타임 | continue_on_failure, partial_success가 필요하면 명시 |
scheduleKind |
deferred_task |
예약 런타임 / AAR | 다른 값은 unsupported_schedule_kind로 거절 |
requireFreshDeviceContext |
false | 예약 실행 허용 단계 | false이면 실행 직전 컨텍스트 새로고침을 요구하지 않음 |
blockWhenTaskManagerBusy |
false | 예약 실행 허용 단계 | fresh context가 없거나 옵션이 false이면 busy만으로 차단하지 않음 |
requiresCloudDecision |
false | 예약 결과 계약 | 실패·미실행 뒤 Cloud 판단이 필요하면 명시 |
missedRunGraceMs |
0 | 예약 실행 허용 단계 | 0은 만료 유예 검사를 사용하지 않는다는 뜻 |
runDueScheduledTasks.nowMs |
현재 시스템 시각 | 예약 런타임 | 시험에서 과거·미래 시각을 주입할 때만 명시 |
조회·실행 limit |
100, 최종 범위 1~100 | 예약·Task 목록 런타임 | AAR scheduler 자체의 주기 실행 묶음 상한 기본은 별도로 20 |
reportNonDueSkips |
true | 예약 런타임 | 아직 시점이 안 된 항목도 skipped 결과에 포함 |
예약 취소 reason |
cancel scheduled task |
예약 런타임 | 사용자·운영 원인을 보존하려면 구체적으로 명시 |
5.4.5 도메인 실행기가 보완하는 값
| 도메인 | 생략 시 보완되는 값 | 적용 범위 |
|---|---|---|
이동 setMoveTo |
isAirsensor=false, isAirSensor=false, isAppCall=false; 이동 시간 제한 기본 120초 |
관리 이동 실행기 |
| 스테이션 복귀 | 이미 도킹 중이면 이동 명령 없이 완료 결과 반환, 아니면 movement.stationCharging 관찰 |
관리 이동 실행기 |
| 청정 | action=시작, mode=기본 청정, speed=0, ai=false; 시간 제한 기본 1200초 |
관리 청정 실행기 |
| 청정 완료 조건 | 정지 명령 또는 기본 청정은 cleaning.stopped, 그 외 시작 청정은 cleaning.reportDone |
관리 청정 실행기 |
| 청정 최소 수행 시간 | cleanMinTimeMs가 없으면 시스템 속성값, 현재 기본 0ms |
완료 대상이 cleaning.stopped인 시작 청정 |
| Security | start/pause/resume/stop 메서드에 맞는 상태 완료 조건 자동 선택 | MainApi 실행기 |
| Mapping | reqmap은 mapping.dataReceived 자동 선택 |
MainApi 실행기 |
| TTS | 완료 조건을 생략하면 재생 요청 반환까지만 처리 | LLM/TTS 실행기 |
| UI 화면 전환 | 완료 조건을 생략하면 화면 적용 증거를 기다리지 않음 | 프레임워크 실행기 |
도메인 기본값은 편의를 위한 임의 추정이 아니라 기존 기능 계약을 안정된 Task 입력으로 바꾸는 어댑터 규칙이어야 한다. 예를 들어 이동 대상 공간, TTS 문장, 화면 이름, 외부 앱 세션 키처럼 의미를 바꾸는 값은 도메인 실행기가 임의 생성하면 안 된다.
청정 기본값 주의: 엄격 검증이 꺼진 상태에서
setAirCleanerOperation에action,mode,speed,operation을 모두 생략하면 실행기가시작·기본 청정·speed=0·ai=false를 보완한다. 기본 청정의 완료 조건은cleaning.stopped이고cleanMinTimeMs기본은 0ms이므로, 시작 직후 정지 명령으로 이어질 수 있다. 이는 하위 호환을 위한 실행기 보완이지 안전한 공개 API 최소 요청이 아니다. 제품 호출자는 최소한 동작과 모드를 명시하고 엄격 검증 시험을 통과해야 한다.
5.4.6 기본값이 없거나 생략하면 안 되는 필드
| 필드·상황 | 생략 결과 | 규범 |
|---|---|---|
제어 method |
raw 경로에서 어느 API인지 판정 불가 | MUST 명시. AAR만 자동 삽입 |
단일 Task taskMethod |
missing_task_method |
MUST 명시 |
Workflow subTasks |
missing_subtasks |
하나 이상의 단계 MUST |
각 Workflow·병렬 자식 taskMethod |
실행 시 missing workflow subTask method 또는 검증 실패 |
각 단계 MUST |
단계 stepId |
단순 순차 실행은 가능하지만 단계 상관관계가 비어 있음 | 의존성·상대 지연·Cloud 추적 단계 MUST |
예약 trigger 또는 시각 필드 |
missing_schedule_trigger |
예약 등록 시 MUST |
| 이동 대상 | 엄격 검증 시 validation_failed, 아니면 실행기에서 unknown_move_target |
공간 ID·이름·좌표 중 지원 값 MUST |
| TTS 문장 | 엄격 검증 시 validation_failed |
tts, text, ttsText, message 중 하나 MUST |
| 화면 전환 대상 | 엄격 검증 시 validation_failed |
screenName, screen, targetScreen 중 하나 MUST |
제품 스케줄 변경의 scheduleId |
엄격 검증 시 validation_failed 또는 하위 기능 실패 |
대상 스케줄을 식별하는 값 MUST |
app.sessionEnded의 completionKey |
missing_completion_key |
앱 패키지·세션 상관 키 MUST |
tts.playbackEnded의 상관 키 |
completionKey → cloud_step_id → requestId → traceId 순으로 찾고 모두 없으면 실패 |
복합 Workflow에서는 명시적 단계 키 SHOULD |
requestId |
Task 실행은 가능하지만 예약 중복 등록 방지 없음 | 외부·예약 요청 SHOULD, 멱등성 요구 시 MUST |
traceId |
Task 실행은 가능하지만 계층 간 추적 연결 없음 | 복합·원격 요청 SHOULD, 추적성 요구 시 MUST |
현재 엄격 검증의 기본값은 false다. 이는 기존 호출 호환성을 위한 선택이지 필수 매개변수가 실제로 선택이라는 뜻이 아니다. 출시 계약에서는 기능 카드에 호출자가 반드시 보내는 값, AAR가 넣는 값, Core 정책값, 도메인 실행기 기본값, 기본값 금지값을 분리해 고정하고, 엄격 검증을 켠 회귀 시험까지 통과해야 한다.
5.5 공통 결과 필드
| 필드 | 의미 |
|---|---|
accepted |
요청 접수 또는 처리 성공 여부 |
taskId / task_id |
TaskManager 내부 task 식별자 |
taskMethod / task_method |
실행 메서드 |
taskQueue / queue |
queue |
taskState / status |
생명주기 상태 |
executionMode |
실행 방식 |
priority |
우선순위 |
source |
요청 출처 |
cancellable |
취소 가능 여부 |
retryCount |
실행 재시도 횟수 |
progress |
0~100 진행률 |
stage |
현재 의미 단계 |
message |
운영/사용자 설명용 메시지 |
workflowName |
상위 Workflow 이름 |
currentStepIndex |
현재 단계 번호 |
currentStepMethod |
현재 단계 메서드 |
subTaskStates |
단계별 상태와 결과 |
taskErrorCode / errorCode |
하위 오류 |
reasonCode / reason_code |
정규화된 실패 사유 |
reasonParams |
대상 등 구조화된 매개변수 |
recoverability |
복구 책임 분류 |
suggestedAction |
다음 권장 동작 |
requiresCloudDecision |
상위 판단 필요 여부 |
result |
기기 도메인 실행기 결과 |
6. 실행 허용 절차
submitTask는 실행기를 호출하기 전에 아래 절차를 통과한다.
6.1 활성화 조건
TaskManager는 다음 중 하나면 활성화된다.
- 요청에
forceTaskManager=true persist.sys.deviceagent.taskmanager.enable=true
해당 속성을 읽지 못했을 때의 기본값은 현재 true다.
6.2 입력 검증
현재 입력 검증은 기존 시스템 호환을 위해 두 단계로 동작한다.
| 모드 | 동작 |
|---|---|
| 기본 | taskMethod 존재 여부만 강제하고, 알려진 메서드의 세부 필드는 엄격하게 검사하지 않음 |
| 엄격 | strictValidation=true이거나 전역 속성이 true이면 메서드별 스키마 검사 |
전역 속성:
persist.sys.deviceagent.taskmanager.strict_validation
예시:
| 메서드 | 엄격한 입력 검증에서 요구하는 값 |
|---|---|
setMoveTo |
positionId, positionName, position, positionIds 중 하나 |
setMoving |
action, operation, moving 중 하나 |
setAirCleanerOperation |
action, mode, speed, operation 중 하나 |
setLlmTts |
tts, text, ttsText, message 중 하나 |
setLauncherScreen |
screenName, screen, targetScreen 중 하나 |
| 스케줄 변경 | 스케줄 ID 또는 메서드별 동작 필드 |
알 수 없는 메서드는 입력 검증기를 통과하더라도 실행기 생성 단계에서 missing_task_command로 거절될 수 있다. 따라서 엄격한 입력 검증만으로 기능 등록 여부까지 보장할 수는 없다.
6.3 호출자 정책
현재 가장 명시적인 요청 출처 정책은 긴급 우선순위 제한이다.
EMERGENCY우선순위는INTERNAL,AUTONOMOUS,SENSOR요청에만 허용한다.bypassCallerPolicy=true는 특권 우회이므로 일반 외부 요청에 노출하면 안 된다.
6.4 도메인 자원 정책
현재 명시적으로 관리하는 충돌 예시는 다음과 같다.
| 요청 | 요구 자원 | 충돌하는 활성 도메인 |
|---|---|---|
rotateInPlace |
movement_base |
Security movement |
observeVisionSemantics |
movement_base, camera |
Security, streaming, vital sign |
| vital sign 화면 | foreground_display, camera, external_app_session |
Security, streaming |
| Security 시작 | camera, movement/session | streaming, vital sign |
requiredResources를 요청에 추가하면 기능별 조건문을 계속 늘리지 않고 자원 요구사항을 구조화할 수 있다. 선택적 상위 Planner도 기능 설명자에 정의된 같은 자원 용어를 사용해야 한다.
6.5 시스템 자원 정책
TaskResourceMonitor는 CPU 사용률, RAM 압력과 발열 단계의 최신 스냅숏을 보관한다. 실행 허용 절차는 resourcePolicyEnabled와 정책 임계값에 따라 작업을 거절할 수 있다. 스냅숏은 하드웨어 상태의 영구 진실이 아니므로 측정 시점과 출처를 함께 확인해야 한다.
6.6 선점 실행 허용
새 요청은 기본적으로 기존 작업을 중단하지 않는다. preemptPolicy가 명시된 경우에만 대기열과 Task 상태를 변경한다.
| 정책 | 동작 |
|---|---|
append |
기존 작업을 유지하고 뒤에 추가 |
clear_pending |
같은 대기열의 PENDING 작업만 취소 |
cancel_running |
같은 대기열에서 실행 중인 작업까지 취소 시도 |
replace_queue |
같은 대기열의 실행 중 작업까지 취소한 뒤 새 요청 제출 |
replace_all |
모든 대기열에서 취소 가능한 Task를 취소한 뒤 제출 |
6.7 기존 DeviceAgent 제품 정책의 계승
TaskManager 도입 전부터 DeviceAgent에는 제품 상태, 배터리, LLM 세션, 개인정보 보호, 오류, 이동 자세와 동작 간 충돌을 판단하는 정책이 있다. TaskManager는 이 정책을 별도 규칙으로 복사하지 않고 승인된 기존 도메인 진입점을 통해 반드시 통과해야 한다.
정책은 다음 네 계층으로 나눈다.
| 계층 | 정책 소유자 | 담당 범위 | TaskManager의 역할 |
|---|---|---|---|
| Task 계약 정책 | TaskBundleValidator, TaskCallerPolicy, TaskPolicyRegistry |
입력, 호출자, 대기열, 우선순위, 시간 제한과 취소 | 실행 전에 공통 계약을 판정한다. |
| 공통 상태·자원 정책 | TaskDomainResourcePolicy, TaskResourcePolicy |
카메라·이동 기반부·전면 앱 세션 충돌, CPU·RAM·발열 | 명백한 공통 충돌을 조기에 차단한다. |
| 제품·도메인 정책 | StateManager, CmdPolicyManager, 도메인별 manager·handler |
제품 모드, LLM, 배터리, AMR 연결, 오류, 개인정보 보호, 현재 동작 간 전환 | 정책 담당자를 우회하지 않고 결과를 구조화된 실패 사유로 변환한다. |
| 물리 부수 정책과 완료 증거 | MovingLocationManager, TiltingManager, LCDManager, 각 domain callback |
이동 자세, 화면 깨움, 정지·도착·도킹·청정 종료 같은 실제 상태 | 내부 자동 동작을 별도 사용자 단계로 만들지 않고 최종 증거를 Task 상태에 반영한다. |
6.7.1 대표 정책 계승 행렬
| 상황 | 기존 정책과 실제 동작 | Task 경로가 지켜야 할 계약 | 소스 기준점 |
|---|---|---|---|
| Factory·ICT·Upgrade·SelfTest | 일반 제품 동작을 제한하거나 별도 모듈로 전달 | 일반 Task 실행 전에 현재 제품 상태를 보존하고 우회하지 않는다. | StateManager.isProductOperationState(), MainApi.executeMethodInternal() |
| Vital Sign·Streaming | 이동·청정·스케줄 등 일부 메서드를 차단 | 화면 전환 성공만으로 후속 이동을 시작하지 않고 세션 상태와 도메인 정책 결과를 확인한다. | StateManager.checkBlockedStatus() |
| LLM 처리 중 | AirSensor 예외 등을 제외한 일반 이동·청정 실행을 제한 | Task 우선순위나 Workflow 순서로 LLM 정책을 덮어쓰지 않는다. | CmdPolicyManager.commonCheck() |
| 저전력·임계 저전력 | 이동·이동청정·스케줄을 제한하고, 저전력 복귀는 별도 우선 정책으로 처리 | 일반 이동과 안전 복귀를 같은 명령으로 취급하지 않는다. | CmdPolicyManager.commonCheck(), isLowBatteryReturnToStationStatus() |
| 개인정보 보호·AMR 미연결·맵 편집·초기화 중 | 이동 계열 동작을 거절 | 도메인 거절을 POLICY_NOT_ALLOWED 계열 실패로 보존한다. |
CmdPolicyManager.commonCheck() |
| 이동 시작 | MOVING 틸트 조건을 켜고 LCD 이벤트를 발생시킨 뒤 AMR 이동 |
Workflow에 tiltDown을 임의로 추가하지 않는다. 이동 도메인이 자세를 자동 관리한다. |
MovingLocationManager.move() |
| 이동 중 일시정지·재개 | 일시정지 시 MOVING=false, 재개 시 MOVING=true |
Task pause·resume이 기존 이동 상태 전이와 틸트 조건을 함께 통과해야 한다. | MovingLocationManager.pause(), resume() |
| 이동 완료·도킹 | 일반 위치 도착 시 MOVING 조건을 해제하고, 스테이션은 충전 증거에서 이동·도킹 조건을 해제 |
위치 도착과 스테이션 충전을 서로 다른 완료 증거로 유지한다. | notifyArrived(), notifyMovingStatus() |
| 이동 중 틸트 | 기본적으로 MOVING 조건은 틸트 DOWN 후보지만 LLM·관찰·보안 등 상위 조건이 최종 자세를 바꿀 수 있음 |
TaskManager가 틸트 결과를 고정하지 않고 TiltingManager의 합성 판단을 따른다. |
TiltingManager.runTiltingChecker() |
| Vision 의미 관찰 | 이동 중이면 거절하고, 정지 후 OBSERVATION 조건으로 틸트 UP 완료를 기다린 뒤 관찰 |
정지 확인 → 관찰 자세 완료 → 최신 Vision 증거 순서를 하나의 도메인 capability 계약으로 유지한다. |
ObservationTaskExecutor.observeVisionSemantics() |
| 청정 중 새 이동 | 관리 이동 실행기는 청정을 정지하고 실제 정지 증거를 기다린 뒤 이동 | 단순 메서드 호출 순서가 아니라 도메인 전환 완료를 확인한다. | MovementTaskExecutor.prepareMovementResource() |
| 복귀 요청 | 기존 동작을 정지하고 높은 우선순위로 복귀하되, 이미 복귀 중이면 기존 상태를 복구·유지 | 일반 선점과 제품 안전 복귀를 구분한다. | CmdPolicyManager.returnToStation() |
이 표의 틸트, LCD 깨움과 도킹 처리처럼 기능 수행에 내재된 제품 정책은 독립 Task로 노출하지 않는다. 독립 Task로 노출하면 Planner나 호출자가 내부 안전 순서를 생략하거나 잘못 재배열할 수 있다. 대신 이동 capability의 실행 계약과 결과에 posturePolicyApplied, physicalCompletionObserved 같은 관측 필드를 추가할 수 있다.
6.7.2 정책 계승 불변 조건
- 관리 실행기는 기존 도메인 정책 담당자를 우회해 HAL·MCU·AMR을 직접 호출하면 안 된다.
- 저수준 호출이 필요한 전용 실행기는 기존 진입점과 동등한 상태·자원 검사를 갖췄다는 별도 검토와 실기기 증거가 있어야 한다.
- TaskManager의
priority,preemptPolicy,forceTaskManager는 제품 안전 정책을 무효화하는 권한이 아니다. - 도메인 정책의 거절·대기·자동 전환 결과는
accepted,errorCode,reason,recoverability로 변환해야 한다. - 암묵적 제품 동작은 Workflow 단계 수를 늘리지 않되, 로그·이벤트·완료 증거에서 적용 여부를 확인할 수 있어야 한다.
- 같은 기능의 기존 경로와 관리 경로는 동일한 정책 조건에서 같은 물리 허용·거절 결과를 내야 한다.
6.7.3 현재 보강이 필요한 경계
| 경계 | 현재 위험 | 보강 기준 |
|---|---|---|
| Legacy 상태 차단 | MainApi의 일부 차단 분기는 구조화된 실패 결과 없이 반환할 수 있음 |
차단 이유를 표준 errorCode와 reason으로 변환한다. |
| 청정 Lock 처리 | Lock 상태에서 실제 실행을 건너뛰면서 성공으로 반환하는 경로가 있음 | skipped와 completed를 분리하고 정책 거절 또는 명시적 no-op 결과로 표현한다. |
| 상태 검사 선택값 | checkBlockedStatus는 Task 입력값에 따라 추가 검사 여부가 달라질 수 있음 |
출시 기능 카드에 필수 상태 검사와 실제 도메인 정책 경로를 고정한다. |
| Security 시험 예외 | 기존 정책 코드에 시험 목적으로 거절이 비활성화된 분기가 존재 | 제품 사양과 시험 예외를 분리하고 출시 형상에서 정책을 확정한다. |
| 저수준 전용 실행기 | 회전·관찰 등 일부 capability는 하위 장치를 직접 사용 | 정지·자원·개인정보 보호·취소·완료 증거의 동등성을 기능별로 입증한다. |
| 정책 변경 추적 | 도메인 정책 변경이 Task 기능 카드와 테스트에 자동 반영되지 않음 | 정책 ID, 소스 기준점, 적용 capability와 회귀 시험을 하나의 추적 항목으로 관리한다. |
7. 실행 정책 목록
TaskPolicyRegistry는 메서드별 기본 실행 정책을 중앙에서 관리한다.
7.1 실행 방식
| 실행 방식 | 의미 | 응답 시점 |
|---|---|---|
DIRECT |
대기열을 거치지 않고 호출 스레드에서 실행 | 실제 메서드 반환 후 |
QUEUED_WAIT |
대기열에 넣고 호출자가 최종 상태까지 대기 | 완료 또는 실패 후 |
ASYNC |
대기열에 넣고 즉시 Task 식별자 반환 | 접수 직후 |
문자열 alias:
direct,sync→DIRECTqueued_wait,wait→QUEUED_WAITasync→ASYNC
7.2 대기열
현재 정책 목록과 런타임에서 사용하는 대기열은 다음과 같다.
| 대기열 | 대표 기능 |
|---|---|
emergency |
stop, reset, emergency 계열 |
movement |
이동, 복귀, 회전 |
cleaning |
청정 실행/정지 |
state |
main/device state, launcher screen |
update |
OTA/firmware 상태 |
sound |
소리·음성 계열 기본 처리 |
settings |
기기 설정 |
ai |
LLM, TTS, Vision 의미 관찰 |
routine |
Eye LED/PUI scene |
schedule |
제품 스케줄 등록·조회·변경·삭제 |
interaction |
Welcome, Wakeup, Relax 등 상호작용 세션 |
security |
WSS Security 세션 |
mapping |
지도와 스테이션 상태 확인 |
device_info |
배터리와 펌웨어 조회 |
workflow |
상위 Workflow 실행 관리 |
default |
명시적 정책이 없는 메서드 |
7.3 우선순위
| 우선순위 | 용도 |
|---|---|
BACKGROUND |
비긴급 유지보수/관찰 |
NORMAL |
일반 실행 |
CONTROL |
일시정지, 재개와 상태 제어 |
HIGH |
이동, 복귀, 중요 세션 제어 |
EMERGENCY |
안전 정지와 복구. 신뢰된 요청 출처로 제한 |
7.4 현재 정책 예시
| 메서드 | 실행 방식 | 대기열 | 우선순위 | 시간 제한 | 취소·보상 동작 |
|---|---|---|---|---|---|
getBatteryInfo |
DIRECT | device_info | NORMAL | 5s | 없음 |
getDeviceStatus |
DIRECT | state | NORMAL | 5s | 없음 |
getStationLocationEvidence |
DIRECT | mapping | NORMAL | 5s | 없음 |
probeDockingSignal |
DIRECT | mapping | NORMAL | 3s | 없음 |
rotateInPlace |
QUEUED_WAIT | movement | HIGH | 30s | stopMovement |
observeVisionSemantics |
QUEUED_WAIT | movement | NORMAL | 10s | stopMovement |
setMainState |
QUEUED_WAIT | state | CONTROL | 30s | 없음 |
setLauncherScreen |
QUEUED_WAIT | state | NORMAL | 30s | 없음 |
setMoveTo |
ASYNC | movement | HIGH | 120s | stopMovement |
returnToStation |
ASYNC | movement | HIGH | 120s | stopMovement |
setAirCleanerOperation |
ASYNC | cleaning | CONTROL | 1200s | 청정 stop 계약 |
setChangeLlmStatus |
ASYNC | ai | HIGH | 30s | LLM stop/status |
| schedule query | DIRECT | schedule | NORMAL | 5s | 없음 |
| schedule mutation | QUEUED_WAIT | schedule | NORMAL | method별 | method별 |
interSchedule |
ASYNC | interaction | HIGH | 1200s | interaction stop |
startSecurityMode |
ASYNC | security | HIGH | 120s | stopSecurityMode |
| security pause/resume | ASYNC | security | CONTROL | 30s | 없음 |
| security stop | ASYNC | security | HIGH | 30s | 없음 |
등록되지 않은 메서드는 이름을 기준으로 실행 방식과 대기열을 추정한다. 이 기본 처리는 기존 기능을 수용하기 위한 임시 안전망일 뿐, 출시 가능한 기능 등록을 뜻하지 않는다. 제품 출시 대상 기능에는 명시적 정책과 실행기를 등록해야 한다.
제3부 · 실행 생명주기와 Workflow — 8~15장은 Task 상태, 실행 방식, 단계 제어, 완료 증거, 취소, 실패와 예약을 정의한다.