Project 10: Plugin SDK and IPC Host

Build a versioned Android plugin protocol and a separately installed demo plugin, then prove the host contains untrusted failures and verifies identity at every boundary.

Quick Reference

  • Main language: Kotlin
  • Alternative language: Java
  • Difficulty: Level 4 - Expert
  • Estimated time: 28-40 hours
  • Primary APIs: bound services, Binder, AIDL or Messenger, PackageManager
  • Supporting tools: Gradle multi-repository fixtures, Compose catalog, instrumentation tests
  • Main book: Enterprise Integration Patterns by Gregor Hohpe and Bobby Woolf
  • Safety boundary: targeted discovery, explicit enrollment, signer trust, bounded versioned messages

1. Learning Objectives

You will learn to:

  1. Design an Android plugin as a protocol rather than a shared implementation shortcut.
  2. Compare AIDL, Messenger, intents, and content-provider boundaries.
  3. Discover candidate plugins through targeted declarations without broad package inventory.
  4. Verify package, component, signer, protocol version, and declared capability.
  5. Recheck caller identity on each sensitive Binder request.
  6. Negotiate compatible protocol ranges before invocation.
  7. Bound message count, string length, collection size, and payload bytes.
  8. Correlate request, progress, cancellation, and result.
  9. Handle Binder death, timeout, malformed replies, and plugin uninstall.
  10. Prevent replay and confused-deputy behavior.
  11. Preserve user configuration when a plugin becomes unavailable.
  12. Build hostile-plugin tests that prove containment.

Mastery signal: The host invokes one enrolled demo capability successfully and rejects or contains wrong-signature, incompatible, oversized, malformed, replayed, timed-out, crashed, and uninstalled plugins.


2. Theoretical Foundation

2.1 A Plugin Boundary Is a Trust Boundary

Separately installed code runs in another application identity and process. Even if you authored both apps, production must assume version skew, crashes, malformed data, compromised builds, replacement packages, and hostile callers.

Do not expose internal repositories or framework objects. Define a narrow message protocol with explicit semantics and failure outcomes.

host domain <-> host adapter <== Binder protocol ==> plugin adapter <-> plugin domain
                trust check       bounded data       caller check

2.2 Why Binder IPC

Binder gives Android process isolation, caller identity, lifecycle signals, and efficient IPC. It does not automatically provide semantic trust, compatible versions, bounded payloads, or safe business behavior.

Candidate approaches:

  • AIDL: explicit typed interfaces; best when protocol evolution is disciplined.
  • Messenger: serialized message handling; useful for simple command channels.
  • Explicit intents: good for coarse fire-and-result interactions.
  • Content provider: appropriate for query-like data contracts, not arbitrary execution.

Select one and document why. The learning project can use AIDL or Messenger, but the domain protocol should remain transport-independent.

2.3 Targeted Discovery and Package Visibility

Modern Android limits visibility into installed apps. A plugin host should not request broad inventory merely for convenience. Use a specific intent action or service contract and declare only the narrow queries needed for discovery.

Discovery yields candidates, not trusted plugins. The user should review candidate identity and explicitly enroll one before execution.

2.4 Identity and Signer Trust

A package name alone is not a durable trust guarantee. A plugin enrollment record should bind:

  • package name;
  • explicit service component;
  • accepted signing-certificate digest or lineage policy;
  • supported protocol range;
  • approved capability IDs;
  • enrollment timestamp and user decision.

Re-read current package and signer information before binding and on reconnect. Never trust signer metadata supplied by the plugin itself.

2.5 Caller Authentication

The plugin must also defend itself. On every Binder transaction, it should obtain the actual calling UID, resolve packages associated with that UID, and apply its host trust policy. A field saying callerPackage=trusted.host is merely attacker-controlled data.

Be careful when work is handed to another thread: capture and verify identity at the Binder entry boundary before identity context is lost.

2.6 Version Negotiation

Versioning should describe protocol compatibility, not app marketing versions.

host supports:   [2, 4]
plugin supports: [3, 5]
intersection:    [3, 4]
selected:        highest mutually supported version 4

If the intersection is empty, fail before sending an execution request. Capability versions may evolve independently from the transport protocol.

2.7 Bounded Messages

Binder transactions have practical size limits and share a transaction buffer within a process. A robust protocol defines strict bounds well below platform failure thresholds.

Bound:

  • maximum request bytes;
  • maximum reply bytes;
  • maximum strings and string length;
  • maximum collection entries;
  • maximum nesting depth;
  • maximum progress events;
  • maximum execution duration;
  • maximum concurrent requests per plugin.

Large data should move through a purpose-built, permission-scoped channel, not an oversized Binder parcel.

2.8 Correlation, Timeout, and Cancellation

Each request needs a host-generated unguessable correlation ID and deadline. The plugin reports one terminal result for that request. Cancellation is best-effort but explicit. A late reply after timeout must not resurrect a completed host run.

The host owns its deadline. A plugin cannot extend it by continually sending progress.

2.9 Binder Death and Process Failure

Binding can fail, the remote process can die, or a transaction can throw. Link to death where appropriate, but still model all remote calls as fallible. After death:

  • mark active requests with a typed plugin-unavailable outcome;
  • clear transient proxy references;
  • release connection resources;
  • apply bounded rebind policy;
  • reverify identity before future use.

2.10 Confused Deputy and Scope

A confused deputy occurs when a less-privileged caller convinces a privileged component to act on its behalf. Prevent it by validating the real caller, authorizing named capabilities, bounding arguments, and refusing generic shell, intent, file, or network execution.

A plugin action should be a narrow operation such as transform.text_length, not execute_arbitrary_command.

2.11 Replay Defense

A request ID that has already reached a terminal state must not execute again accidentally. Maintain a bounded replay ledger per enrolled plugin or require the plugin to enforce idempotency for its capability. Define expiry and process-death behavior explicitly.

2.12 Common Misconceptions

Misconception: Package name is sufficient authentication.

Correction: verify installed signer and actual Binder caller identity.

Misconception: AIDL makes a protocol backward compatible.

Correction: wire typing does not replace version negotiation and semantic evolution rules.

Misconception: Discovery means a plugin is trusted.

Correction: discovery produces untrusted candidates that require validation and enrollment.

Misconception: Binder calls are local and therefore reliable.

Correction: remote process death, timeouts, and malformed behavior are normal cases.

Misconception: The plugin can report its own signer.

Correction: identity evidence must come from trusted platform APIs.

2.13 Key Terms

  • Binder: Android kernel-mediated IPC mechanism.
  • AIDL: interface definition language for Binder contracts.
  • Caller UID: OS identity of the process making the Binder call.
  • Signer digest: fingerprint derived from an installed package’s signing certificate.
  • Capability ID: stable name for a narrow plugin-provided operation.
  • Protocol range: minimum and maximum compatible protocol versions.
  • Binder death: loss of the remote process hosting an IPC endpoint.
  • Confused deputy: privileged component tricked into misusing its authority.
  • Replay: repeated processing of a previously accepted request.
  • Enrollment: explicit user decision to trust a validated plugin identity and scope.

3. Project Specification

3.1 What You Will Build

Build two separately installed applications:

Plugin Host

  • targeted discovery catalog;
  • identity and signer inspection;
  • explicit enrollment workflow;
  • protocol negotiation;
  • capability catalog;
  • test invocation UI;
  • typed result and diagnostic viewer;
  • disabled-state handling after uninstall or trust change.

Demo Plugin

  • one synthetic trigger capability;
  • one action capability named transform.text_length;
  • host caller verification;
  • bounded request parser;
  • cancellation and timeout cooperation;
  • debug-only hostile behavior modes for tests.

3.2 Functional Requirements

  • Discover only services matching the exact plugin contract.
  • Show package, service, signer digest, protocol range, and capabilities.
  • Require explicit enrollment before binding for execution.
  • Persist trusted signer and approved scopes.
  • Reverify installed identity before every new connection.
  • Negotiate one protocol version from the intersection.
  • Send bounded versioned requests with correlation IDs and deadlines.
  • Return typed success and failure results.
  • Support cancellation.
  • Detect Binder death and timeout.
  • Reject replayed request IDs.
  • Reject malformed, oversized, or unknown fields according to protocol rules.
  • Safely disable dependent rules when plugin is uninstalled.
  • Preserve those rules for later repair or re-enrollment.

3.3 Non-Functional Requirements

  • No QUERY_ALL_PACKAGES dependency.
  • No generic command, shell, file, or arbitrary-intent capability.
  • No sensitive data in the demo protocol.
  • Every external collection and string has a maximum size.
  • Every call has a deadline.
  • Remote code cannot block the host main thread.
  • Diagnostics identify the plugin and correlation without exposing payload content.
  • Host and plugin tests can run from independently versioned fixtures.

3.4 Demo Interaction

Candidate plugin
  package: dev.example.lengthplugin
  service: .AutomationPluginService
  signer: sha256/9C:...
  protocol: 2..3
  capabilities: transform.text_length
  trust: not enrolled

User enrolls capability: transform.text_length

Request
  protocol: 3
  request_id: req-17
  input: synthetic text, 12 bytes
  deadline: 2 seconds

Result
  request_id: req-17
  status: completed
  output: length=12

Hostile case:

Result: plugin_rejected
Reason: signer_changed
Dependent rule: disabled, configuration preserved
Resolution: review and enroll the new signer explicitly

3.5 Hostile Test Modes

  • wrong signer fixture;
  • incompatible protocol range;
  • malformed catalog;
  • unknown capability;
  • oversized request demand;
  • oversized response;
  • delayed response past deadline;
  • plugin process crash;
  • duplicate terminal response;
  • replayed request ID;
  • uninstall during an active request.

3.6 Real-World Outcome

A reviewer installs the host and demo plugin, sees a targeted candidate, reviews signer and capabilities, enrolls only the text-length action, and completes a correlated request. The reviewer then runs every hostile mode and observes typed containment. Uninstalling the plugin disables, but does not erase, dependent automation rules.


4. Solution Architecture

4.1 High-Level Architecture

                  Android PackageManager
                           |
                 targeted intent query
                           |
                    candidate catalog
                           |
              identity + signer verifier
                           |
                   user enrollment store
                           |
 automation rule --> plugin host gateway
                           |
              protocol/version negotiator
                           |
              request limiter + correlator
                           |
                    Binder client adapter
====================== process boundary ======================
                    Binder service stub
                           |
             actual caller UID + signer check
                           |
                 bounded protocol decoder
                           |
                 capability authorization
                           |
               demo plugin action executor
                           |
                 correlated typed result

4.2 Component Responsibilities

Component Responsibility Must Not Do
Discovery adapter query exact declared plugin contract enumerate all packages
Identity verifier read component and signer from platform trust plugin self-report
Enrollment store bind user trust to identity and scope auto-trust new signer
Negotiator select mutual protocol version guess compatibility
Host gateway enforce bounds, deadline, correlation call remote service on main thread
Binder adapter transport typed messages expose host internals
Plugin caller guard verify real calling UID trust request package field
Capability registry authorize named operations expose arbitrary execution
Replay ledger reject completed request IDs grow without expiry bound
Health projector disable unavailable dependencies delete user configuration

4.3 Discovery Manifest Contract

Illustrative configuration, not a copy-paste production manifest:

<queries>
  <intent>
    <action android:name="dev.example.AUTOMATION_PLUGIN" />
  </intent>
</queries>

<service
  android:name=".AutomationPluginService"
  android:exported="true">
  <intent-filter>
    <action android:name="dev.example.AUTOMATION_PLUGIN" />
  </intent-filter>
</service>

Production design must add an appropriate signature permission or equivalent trust control and validate actual callers.

4.4 Protocol Schemas

PluginDescriptor {
  protocolMin
  protocolMax
  pluginInstanceId
  capabilities[]
  maxRequestBytes
  maxConcurrentRequests
}

CapabilityDescriptor {
  capabilityId
  capabilityVersion
  inputSchemaId
  outputSchemaId
  declaredEffects
}

PluginRequest {
  protocolVersion
  requestId
  capabilityId
  capabilityVersion
  deadlineElapsed
  payload
}

PluginResult {
  protocolVersion
  requestId
  status
  boundedPayload?
  typedError?
}

4.5 Enrollment Record

PluginEnrollment {
  packageName
  serviceComponent
  acceptedSignerDigest
  signerLineagePolicy
  approvedCapabilities[]
  protocolRangeAtEnrollment
  enrolledAt
  status
}

4.6 Host Invocation Algorithm

resolve enrollment by plugin ID
query current explicit service component
verify package and current signer against enrollment
bind using explicit component
obtain descriptor within handshake deadline
validate descriptor bounds and negotiate version
verify requested capability is enrolled and advertised
create request ID and monotonic deadline
record in-flight request before dispatch
send bounded request off main thread
accept at most one matching terminal result before deadline
on timeout, death, mismatch, or malformed data: close request with typed failure
ignore late terminal replies

4.7 Plugin Entry Algorithm

on Binder entry:
  capture actual calling UID
  verify UID resolves to an enrolled trusted host signer
  parse message within size and structure bounds
  validate negotiated version and capability scope
  reject replayed request ID
  enforce concurrency and deadline
  execute named capability only
  emit one bounded correlated terminal result

4.8 Failure Taxonomy

Class Examples Host behavior
identity signer changed, component moved reject and require review
compatibility no version intersection disable with upgrade guidance
protocol malformed, unknown, oversized reject and record safe diagnostic
availability bind failure, crash, uninstall fail active run; retain configuration
timing handshake or execution timeout cancel, close correlation, ignore late reply
authorization unapproved capability, wrong caller deny without execution
replay duplicate request or result reject or ignore by terminal state

4.9 Critical Invariants

  1. Discovery never implies trust.
  2. Package name alone never implies signer identity.
  3. Every sensitive Binder entry validates actual caller identity.
  4. Every request is bounded, correlated, timed, and scoped.
  5. No remote call blocks the main thread.
  6. Exactly one terminal result closes a request.
  7. Late replies cannot revive timed-out work.
  8. Plugin loss disables dependent execution without deleting rules.

5. Implementation Guide

5.1 Environment Setup

  • Use current stable Android Studio and SDK Platform 36.
  • Create host and plugin as separately installable apps.
  • Use independent application IDs and signing fixtures.
  • Generate at least two debug keystores for signer-change tests.
  • Add a second plugin fixture with incompatible protocol range.
  • Use an emulator without personal data.

5.2 Suggested Repository Structure

plugin-lab/
  protocol-spec/
    schemas/
    compatibility.md
    limits.md
  host-app/
    discovery/
    identity/
    enrollment/
    negotiation/
    gateway/
    health/
    ui/
  demo-plugin/
    caller-guard/
    protocol/
    capabilities/
  hostile-fixtures/
  tests/

5.3 Core Question

How can separately installed automation plugins cooperate without becoming a confused deputy, a brittle shared implementation, or an unbounded crash path?

5.4 Concepts to Understand First

  1. Android application UID and process isolation.
  2. Bound-service and Binder lifecycle.
  3. AIDL or Messenger transport semantics.
  4. Package visibility and targeted queries.
  5. APK signing identity and certificate rotation.
  6. Protocol compatibility and schema evolution.
  7. Deadlines, cancellation, replay, and backpressure.
  8. Capability-based authorization.

5.5 Design Questions

  • Why is the chosen transport appropriate?
  • What exactly makes a candidate trusted?
  • How does the plugin authenticate the actual host caller?
  • What are every message’s explicit bounds?
  • Which fields may be ignored for forward compatibility?
  • Which unknown fields or values must fail closed?
  • How is one terminal result enforced?
  • What happens to rules after signer change or uninstall?
  • How does certificate rotation affect enrollment?

5.6 Thinking Exercise

Trace platform identity, durable state, transient state, and final outcome for:

  • valid plugin first enrollment;
  • attacker installs a same-looking package with another signer;
  • plugin upgrades from protocol 2..3 to 3..4;
  • plugin sends a result after host timeout;
  • host process dies after dispatch;
  • plugin process dies during execution;
  • plugin is uninstalled while a rule references it;
  • request ID is replayed after a successful result.

5.7 Interview Questions

  1. Why is an AIDL interface not a complete security boundary?
  2. How do you authenticate a Binder caller?
  3. Why should plugin discovery be targeted?
  4. How do you evolve a plugin protocol safely?
  5. What happens when the remote Binder dies?
  6. How do deadlines and correlation prevent stale replies?
  7. What is the confused-deputy risk in an automation host?

5.8 Hints in Layers

Hint 1 - Write the protocol before apps

Define messages, limits, errors, and compatibility examples.

Hint 2 - Build discovery without binding

Catalog candidates and verify identity first.

Hint 3 - Add explicit enrollment

Persist signer and capability scope from a user decision.

Hint 4 - Implement one tiny capability

Text length is deterministic, bounded, and harmless.

Hint 5 - Make the plugin hostile

Reliability evidence comes from malformed, slow, and crashing fixtures.

5.9 Books That Will Help

Topic Book Suggested focus
Messaging Enterprise Integration Patterns request/reply, correlation, adapters
Security Security Engineering trust boundaries and authentication
Reliability Release It! remote calls, timeouts, bulkheads
Evolution Building Evolutionary Architectures compatibility and fitness functions

5.10 Implementation Phases

Phase 1 - Protocol specification

  • Choose AIDL or Messenger.
  • Define descriptor, request, result, and error schemas.
  • Define compatibility rules.
  • Define strict size and timing limits.

Phase 2 - Targeted discovery

  • Declare the exact plugin intent query.
  • Resolve matching service candidates.
  • Read package and signer from platform APIs.
  • Display an untrusted catalog.

Phase 3 - Enrollment

  • Show identity and capabilities.
  • Record explicit user approval.
  • Bind approval to signer and component.
  • Approve only selected capability IDs.

Phase 4 - Demo plugin guard

  • Verify actual caller UID.
  • Resolve trusted host signer.
  • Add concurrency and replay limits.
  • Reject untrusted entry before parsing expensive data.

Phase 5 - Handshake and negotiation

  • Bind by explicit component.
  • Retrieve a bounded descriptor.
  • Compute version intersection.
  • Reject incompatibility before execution.

Phase 6 - Request pipeline

  • Create correlation and deadline.
  • Validate request bounds.
  • Dispatch off main thread.
  • Accept one correlated terminal result.

Phase 7 - Failure containment

  • Handle timeout and cancellation.
  • Link to remote death.
  • Ignore late and duplicate replies.
  • Reverify identity before rebind.

Phase 8 - Hostile fixtures

  • Change signer.
  • Change protocol range.
  • Send malformed and oversized data.
  • Delay, crash, replay, and uninstall.

Phase 9 - Rule integration

  • Reference plugin and capability IDs in a rule.
  • Disable execution when unhealthy.
  • Preserve configuration and resolution guidance.
  • Restore only after trust revalidation.

5.11 Key Decisions

  • Protocol contract instead of shared internals.
  • Targeted discovery instead of broad inventory.
  • Platform-derived signer evidence.
  • User enrollment scoped to capabilities.
  • Actual Binder caller verification.
  • Strict message and concurrency bounds.
  • Monotonic deadlines and one terminal result.
  • Safe degradation without configuration loss.

6. Testing Strategy

6.1 Protocol Contract Tests

  • Lowest supported mutual version succeeds.
  • Highest supported mutual version succeeds.
  • Empty version intersection fails.
  • Required unknown enum value fails safely.
  • Permitted unknown optional field is ignored.
  • Strings, lists, nesting, and payload bytes respect limits.
  • Exactly one terminal result is accepted.

6.2 Identity Tests

  • Enrolled package and signer succeed.
  • Same package fixture with different signer fails.
  • Component change requires policy evaluation.
  • Plugin-supplied signer claim is ignored.
  • Plugin rejects host fixture with wrong signer.
  • Caller package field cannot spoof actual Binder UID.

6.3 Lifecycle Tests

  • Bind, invoke, unbind, and rebind.
  • Kill plugin before handshake.
  • Kill plugin during request.
  • Kill host after dispatch.
  • Uninstall plugin during request.
  • Reinstall with same signer.
  • Reinstall with different signer.

6.4 Hostile Protocol Tests

  • Malformed descriptor.
  • Oversized capability catalog.
  • Unknown capability response.
  • Mismatched correlation ID.
  • Duplicate terminal result.
  • Result after deadline.
  • Progress flood.
  • Replay of completed request ID.
  • Plugin refuses cancellation.

6.5 Rule-Degradation Tests

  • Referenced plugin unavailable at startup.
  • Plugin uninstalled while rule enabled.
  • Signer changes after enrollment.
  • Protocol becomes incompatible after upgrade.
  • Capability disappears from catalog.
  • Configuration survives every case.
  • Execution resumes only after valid resolution.

6.6 Security Review Checklist

  • Enumerate exported components.
  • Verify explicit binding.
  • Verify signer lookup uses platform state.
  • Verify actual caller UID at Binder entry.
  • Verify no arbitrary command capability.
  • Verify strict message limits.
  • Verify diagnostics contain no request payload.
  • Verify replay ledger is bounded.

6.7 Acceptance Transcript

Save a transcript for valid enrollment and invocation plus wrong signer, no version overlap, malformed, oversized, timeout, crash, replay, late result, and uninstall. Include correlation IDs, typed outcomes, and rule-health projections.


7. Common Pitfalls & Debugging

Problem 1: Candidate never appears

  • Why: intent query, service action, exported state, or package visibility differs.
  • Fix: compare the exact action and resolve through PackageManager diagnostics.
  • Quick test: install only the demo plugin and query the explicit contract.

Problem 2: Host trusts a replacement build

  • Why: enrollment stored only package name.
  • Fix: bind trust to platform-derived signer evidence and recheck it.
  • Quick test: reinstall a same-ID hostile fixture signed differently.

Problem 3: Plugin accepts a spoofed host field

  • Why: it trusts message data rather than Binder caller UID.
  • Fix: authenticate at the Binder entry boundary.
  • Quick test: invoke from an untrusted caller claiming the host package.

Problem 4: Host freezes on a plugin call

  • Why: remote work runs on the main thread or lacks a deadline.
  • Fix: isolate calls and close them on host-owned deadlines.
  • Quick test: enable delayed hostile mode while profiling UI responsiveness.

Problem 5: Late result changes a failed run to success

  • Why: correlation state remains open after timeout.
  • Fix: terminally close the request and ignore later replies.
  • Quick test: deliver success one second after deadline.

Problem 6: Uninstall deletes rules

  • Why: plugin health is coupled to rule identity.
  • Fix: retain configuration and project an unavailable dependency.
  • Quick test: uninstall and reinstall the enrolled plugin.

Problem 7: Large parcel fails unpredictably

  • Why: protocol has no conservative payload bounds.
  • Fix: validate before transport and use a different channel for large data.
  • Quick test: exercise values immediately below and above each documented limit.

8. Extensions & Challenges

Extension 1: Capability Schema Registry

Add versioned schemas for a few harmless synthetic operations and compatibility fixtures.

Extension 2: Certificate Rotation Policy

Model signing-certificate lineage and require explicit rules for accepted rotation.

Extension 3: Plugin Health Dashboard

Show last handshake, version, latency, death count, timeout count, and disabled dependencies.

Extension 4: Fuzzed Decoder Fixtures

Generate bounded malformed messages and prove parsers fail without crashing either app.

Extension 5: SDK Documentation

Publish a protocol-only developer guide with limits, threat model, conformance tests, and sample transcripts.

Forbidden Extensions

  • Arbitrary shell or ADB execution.
  • Generic file-system or intent proxying.
  • Broad package inventory for discovery.
  • Auto-trusting any package with a matching name.
  • Unbounded payloads, concurrency, retries, or execution time.

9. Real-World Connections

Android plugin ecosystems appear in automation apps, keyboards, launchers, password managers, enterprise tools, and media applications. Sustainable ecosystems require a stable protocol, independent release cadence, conformance tests, trust enrollment, compatibility telemetry, and deprecation policy.

The lessons also apply to microservices and browser extensions: network or process isolation creates a boundary, but the protocol still needs authentication, authorization, limits, timeouts, correlation, and evolution rules.

Production Gap Analysis

Learning build Production requirement
one demo plugin third-party SDK governance and review
debug signer fixtures release signing and rotation operations
local catalog localized consent and support diagnostics
one protocol version family deprecation windows and compatibility telemetry
simple replay ledger durable idempotency and abuse controls

10. Resources

Official Android Documentation

Official Policy

Suggested Reading Order

  1. Read bound-service and Binder lifecycle guidance.
  2. Compare AIDL and Messenger.
  3. Study package visibility and narrow query use cases.
  4. Review signing identity and rotation.
  5. Revisit the parent guide’s IPC, security, and observability chapters.

11. Self-Assessment Checklist

Knowledge

  • I can explain why IPC is a trust boundary.
  • I can compare AIDL, Messenger, and explicit intents.
  • I understand package visibility and targeted discovery.
  • I can authenticate an actual Binder caller.
  • I can explain version intersection and Binder death.

Design

  • Discovery, validation, enrollment, and execution are distinct phases.
  • Enrollment binds package, component, signer, and capability scope.
  • Every message and execution dimension has a bound.
  • Every request has correlation, deadline, and cancellation semantics.
  • The protocol exposes no arbitrary execution primitive.

Verification

  • I tested wrong signer and wrong caller.
  • I tested incompatible versions.
  • I tested malformed and oversized messages.
  • I tested timeout, crash, replay, and late reply.
  • I tested uninstall without rule deletion.

Reflection

  • I can defend the selected transport.
  • I documented certificate-rotation assumptions.
  • I can identify one confused-deputy path that was closed.
  • I can describe how protocol version 4 could evolve safely.

12. Submission / Completion Criteria

Submit:

  1. Protocol specification with compatibility rules.
  2. Complete message, size, concurrency, and timing limits.
  3. Targeted discovery and package-visibility design.
  4. Identity, signer, and caller-authentication threat model.
  5. Enrollment and capability-scope schema.
  6. Host and plugin sequence diagram.
  7. Failure taxonomy and recovery rules.
  8. Hostile-fixture automated test report.
  9. Redacted acceptance transcript.
  10. SDK conformance checklist for future plugin authors.

Definition of Done

  • Targeted discovery works without broad package inventory.
  • Package, component, signer, protocol range, and capability scope are verified.
  • Sensitive Binder entries authenticate the actual caller.
  • Requests are versioned, bounded, correlated, timed, cancellable, and replay-aware.
  • Wrong signer, incompatible version, malformed, oversized, timeout, crash, replay, and late reply are contained.
  • Remote calls never block the host main thread.
  • Exactly one terminal result closes each request.
  • Plugin uninstall safely disables dependent rules without deleting configuration.
  • No arbitrary command or confused-deputy primitive exists.
  • Another developer can implement a conforming plugin from the protocol document alone.

Expanded from ANDROID_AUTOMATION_APPS_MASTERY.md. For the complete learning path, see the parent guide.