Motion Sensor HAL
The Motion Sensor HAL provides a standard interface for motion detection on RDK-E devices (e.g., PIR, radar).
It abstracts platform drivers and exposes a consistent API to discover sensors, configure detection modes, handle timing windows, and receive motion/no-motion events.
The HAL supports multiple motion sensors and delivers immutable capabilities per sensor.
A clear lifecycle state machine ensures dependable operation and predictable event delivery.
References
| Interface Definition | sensor/current/com/rdk/hal/sensor/motion |
| HAL Interface Type | AIDL and Binder |
| Initialization | systemd – hal-sensor-motion.service |
Related Pages
Overview
The Motion HAL enables RDK Middleware to configure and receive event-driven motion status from platform sensors.
Sensor Types
The HAL supports various motion/presence detection technologies:
- PIR (Passive Infrared): Detects heat signatures and movement
- Microwave/Radar: Active sensors measuring reflected waves
- Hybrid: Combination of multiple sensor types for improved accuracy
Each sensor type has different characteristics (range, field-of-view, sensitivity) exposed via Capabilities.
Use Cases
- Wake on Motion: Resume from standby when user approaches device
- Power Savings: Enter low-power mode after period of no activity
- Presence Detection: Adapt UI/behaviour based on user presence
- Security Flows: Detect unauthorized movement
- Energy Management: Automated standby during scheduled inactive periods
Key Features
- Controller pattern: Exclusive ownership via
open()/close()with binder death cleanup - Event-driven architecture: Async callbacks eliminate polling overhead
- Configurable timing: Control activation delays, inactivity windows, and scheduled active periods via
StartConfig - Optional deep-sleep autonomy: Sensor can operate and wake system from low-power states
- Per-sensor capabilities: Static properties describe hardware limits and features
- Diagnostics:
getStartConfig()andgetLastEventInfo()for runtime inspection
Implementation Requirements
| # | Requirement | Comments |
|---|---|---|
| HAL.MOTION.1 | Shall expose per-sensor capabilities via getCapabilities(); values remain immutable during runtime. |
|
| HAL.MOTION.2 | Shall provide start/stop APIs on IMotionSensorController to control detection. |
|
| HAL.MOTION.3 | Shall support querying current state via IMotionSensor.getState() and current config via IMotionSensorController.getStartConfig(). |
|
| HAL.MOTION.4 | Shall deliver motion/no-motion events via IMotionSensorEventListener.onEvent(mode) according to the StartConfig. |
|
| HAL.MOTION.5 | If sensitivity is supported (minSensitivity/maxSensitivity > 0), setSensitivity() shall enforce range and require State==STOPPED. |
Returns false for out-of-range; throws EX_ILLEGAL_STATE if not stopped. |
| HAL.MOTION.6 | Event listener registration shall be idempotent; duplicate registrations return false, as do unregisters of unknown listeners. |
|
| HAL.MOTION.7 | If deep-sleep autonomy is supported, setAutonomousDuringDeepSleep() shall require State==STOPPED; when unsupported it shall return false. |
|
| HAL.MOTION.8 | Active time windows shall only suppress events outside configured periods; motion detection continues but notifications are deferred or cancelled. | See IMotionSensorController.setActiveWindows(). |
| HAL.MOTION.9 | When active windows are configured, events shall only fire during the union of all configured windows. Empty array or windows with both times = 0 enables 24-hour monitoring. | |
| HAL.MOTION.10 | Shall register the service under the name "sensor.motion" and become operational at startup. |
Matches IMotionSensorManager.serviceName. |
| HAL.MOTION.11 | IMotionSensorControllerListener.onStateChanged() shall fire for every lifecycle state transition. |
Matches the pattern used by all other HAL modules. |
| HAL.MOTION.12 | If the controller-owning client crashes, the HAL shall implicitly call stop() and close() to release the sensor. |
Binder death cleanup. |
Interface Definition
| Interface Definition File | Description |
|---|---|
IMotionSensorManager.aidl |
Manager interface to enumerate and acquire motion sensors. |
IMotionSensor.aidl |
Per-sensor interface: capabilities, state, open/close, event listener registration. |
IMotionSensorController.aidl |
Exclusive controller: start/stop, config, sensitivity, deep sleep, active windows, diagnostics. |
IMotionSensorControllerListener.aidl |
Controller callbacks: onStateChanged, onActiveWindowEntered, onActiveWindowExited. |
IMotionSensorEventListener.aidl |
Multi-observer callback: onEvent(mode) for motion/no-motion detection. |
Capabilities.aidl |
Immutable capabilities (sensorName, sensitivity range, autonomy support). |
StartConfig.aidl |
Parcelable: operational mode + timing parameters for start(). |
LastEventInfo.aidl |
Diagnostic parcelable: last event mode + timestamp. |
OperationalMode.aidl |
Mode enum: MOTION, NO_MOTION. |
State.aidl |
Lifecycle states: STOPPED, STARTING, STARTED, STOPPING, ERROR. |
TimeWindow.aidl |
Daily time window for active period scheduling. |
Initialization
Vendors shall provide a hal-sensor-motion.service systemd unit to launch the Motion HAL.
The service shall register IMotionSensorManager with the Service Manager using serviceName = "MotionSensorManager".
Dependencies on drivers or low-level services must be expressed using systemd Requires= or Wants=.
System Context
flowchart TD
Client[RDK Middleware]
Manager[IMotionSensorManager]
Sensor[IMotionSensor]
Controller[IMotionSensorController]
CtrlListener[IMotionSensorControllerListener]
EventListener[IMotionSensorEventListener]
Hardware[PIR / Radar Sensor]
Client --> Manager
Manager --> Sensor
Sensor -->|open| Controller
Controller -->|state + window events| CtrlListener
Sensor -->|motion events| EventListener
Sensor --> Hardware
classDef blue fill:#1565C0,stroke:#E0E0E0,stroke-width:2px,color:#E0E0E0;
classDef wheat fill:#FFB74D,stroke:#424242,stroke-width:2px,color:#000000;
classDef green fill:#4CAF50,stroke:#E0E0E0,stroke-width:2px,color:#FFFFFF;
class Client blue;
class Manager,Sensor,Controller,CtrlListener,EventListener wheat;
class Hardware green;
Lifecycle and State Machine
| State | Description |
|---|---|
| STOPPED | Detection inactive; configuration changes allowed. |
| STARTING | Arming detection (stabilization windows may apply). |
| STARTED | Detection active; events may be delivered. |
| STOPPING | Disarming detection. |
| ERROR | Failure occurred; requires recovery or re-init. |
IMotionSensorControllerListener.onStateChanged(oldState, newState) fires for every transition.
Controller Pattern
The motion sensor uses an exclusive controller pattern:
IMotionSensor.open(controllerListener)— acquires exclusiveIMotionSensorController- Controller provides:
start(),stop(),getStartConfig(),getLastEventInfo(), sensitivity, deep sleep autonomy, active windows IMotionSensor.close(controller)— releases the controller- If the owning client crashes, the HAL implicitly calls
stop()+close()
Event listeners (IMotionSensorEventListener) are registered separately on IMotionSensor and do not require ownership — any client can observe motion events.
Capabilities Structure
parcelable Capabilities {
String sensorName;
int minSensitivity; // 0 if unsupported
int maxSensitivity; // 0 if unsupported
boolean supportsDeepSleepAutonomy;
}
- Capabilities are immutable for the process lifetime.
- Sensitivity is unsupported when both min/max are
0.
StartConfig and Operational Modes
IMotionSensorController.start(StartConfig config):
parcelable StartConfig {
OperationalMode operationalMode;
int noMotionSeconds;
int activeStartSeconds;
int activeStopSeconds;
}
- operationalMode:
MOTION: fire event when motion is detected after activation window.NO_MOTION: fire event after contiguousnoMotionSecondsof inactivity.- noMotionSeconds: inactivity window (only for
NO_MOTION);0disables it. - activeStartSeconds: delay after
start()before the sensor becomes active (0= immediate). - activeStopSeconds: automatic stop after duration (
0= continuous untilstop()).
The current config is retrievable via IMotionSensorController.getStartConfig().
Diagnostics
IMotionSensorController.getLastEventInfo() returns the mode and timestamp of the most recent event, or null if no event has occurred since start(). Elapsed time since the event is System.nanoTime() - timestampNs.
Active Time Windows
IMotionSensorController.setActiveWindows() schedules when the sensor should actively report events:
parcelable TimeWindow {
int startTimeOfDaySeconds; // 0-86399 (seconds since midnight)
int endTimeOfDaySeconds; // 0-86399 (seconds since midnight)
}
- Multiple Windows: Array of
TimeWindowobjects; events fire during ANY configured window (union semantics) - Midnight Wrapping: Windows can span midnight when
endTime < startTime(e.g., 22:00-02:00) - 24-Hour Monitoring: Empty array or single window with both values = 0
- Configuration Timing: Must be set in
STOPPEDstate; takes effect on nextstart() - Event Suppression: Outside active windows, the sensor may continue detecting but SHALL NOT deliver events
- Window Callbacks:
IMotionSensorControllerListener.onActiveWindowEntered()/onActiveWindowExited()fire on transitions (only when windows are configured)
DST Shifts
On days when DST shifts occur (23-hour or 25-hour days), applications should reprogram active windows to ensure reliable operation. If windows are updated daily, this occurs automatically.
Controller Listener (IMotionSensorControllerListener)
Delivered exclusively to the controller owner (passed into open()).
| Event | Description | When fired |
|---|---|---|
onStateChanged(old, new) |
Lifecycle state transition | Every start/stop/error transition |
onActiveWindowEntered() |
Sensor entered active monitoring window | Only when windows configured |
onActiveWindowExited() |
Sensor exited active monitoring window | Only when windows configured |
Event Listener (IMotionSensorEventListener)
Available to any registered observer.
| Event | Description |
|---|---|
onEvent(mode) |
Motion or no-motion condition detected |
Interaction Flow
Motion Trigger (MOTION mode)
sequenceDiagram
participant MW as Middleware
participant Sensor as IMotionSensor
participant Ctrl as IMotionSensorController
participant CtrlL as IMotionSensorControllerListener
participant EvtL as IMotionSensorEventListener
participant HW as Motion Sensor
MW->>Sensor: registerEventListener(evtListener)
MW->>Sensor: open(ctrlListener)
Sensor-->>MW: IMotionSensorController
Note over Ctrl: sensor remains in STOPPED state
MW->>Ctrl: start({MOTION, 0, 0, 0})
CtrlL-->>MW: onStateChanged(STOPPED, STARTING)
Ctrl->>HW: Arm detection
CtrlL-->>MW: onStateChanged(STARTING, STARTED)
HW-->>Ctrl: Motion detected
EvtL-->>MW: onEvent(MOTION)
MW->>Ctrl: stop()
CtrlL-->>MW: onStateChanged(STARTED, STOPPING)
CtrlL-->>MW: onStateChanged(STOPPING, STOPPED)
MW->>Sensor: close(controller)
No-Motion Window (NO_MOTION mode)
sequenceDiagram
participant MW as Middleware
participant Ctrl as IMotionSensorController
participant CtrlL as IMotionSensorControllerListener
participant EvtL as IMotionSensorEventListener
participant HW as Motion Sensor
MW->>Ctrl: start({NO_MOTION, 5, 0, 0})
CtrlL-->>MW: onStateChanged(STOPPED, STARTING)
CtrlL-->>MW: onStateChanged(STARTING, STARTED)
Ctrl->>HW: Arm detection with 5s inactivity window
HW-->>Ctrl: No motion for 5s
EvtL-->>MW: onEvent(NO_MOTION)
Performance & Behaviour
- Event latency should be ≤ 500 ms from physical motion to callback under typical conditions (non-normative but recommended).
- Timing parameters in
StartConfigmust be honoured precisely. - When deep-sleep autonomy is enabled and supported, the sensor should continue operating per vendor constraints during low-power states.
Hardware Configuration Example
The HAL Feature Profile (HFP) defines platform-specific capabilities and defaults:
sensor:
motion:
- id: 0
sensorName: "PIR-Front-1"
sensitivity_range:
minSensitivity: 1
maxSensitivity: 10
supportsDeepSleepAutonomy: true
operational_modes:
- MOTION
- NO_MOTION
# Factory default StartConfig values (maps to StartConfig.aidl fields)
defaultStartConfig:
operationalMode: MOTION
noMotionSeconds: 5
activeStartSeconds: 0
activeStopSeconds: 0
active_windows:
- startTimeOfDaySeconds: 32400 # 09:00
endTimeOfDaySeconds: 61200 # 17:00
- startTimeOfDaySeconds: 72000 # 20:00
endTimeOfDaySeconds: 79200 # 22:00
requirements:
min_reaction_time_ms: 500
notes:
- "Front-facing PIR motion detector."
- "Supports autonomous operation during deep sleep."
| Section | Purpose | Mutability |
|---|---|---|
id, sensorName, sensitivity_range, supportsDeepSleepAutonomy |
Hardware capabilities via getCapabilities() |
Immutable at runtime |
operational_modes, defaultStartConfig, active_windows |
Platform defaults for testing/validation | Configuration values |
Validation Checklist
| Test | Expected Behaviour |
|---|---|
| Capabilities Stability | Values constant across calls. |
| Open/Close Lifecycle | open() returns controller; close() releases it; double-open fails. |
| Start/Stop Sequence | State transitions follow the model; onStateChanged() fires for each. |
| StartConfig Retrieval | getStartConfig() matches the config passed to start(). |
| LastEventInfo | Returns null before first event; populated after onEvent() fires. |
| Sensitivity Control | Enforced only in STOPPED; range-checked or returns false if unsupported. |
| Listener Semantics | Idempotent register/unregister; single delivery per event condition. |
| NO_MOTION Window | Event fires only after contiguous inactivity equals noMotionSeconds. |
| Deep-Sleep Autonomy | setAutonomousDuringDeepSleep() behaviour matches capability flag. |
| Active Window Callbacks | onActiveWindowEntered/onActiveWindowExited fire at window boundaries. |
| Crash Cleanup | Controller owner crash triggers implicit stop() + close(). |