Pairing·SDK·호출 시험 모듈 상세
기준:
1398d109c391c4044cae26d0e9aea4d3f08d9670. 지정 커밋의 추적 파일을 직접 확인한 정적 구조 분석이며, 현재 HEAD·후속 TaskManager·SKIX 구현을 포함하지 않는다.
PairingAgent: 등록 통신과 네트워크 설정
기준 루트 P/는 apps/PairingAgent/app/src/main/java/com/sk/airbot/pairingagent/다. Android.mk는 prebuilt APK를 선택하지만 이 커밋의 Java 소스 구조도 별도로 분석했다. 아래 내용은 소스 기준이며 prebuilt dex와의 일치는 미확인이다.
| 구성 | 구현 역할 | 근거 |
|---|---|---|
| PairingAgentService | IPairingControl Stub, foreground 시작, Bluetooth 상태 확인 Handler | P/PairingAgentService.java:37–179 |
| BLECentral | BluetoothGattServerCallback 구현, 광고·GATT 서비스·read/write 요청·Wi-Fi 상태 응답 | P/ble/BLECentral.java:87, :296, :648, :957 |
| BLEProfile / AES128Config | BLE characteristic 계약과 암복호화 지원 | P/ble/ |
| WifiConnectionManager | 수신한 네트워크 설정을 WifiConfiguration으로 만들고 addNetwork·enableNetwork·reconnect 수행 | P/wifi/WifiConnectionManager.java:300–371 |
| BLEPeripheral / BLEScanner | GATT client read/write와 scan 지원 | P/ble/BLEPeripheral.java:27, :125, BLEScanner.java |
| classicbt | Bluetooth 스캔·연결·A2DP 지원 | P/classicbt/ |
| IntentReceiver / IntentSender | 외부 pairing·인증·reset broadcast 연결 | P/intent/, Manifest |
| provider | DB helper·계약·provider 소스 | P/provider/; 현재 Manifest에 provider 등록은 없음 |
호출의 왕복
DeviceAgent → IPairingControl.sendModuleCommand(method=setBluetooth) → PairingAgentService.setBluetooth() → BLEStatusHandler → BLECentral.startAdvertiser()가 제어 방향이다. Handler는 Bluetooth 상태를 1초 간격으로 확인한다. off 요청은 광고를 중지한다.
스마트폰 등의 GATT 요청은 BLECentral에서 처리한다. 분할 payload 재조립·복호화·SSID/보안 정보 설정을 거쳐 WifiConnectionManager가 Android Wi-Fi 설정을 적용한다. 이후 네트워크 상태·GATT read 응답과 DeviceControl 명령으로 등록 진행 상태를 전달한다.
근거: P/PairingAgentService.java:51–147, P/ble/BLECentral.java:957 이후의 characteristic 처리와 ConnectSsidRebuilder 등 재조립 코드, P/wifi/WifiConnectionManager.java:350–372.
생명주기와 외부 의존
onCreate에서 receiver 등록, foreground, DeviceControlProxy 연결, EncryptionServiceManager 연결, Wi-Fi·Bluetooth 활성화를 요청한다. BLECentral도 DeviceAgent callback을 사용한다. 따라서 이 앱은 Bluetooth 전송만 하는 모듈이 아니라 기기 초기 설정과 제품 상태의 연결점이다.
검토할 경계: unregisterCallback()이 같은 메서드를 재귀 호출하는 코드가 있으며(PairingAgentService.java:98–104), 이는 정상적인 callback 해제 구현으로 설명할 수 없다. 실제 prebuilt에서 같은 코드가 실행되는지는 별도 확인해야 한다. onDestroy의 receiver 해제만으로 BLE·Handler·외부 연결 전체 정리가 증명되는 것도 아니다.
DeviceControlAPI: legacy 정적 Java client
모듈 DeviceControlAPIJavaLib의 핵심은 apps/DeviceControlAPI/java/com/sk/airbot/devicecontrol/DeviceControlProxy.java다. 호출자는 static connect와 getService를 통해 IDeviceControl을 얻고 raw Bundle 명령을 보낸다.
앱 connect(context, callback, className/rebind)
→ singleton에 context·caller 이름·callback 보관
→ action + 명시적 DeviceAgent package로 bindService
→ IDeviceControl.Stub.asInterface
→ callback 등록 및 binder death 연결
→ 호출자의 onServiceConnected / onModuleCallback
disconnect는 death recipient 해제, 이름 기반 callback 해제, unbind, 연결 flag 초기화를 수행한다. 이 proxy는 명령 의미를 typed 도메인 API로 모두 변환하는 SDK가 아니라 Binder 연결·callback 수명 관리가 중심이다.
근거: 같은 파일 connect() overload, 내부 IDeviceControlSingleton, ServiceConnection, connectService():211, disconnectService():220 이후; apps/DeviceControlAPI/Android.mk:5–18.
AirbotSdkProject: 일반 제어·WSS·Streaming client library
Gradle 프로젝트의 devicecontrolapi 모듈에는 일반 DeviceControlProxy 외에 WSS와 Streaming 전용 proxy가 있다. app 모듈 Manifest에는 별도 Activity가 없어 이 커밋만으로 완성된 사용자용 sample UI라고 설명하지 않는다.
| 계층 | 클래스·파일 | 역할 |
|---|---|---|
| 일반 제어 | devicecontrol/DeviceControlProxy.java |
IDeviceControl 연결·callback |
| WSS 공통 | wsscontrol/WssManagerProxy.java |
bind timeout, event observer, death recipient, 재연결 |
| WSS 역할 | WssManagerFront / WssManagerRemote | front와 remote별 API 표면 |
| Streaming 공통 | streamingcontrol/StreamingManagerProxy.java |
세션 상태·movement·error·request 이벤트 전달 |
| Streaming 역할 | StreamingManagerFront / StreamingManagerRemote | 로컬 표현 쪽과 원격 요청 쪽 API 표면 |
| 값·IPC | deviceagent/wss/data/, deviceagent/data/, src/main/aidl/ |
parcelable·구역·위치 및 interface 사본 |
기준 루트: apps/AirbotSdkProject/devicecontrolapi/src/main/java/com/sk/airbot/.
WssManagerProxy.initWssManager는 bindService 결과를 확인하고 CountDownLatch로 지정 timeout까지 기다린다. 연결 시 IWssControl 변환·linkToDeath·registerWssCallback을 수행한다. 끊김·death 경로와 재연결 루프가 별도로 있다. 따라서 호출 스레드와 timeout·destroy 처리는 API 사용 시 확인해야 한다. UI thread에서 안전하다는 검증은 이번 분석에 포함하지 않는다.
근거: wsscontrol/WssManagerProxy.java:223–270, :328–416. Streaming의 RESULT_SUCCESS·RESULT_ERR_TIMEOUT·RESULT_ERR_BIND_FAILED와 running-state/event 상수는 streamingcontrol/StreamingManagerProxy.java:28–100.
Front/Remote 클래스가 있다고 server 인증을 대체하는 것은 아니다. server의 WssPackageValidator와 SDK API 표면은 서로 다른 책임이다. AIDL·parcelable 사본의 호환성은 IPC 문서를 참조한다.
devicecontrolapi_test: 수동 호출 시험 앱
apps/devicecontrolapi_test/java/.../MainActivity.java는 화면 위젯을 바인딩하고 DeviceControlProxy로 연결한다. callback은 method와 Bundle을 로그에 출력한다. 일부 화면명은 display/audio/LED 시험 이름을 유지하지만 실제 버튼 동작은 수정되어 있다. 예를 들어 한 버튼은 setLlmStatus Bundle을 전송하고 다른 버튼은 EXIT 표시로 바뀐다.
따라서 이 모듈은 API 회귀 suite나 자동 품질 gate가 아니다. UI 라벨만 보고 현재 검증 범위를 판정하면 안 된다. 실제 수행 method와 출력·장치 결과를 확인해야 한다.
근거: MainActivity.java:60–120, :128–135, :185 이후, apps/devicecontrolapi_test/Android.mk의 정적 library 의존.
permissions: 설치 권한 지원 모듈
이는 실행 앱이 아니다. privapp XML이 package별 권한을 선언하고 생성 도구가 실제 image의 APK와 framework permission을 비교한다. 앱 manifest에서 요청한 권한, allowlist, UID·서명, SELinux는 각기 다른 층이다. 상세 파일과 조건은 플랫폼·권한에 모았다.
확대 구조도와 연결별 근거
Connections
전체 목차 · 앱 구성 · DeviceAgent 내부 · IPC · 실행 흐름 · 플랫폼·빌드 · 근거·확인 범위