Change by task
July 29, 2026 · View on GitHub
Before editing code, write the complete path: who creates the request, which Hook is called, who applies the result, and where the user sees the change. A contract with no host caller or result applier is still a placeholder.
Add or change a Hook
Work in this order:
- Define request, result, and
HookSpecin:extension:api. Put general features inHostHookContracts.ktand provider features undersubscription/. - Add that official
HookSpecand its base capabilities to the singleExtensionContractCatalogentry list. Its supported-schema and capability views are derived from this list. - Cover affected registration, version, capability, error, size, timeout, and cancellation behavior in
ExtensionRuntimeTest. - Add a real host caller; the manifest declaration only advertises that the Hook is available.
- Add a scoped host applier and test errors, oversized results, partial failure, and successful empty results.
- Update an APK example with
TypedExtensionService, then cover cross-process behavior inextension-reference. - Update the English and Chinese developer feature page and maintainer status page.
Additive compatible fields need defaults. Raise the Hook schema version when an old implementation cannot safely handle the new shape; raise the API major only for platform-wide incompatibility.
Change the built-in Emby/Jellyfin provider
The complete path is:
SubscriptionProviderRepositoryImpl
-> ExtensionRuntime.invoke(SubscriptionHookSpecs.*)
-> EmbyCompatibleProvider -> EmbyCompatibleClient
<- typed result
SubscriptionProviderRepositoryImpl -> SubscriptionProviderImporter
Start in EmbyCompatibleProviderIntegrationTest for HTTP behavior and SubscriptionProviderRepositoryIntegrationTest for persistence and lifecycle.
New provider kinds are driven by descriptors and declarative settings. The generic source selector,
form state, subscription repository, and importer do not branch on concrete ProviderKind; only
the provider implementation does. New subscriptions are stored as DataSource.Provider.
DataSource.Emby and DataSource.Jellyfin remain legacy compatibility inputs.
Change APK discovery, trust, or IPC
| Change | Main files |
|---|---|
| Service action, discovery, and package identity | ExtensionProtocol, AndroidExtensionDiscovery |
| Explicit binding, handshake, PFD, and calls | AndroidBoundExtensionTransport |
| APK-side Binder implementation | ExtensionService |
| APK-side typed Hook registration | TypedExtensionService |
| Certificate pinning and user authorization | ExtensionTrustStore, ExtensionPluginRepositoryImpl |
| Cross-process fixture | testing/extension-reference |
Every lifecycle change must cover normal return, cancellation, timeout, Binder death, disable, revocation, and process restart. Use ExtensionConnectionStateTest for connection state and ExternalExtensionIpcTest for the cross-process path.
Change a result applier
An applier must define the current request scope, result owner, and old-data replacement scope.
At minimum, cover that:
- a failure or exception preserves previous valid data;
- one extension failure does not affect another extension;
- a successful empty result clears only the current owner's data;
- cancellation continues upward;
- count or field overflow is not treated as a complete truncated success;
- deletion and insertion happen in one transaction.
For persistent channel, provider, and EPG work, start with SubscriptionProviderImporter, ExtensionContributionRepositoryImplTest, and ExtensionContributionImporterTest.
Change settings, credentials, or the network broker
ExtensionSettingsRepositoryImpl owns settings schema and ordinary values. Host vaults encrypt secret settings and provider tokens. Extension contracts carry credential handles, never plaintext secrets.
When changing the broker, add denial cases to HostNetworkBrokerSecurityTest before implementing behavior. Changes to owner, origin, redirect, authentication headers, response size, or credential capture must also be checked against the external extension release gates.
Change phone or TV UI
UI observes repository state and sends operations; it does not discover or bind services directly.
- On phone, start with
SubscriptionsFragmentandExtensionSettingsDialog. - On TV, start with
TvHomeViewModelandTvScreens.
Check full-row clicks, scrollable authorization, visible errors, and settings persistence on phone. Check DPad order, focus contrast, back behavior, and long text on TV.
Validation evidence
| Change | Closest evidence |
|---|---|
| API or runtime | ExtensionContractTest, ExtensionRuntimeTest |
| APK SDK and typed handlers | TypedExtensionServiceTest, hello-extension |
| Certificate trust and connection state | CertificateSetFingerprintTest, ExtensionTrustStoreTest, ExtensionConnectionStateTest |
| Cross-process discovery, binding, PFD, invocation, and cancellation | ExternalExtensionIpcTest, extension-reference |
| External provider lifecycle | ExternalProviderEndToEndTest, extension-reference, mock-server |
| Built-in provider and importer | EmbyCompatibleProviderIntegrationTest, SubscriptionProviderRepositoryIntegrationTest, and the applier tests linked above |
| Phone or TV product flow | The product UI test for the changed trigger and visible result |