Current contract
The minimal provider contract lives in core:plugin-api.
interface Plugin {
val id: String
val types: Set<String>
suspend fun pull(type: String, sinceMs: Long, untilMs: Long): List<Event>
}
The interface expresses the interval [sinceMs, untilMs). Inspect how each provider actually applies those arguments. This is not the initialization API of a distributed external DTRAC SDK.
Activation filters
Ordinary app initialization combines registry enablement, allowlist, build feature settings, and Plugin.types. It reads the intersection of registry types and types advertised by the plugin.
The sensor starter receives selected types through configure(). Its unconfigured compatibility path allows all types, so an external host integration needs an explicit initialization/start/stop contract.
Extension workflow
- Define a provider ID, data meaning, units, time range, and required permissions.
- Implement
Pluginand the provider adapter, then register through the existing Hilt pattern. - Align the registry, allowlist, feature toggles, and actual
types. - Connect persistence through existing repositories/ingestion. Review entities, DAOs, and migrations for new data shapes.
- Determine whether remote synchronization and JSON bindings are required.
- Test missing permission, successful empty results, read failures, retries, and duplicates separately.
Returned data versus persisted data
Some implementations persist during a pull; the sensor plugin reads summaries of existing Room batches. Returning List<Event> does not automatically store it. Survey responses use a separate submission path; an existing in-memory EventStore should not become a public durable-response API.
Distribution of internal modules to another app is covered separately in the Android SDK plan.