Sprint: Android Automation Apps Mastery - Real World Projects

Goal: Build a first-principles understanding of how native Android automation applications work, from event collection and deterministic rule evaluation to background scheduling, inter-app plugins, notification access, and consentful UI automation. You will learn why Tasker- and AutoInput-style tools are not powered by one magic permission, but by a portfolio of narrowly scoped platform capabilities with different lifecycle, privacy, distribution, and failure rules. Across fifteen cumulative projects you will build a Kotlin and Jetpack Compose automation studio whose behavior is observable, revocable, testable, and honest about degraded modes. By the end, you will be able to design consumer automation features, enterprise device-management adapters, and developer-only bridges without confusing their authority boundaries.

Introduction

An Android automation app converts signals into controlled actions. A signal might be a charger connection, a scheduled time, a notification, a user-tapped Quick Settings tile, a plugin callback, or an accessibility event. The app normalizes that signal, evaluates human-authored conditions, chooses one or more actions, checks whether it currently has the required authority, executes within Android’s lifecycle limits, and records evidence about the result.

Tasker is best understood as an event-condition-action platform. AutoInput adds a UI interaction adapter using Android accessibility capabilities. A serious automation product also needs a durable rule model, a scheduler, permission onboarding, plugin contracts, retry and deduplication semantics, security boundaries, and diagnostics. This guide teaches those foundations rather than cloning a product screen by screen.

What you will build

  • A capability and consent dashboard that distinguishes ordinary permissions, special app access, user-enabled services, roles, and managed-device authority.
  • A live context signal monitor and a deterministic event-condition-action engine.
  • Durable Room-backed rules, WorkManager and alarm scheduling, notification triggers, and user-facing command surfaces.
  • A consentful accessibility inspector and AutoInput-style deterministic macro runner against a sandbox target app.
  • A signed, versioned plugin protocol plus a secure webhook and Termux bridge.
  • A MediaProjection screen-understanding lab and a managed-device policy adapter.
  • An observability and fault-injection workbench.
  • A capstone named FlowForge Automation Studio.

In scope

  • Kotlin, coroutines and Flow, Jetpack Compose, Room, DataStore, WorkManager, AlarmManager, broadcasts, services, notifications, intents, Binder-oriented IPC, AccessibilityService, MediaProjection, Android Keystore, DevicePolicyManager, tests, and Play policy-aware design.
  • Unrooted consumer devices, managed test devices, emulators, and clearly labeled sideload/developer tracks.
  • Deterministic, human-defined rules with visible state, emergency stop, consent, redaction, and auditability.

Out of scope

  • Malware, credential or PIN automation, CAPTCHA bypass, deceptive overlays, purchase or financial confirmation automation, hidden surveillance, security-control bypasses, silent screen capture, privilege escalation, or autonomous AI planning through accessibility.
  • Treating ADB shell, device owner, root, or signature permissions as powers a normal Play-installed application can request.
  • Full runnable solutions. The guide uses pseudocode, contracts, test transcripts, and architecture sketches so the learner must implement the hard parts.
                        HUMAN-AUTHORED AUTOMATION
                                    |
                                    v
  +-----------+       +---------------------------+       +--------------+
  | Platform  | ----> | Normalize -> Evaluate ->  | ----> | Capability   |
  | signals   |       | Plan deterministic action |       | gate         |
  +-----------+       +---------------------------+       +------+-------+
                                                                   |
                    +------------------+-----------------------------+
                    |                  |                 |
                    v                  v                 v
             Built-in APIs       Plugin adapters    High-authority
             intents/work        signed IPC         adapters
             notifications       webhooks           accessibility/DPC
                    |                  |                 |
                    +------------------+-----------------+
                                       |
                                       v
                         result + audit + user feedback

The north-star rule is: prefer the narrowest Android API that can perform the user’s explicit intent; use broader authority only when the capability is central, disclosed, revocable, and technically unavoidable.

How to Use This Guide

  1. Read the complete theory primer before implementing Project 1. The chapters establish vocabulary used by every project.
  2. Build Projects 1-5 in order. They form the capability registry, event model, rule engine, persistence boundary, and scheduler used later.
  3. Choose adapters after the foundation: notifications and command surfaces, UI automation, plugins and webhooks, screen understanding, or managed devices.
  4. Run every project on both an emulator and a physical phone when possible. Emulators make provisioning and repeatable tests easy; physical phones reveal OEM background restrictions, settings UX, and real process death.
  5. Begin each build with the Core Question and Thinking Exercise. Write expected event traces and failure categories before implementation.
  6. Treat permission denial, revocation, locked-device state, missing plugin, process death, and policy restriction as expected states rather than exceptional surprises.
  7. Use the expanded project file only when starting that project. It adds architecture, milestones, test data, extensions, and submission criteria while preserving the learning challenge.

Prerequisites & Background Knowledge

Essential Prerequisites (Must Have)

  • Comfortable programming with functions, interfaces, collections, errors, asynchronous work, and automated tests.
  • Basic Kotlin syntax or prior Java experience.
  • Basic Android vocabulary: activity, service, broadcast receiver, intent, manifest, application process, runtime permission, and lifecycle.
  • Basic HTTP, JSON, and public-key/HMAC concepts for the integration projects.
  • Recommended reading: “Head First Java, 3rd Edition” by Kathy Sierra and Bert Bates — Chapters 1-7 for JVM object and interface fundamentals.
  • Recommended reading: “Effective Java, 3rd Edition” by Joshua Bloch — Items 15-25 and 78-84 for API boundaries, immutability, and concurrency discipline.

Helpful But Not Required

  • Jetpack Compose and unidirectional state flow.
  • Coroutines, Flow, Room, dependency injection, and Gradle multi-module builds.
  • State machines, event sourcing vocabulary, Binder/AIDL, Android Keystore, and enterprise device management.
  • Familiarity with Tasker, AutoInput, MacroDroid, Automate, Termux:Tasker, or Android’s developer options.

Self-Assessment Questions

  1. Can you explain why a process may disappear without an application callback and why durable state cannot live only in memory?
  2. Can you distinguish an ordinary runtime permission from a Settings-granted special capability or user-enabled service?
  3. Can you describe at-least-once delivery and explain why an action needs an idempotency strategy?
  4. Can you explain why a notification listener, an accessibility service, a media projection, and a device owner have different trust models?
  5. Can you model “when X, if Y, do Z” without coupling the rule engine to Android framework classes?
  6. Can you identify sensitive fields that must be redacted from an automation log?

Development Environment Setup

Required tools

  • Current stable Android Studio and Android SDK Platform 36 for the reference track.
  • JDK supported by the selected Android Gradle Plugin.
  • Kotlin, Jetpack Compose, AndroidX Lifecycle, coroutines/Flow, Room, DataStore, WorkManager, and Android test libraries.
  • At least one Android 13+ emulator and, ideally, one physical Android phone with USB debugging enabled.
  • A Git repository and a test HTTP receiver for webhook projects.

Recommended tools

  • A second sandbox Android app used as the safe target for accessibility macros.
  • A factory-resettable emulator for device-owner provisioning.
  • ADB, Logcat, Layout Inspector, Database Inspector, Background Task Inspector, Perfetto, and Macrobenchmark.
  • A locally controlled Termux environment for the explicit bridge project.

Testing your setup

$ adb devices
List of devices attached
emulator-5554    device

$ adb shell getprop ro.build.version.sdk
36

$ adb shell pm list features | head -3
feature:android.hardware.bluetooth
feature:android.hardware.location
feature:android.software.device_admin

The exact feature list varies. The invariant is that ADB can identify the target, the app can be installed from Android Studio, and you can create a second emulator snapshot for destructive management tests.

Time Investment

  • Foundation projects: 10-28 hours each.
  • Capability adapter projects: 16-40 hours each.
  • Reliability and managed-device projects: 24-40 hours each.
  • Capstone: 50-75 hours.
  • Full sprint: approximately 320-470 hours, or 8-12 months at 8-10 focused hours per week.

Important Reality Check

Android automation is an exercise in negotiated authority. A user can revoke access; a package can update its UI; a notification action can expire; an OEM can defer work; a screen can expose no semantic nodes; a device can lock; an exact alarm grant can disappear; and the operating system can kill your process. A correct automation product does not promise immortality. It promises explicit capabilities, truthful scheduling, recoverable state, safe failure, and enough evidence to explain what happened.

Big Picture / Mental Model

Think in eight layers. Android-specific mechanisms belong at the outside edges; the rule engine in the middle should remain deterministic and testable on the JVM.

 [8] Human intent       editor | consent | dry-run | enable | emergency stop
          |
 [7] Entry surfaces     app | shortcut | tile | widget | notification | plugin
          |
 [6] Trigger adapters   broadcasts | callbacks | schedules | accessibility
          |
 [5] Event model        normalize | timestamp | source | deduplicate | redact
          |
 [4] Rule engine        event -> conditions -> deterministic actions
          |
 [3] Execution policy   authority | allowlist | idempotency | retry | timeout
          |
 [2] Action adapters    Android APIs | plugin IPC | HTTPS | accessibility | DPC
          |
 [1] Evidence/state     Room | run trace | health | metrics | support bundle

 Android process death, Doze, OEM behavior, policy, and user revocation
 surround every layer; they are not a separate “background mode.”

Five invariants organize the entire sprint:

  1. Rules contain domain data, not Android framework objects.
  2. Every action declares the capability it requires before execution begins.
  3. Durable work is resumable and idempotent; memory-only callbacks are opportunistic.
  4. High-authority adapters are separately enabled, visibly active, narrowly allowlisted, and immediately stoppable.
  5. Every run produces a redacted trace that answers “what triggered, what matched, what ran, and why did it stop?”

Theory Primer

Chapter 1: Android Components, Processes, and Capability Boundaries

Fundamentals

An Android application is a signed package whose components run under an application UID inside a sandbox. Activities provide interactive screens; services represent longer-lived or remotely bound work; broadcast receivers handle short event deliveries; and content providers expose structured data across process boundaries. None of these components guarantees that the process remains alive. Android ranks processes by user importance and may reclaim a background process without giving application code a final callback. Automation software must therefore separate durable intent from transient execution. A rule saved in Room is durable intent; a coroutine collecting connectivity callbacks is transient execution. The app must also distinguish availability from authority: an API can exist on the OS while the user grant, role, service enablement, device feature, current lifecycle state, or distribution policy needed to use it is absent.

Deep Dive

Desktop automation tools often inherit the authority of the logged-in user and run in an environment that favors persistent background processes. Android is deliberately different. Each installed package receives a Linux UID, private storage, a process sandbox, and only the platform capabilities granted by its manifest, runtime decisions, system roles, special settings, or administrative provisioning. The application signature establishes identity across updates and can protect inter-app protocols with signature-level permissions. SELinux, Binder checks, app-op state, permission state, and component export rules add enforcement beyond ordinary filesystem identity.

The four classic component types have different execution contracts. An activity is an entry surface, not a daemon. Its lifecycle follows visibility and task navigation. A started service does not imply a worker thread and is subject to background execution limits. A foreground service represents immediate, user-perceptible work and must display an ongoing notification; modern Android restricts when it can be started, requires declared service types for many uses, and can impose time limits. A bound service exists while clients are connected and is useful for IPC. A broadcast receiver has a short delivery window and should validate, enqueue, or hand off work rather than create an untracked background thread. A provider is appropriate for data-shaped IPC but expands the attack surface if exported carelessly.

Process lifetime is orthogonal to component state. Android can recreate a component in a new process, restore an activity from saved state, reconnect a notification listener, or run a Worker after the original UI process is gone. Anything required for correctness must cross that boundary through a database, DataStore, scheduled-work record, or reconstructable system registration. Conversely, transient objects such as AccessibilityNodeInfo, PendingIntent instances, Binder handles, and MediaProjection tokens have lifetimes that must not be confused with durable identifiers.

Capability detection is a first-class architectural service. For each trigger or action, the engine needs a descriptor containing minimum API level, required device feature, manifest declaration, user grant, special access, role, service connection, package visibility, policy mode, foreground requirement, and current availability. This registry should return states richer than a Boolean: available, needs consent, temporarily unavailable, unsupported, restricted by policy, revoked, or misconfigured. The UI uses the same registry as the executor, preventing the editor from promising actions the runtime cannot perform.

Some capabilities are consumer-facing: runtime permissions, notification access, exact-alarm access, accessibility service enablement, media projection consent, and user-selected roles. Others require a different product relationship. DevicePolicyManager becomes powerful only after profile-owner or device-owner provisioning. Signature permissions require packages signed by the same trusted key. Privileged permissions normally require installation as a system/privileged app. ADB shell and root live outside the normal application UID. Treating these as interchangeable produces insecure designs and impossible onboarding.

Android version and target SDK also shape the contract. A capability can behave differently because of the device OS, the application’s target SDK, the distribution channel, or a compatibility change. The guide’s reference track targets Android 16/API 36 and tests older supported versions intentionally. Capability adapters, rather than the domain engine, own these branches.

How This Fits on Projects

Projects 1 and 2 make lifecycle and capability state visible. Projects 5-13 build adapters with different contracts. Project 14 proves restart and revocation behavior, and Project 15 integrates them without erasing their boundaries.

Definitions and Key Terms

  • Application UID: The Linux identity and sandbox boundary assigned to an installed application.
  • Component: An Android-declared entry point such as an activity, service, receiver, or provider.
  • Capability: A specific operation together with every technical and consent precondition needed to perform it.
  • Target SDK: The Android behavior contract an app declares it has been tested against.
  • Process death: System reclamation of an app process; not equivalent to an orderly application shutdown.
  • Special app access: A Settings-mediated capability outside the ordinary runtime permission dialog.

Mental Model Diagram

 signed APK
    |
    +--> UID sandbox
    |      +--> private files / database
    |      +--> process (disposable)
    |      +--> activities / services / receivers / providers
    |
    +--> declared surface
           +--> permissions
           +--> exported components
           +--> SDK and feature requirements
           +--> user-enabled special services
                         |
                         v
              capability registry state
        available / consent / temporary / unsupported / policy

How It Works

  1. The editor asks the registry whether a trigger or action can be configured.
  2. The registry evaluates static platform support and current dynamic authority.
  3. The user receives a plain-language rationale before any settings or consent journey.
  4. Execution rechecks capability state; an earlier grant is never assumed permanent.
  5. The adapter performs only the narrow operation represented by its contract.
  6. The trace stores the capability decision and typed outcome.
  7. If the process dies, durable registrations and queued work are reconciled from storage on the next valid entry point.

Invariant: domain rules remain readable without Android objects. Failure modes include stale cached grants, missing manifest declarations, component export mistakes, background-start rejection, process-local state loss, and unsupported OEM behavior.

Minimal Concrete Example

CapabilityDescriptor:
  id: notification.listen
  minimum_api: 18
  manifest_component: NotificationBridgeService
  user_gate: Settings notification access
  runtime_state: NEEDS_CONSENT
  degradation: disable notification triggers; preserve rule
  sensitive_fields: title, text, action payload

Common Misconceptions

  • “A service runs forever.” Android may stop the service or kill the process; foreground services have strict purpose and visibility requirements.
  • “If an API exists, my app can call it.” Availability, authority, lifecycle, and policy are separate questions.
  • “ADB shell is an app permission.” It is a different OS identity and deployment model.
  • “Device admin equals device owner.” Legacy admin, profile owner, and device owner expose different powers.

Check-Your-Understanding Questions

  1. Why must a rule survive even when its trigger collector does not?
  2. Which data belongs in the capability registry rather than the rule engine?
  3. Why is a device-owner adapter a separate deployment track?

Check-Your-Understanding Answers

  1. Android can kill the process; durable user intent must be reconstructable.
  2. API level, feature, grant, role, service connection, policy, and lifecycle prerequisites.
  3. Device owner requires administrative provisioning and represents organizational authority, not a normal consumer consent dialog.

Real-World Applications

Automation platforms, accessibility tools, password managers, device policy controllers, notification companions, VPN clients, launchers, and wearable companions all use capability-aware architecture.

Where You Will Apply It

Projects 1, 5-13, 14, and 15.

References

  • Android Developers, “Application fundamentals”: https://developer.android.com/guide/components/fundamentals
  • Android Developers, “Processes and app lifecycle”: https://developer.android.com/guide/components/activities/process-lifecycle
  • Android Developers, “Services overview”: https://developer.android.com/develop/background-work/services
  • “Operating Systems: Three Easy Pieces” by Arpaci-Dusseau and Arpaci-Dusseau — Processes and Virtualization chapters.

Key Insight

An Android automation product is a capability negotiator running in a disposable process, not a permanently privileged daemon.

Summary

Correct architecture separates signed identity, component lifecycle, process lifetime, durable state, and capability authority. Once those are explicit, unavailable powers become modeled states rather than mysterious crashes.

Homework / Exercises

  1. Classify ten proposed automation actions by component, authority type, and restart strategy.
  2. Draw the state transitions for a notification listener from unavailable through enabled, connected, disconnected, and revoked.

Solutions to the Homework / Exercises

  1. A good answer names a narrow adapter, durable input, current gate, and degraded behavior for every action.
  2. Enabled and connected must be separate; a service can be granted but temporarily disconnected, and revocation must disable execution without deleting the user’s rule.

Chapter 2: Permissions, Consent, Privacy, and Distribution Policy

Fundamentals

Permissions answer only part of the question “may this app act?” Android uses normal and dangerous manifest permissions, app-ops, special app access pages, user-enabled services, one-session capture consent, package roles, signature permissions, and enterprise provisioning. The user experience and revocation semantics differ for each. An automation app also processes unusually sensitive context: notification text, foreground-app history, screen structure, screenshots, location, network metadata, and user-authored actions. Least privilege therefore means minimizing both authority and observed data. Google Play policy adds a distribution contract on top of platform enforcement. A technically possible feature may require prominent disclosure, declaration, core-purpose justification, or a separate distribution flavor. Consent is not a one-time legal checkbox; it is an ongoing product state that must remain understandable and reversible.

Deep Dive

Android’s ordinary runtime permission flow covers dangerous permissions such as precise location or microphone access. The app declares the permission, explains the immediate user-facing purpose, requests it in context, and handles denial or later revocation. Automation features frequently depend on mechanisms outside that flow. Notification access and accessibility services are enabled in Settings. Usage access is special app access. Exact alarms have their own access model. A MediaProjection token follows a user confirmation and is valid for a specific capture session. A Quick Settings tile must be added by the user. A role such as default SMS handler has eligibility requirements and user selection. Device owner must be provisioned, usually on a managed or newly set-up device.

These differences should be represented as consent journeys rather than scattered activity-result callbacks. A journey includes a capability explanation, data-use disclosure, scope selection, launch to the system surface, return-time verification, success evidence, revocation instructions, and a degraded alternative. The app should not repeatedly nag after denial. It should preserve the disabled rule and show precisely which gate blocks it.

Data minimization starts before storage. A notification trigger often needs package, channel, and a predicate result; it may not need the full body persisted. An accessibility selector may need a resource ID, class, semantic label hash, and relative structure; it should not capture passwords or dump every window. A screenshot can be processed in memory and discarded. A usage-event cursor can retain a last-seen timestamp without constructing a permanent behavioral history. Logs use correlation IDs and typed redaction rather than arbitrary object serialization.

Least authority also shapes adapter selection. Prefer a published intent or notification action over accessibility traversal. Prefer WorkManager over an always-running service for deferrable durable work. Prefer targeted package queries over QUERY_ALL_PACKAGES. Prefer a user-tapped shortcut or tile over a background activity launch. Prefer a per-app allowlist over observing everything. If a broader capability is unavoidable, narrow it with explicit packages, rule-specific scopes, time limits, visible indicators, and an emergency stop.

Play distribution policy is a design input. Current policy permits deterministic, rule-based accessibility automation for a narrow, clearly understood purpose but prohibits using Accessibility APIs for a system that autonomously initiates, plans, and executes decisions. Non-disability automation apps must not falsely claim to be accessibility tools and need disclosure, affirmative consent, accurate listing documentation, and declaration. Broad package visibility, VPN use, exact alarms, foreground-service types, SMS/call access, and sensitive data each have additional requirements. A sideloaded developer flavor may explore capabilities that are inappropriate for a Play flavor, but sideloading does not erase platform consent or safety responsibilities.

Security and privacy UX must be symmetrical. Onboarding explains how to enable; the capability screen explains how to disable. A running macro shows a persistent controller and stop action. A webhook screen shows destinations and last delivery. A plugin catalog shows signer and requested capabilities. A support bundle previews redacted contents. A managed-device screen makes the administrative mode obvious.

The strongest test is counterfactual: if the user revokes a capability halfway through execution, what stops, what remains durable, what evidence appears, and what data is deleted? If the answer is unclear, consent has not yet become architecture.

How This Fits on Projects

Project 1 builds consent journeys. Projects 6, 8, 11, and 13 handle sensitive capability grants. Projects 9, 10, and 12 scope external actors. Projects 14 and 15 enforce redaction, audit, and emergency stop.

Definitions and Key Terms

  • Least privilege: Granting only the minimum authority required for the current feature.
  • Data minimization: Collecting, processing, retaining, and sharing only what is required.
  • Prominent disclosure: Clear in-app explanation shown before sensitive access, not hidden in terms.
  • Affirmative consent: A deliberate user action accepting the disclosed use.
  • Role: A system-recognized application function selected by the user and associated with privileges.
  • Revocation: Removal of previously available authority by the user, system, policy, or package state.

Mental Model Diagram

 feature request
      |
      v
 narrower API available? --yes--> use it
      |
      no
      v
 explain purpose -> choose scope -> system consent -> verify
      |                                      |
      | denied/revoked                       v
      +------------------------------> capability state
                                             |
                   +-------------------------+----------------------+
                   |                         |                      |
                execute                 degrade safely          stop now
                   |
          minimize -> redact -> retain briefly -> make reversible

How It Works

  1. Model the user-facing feature before selecting permissions.
  2. Enumerate every data field and device action the feature requires.
  3. Select the narrowest platform API and distribution-compatible mechanism.
  4. Present purpose, scope, visible behavior, and revocation path.
  5. Ask for authority only when the user enables the feature.
  6. Verify current state after returning from Settings and again before use.
  7. Redact at ingestion, retain minimally, and stop immediately on revocation.

Invariant: denied authority never silently falls back to a broader mechanism. Failure modes include permission fatigue, misleading disclosure, overbroad package discovery, accidental sensitive logging, false accessibility-tool claims, and features that cannot be stopped.

Minimal Concrete Example

ConsentJourney: accessibility.macro_runner
  purpose: Execute only macros the user explicitly records and enables
  scope: Selected packages [Sandbox Target]
  visible_state: Persistent “Macro running” controller
  prohibited: credentials, secure windows, purchases, permission dialogs
  revoke: Settings -> Accessibility -> FlowForge -> Off
  denial_behavior: Keep macro disabled; offer manual test simulation

Common Misconceptions

  • “The privacy policy is enough.” Sensitive access often needs contextual in-app disclosure and affirmative consent.
  • “Once granted, access remains granted.” Users and systems can revoke or restrict capabilities.
  • “Accessibility automation can be open-ended if the user opted in.” Platform and Play rules still constrain purpose and behavior.
  • “Sideloading makes every design acceptable.” Platform safety, consent, and local law still apply.

Check-Your-Understanding Questions

  1. Why should denial preserve a rule rather than delete it?
  2. What makes a consent journey testable?
  3. Why can a narrower API improve reliability as well as privacy?

Check-Your-Understanding Answers

  1. Denial changes current authority, not the user’s authored intent; preserving the disabled rule makes the state explainable and reversible.
  2. It has observable states, verification on return, revocation behavior, and a defined degraded path.
  3. Purpose-built APIs expose stable semantic contracts, whereas broad UI or package observation is more fragile and sensitive.

Real-World Applications

Password managers, screen readers, parental controls, enterprise DPCs, notification assistants, VPNs, and device companions all need capability-specific consent and disclosure.

Where You Will Apply It

Projects 1, 6, 8, 9, 11-15.

References

  • Android Developers, “Permissions on Android”: https://developer.android.com/guide/topics/permissions/overview
  • Android Developers, “Special permissions”: https://developer.android.com/training/permissions/requesting-special
  • Google Play, “Use of the AccessibilityService API”: https://support.google.com/googleplay/android-developer/answer/10964491
  • Google Play, “Developer Program Policy”: https://support.google.com/googleplay/android-developer/answer/17105854
  • “Foundations of Information Security” by Jason Andress — access control, privacy, and risk chapters.

Key Insight

Consent becomes trustworthy only when authority, data flow, visible execution, revocation, and degraded behavior are designed as one state machine.

Summary

Android automation spans multiple authority systems. Capability-specific onboarding, least-authority adapter selection, ingest-time redaction, accurate distribution claims, and immediate revocation handling are core implementation concerns.

Homework / Exercises

  1. Create a data inventory for notification, accessibility, usage, screenshot, webhook, and plugin features.
  2. Redesign an overbroad “grant everything” onboarding into progressive capability journeys.

Solutions to the Homework / Exercises

  1. Record source, fields, purpose, retention, destination, redaction, and revocation behavior for each data class.
  2. Ask only when a rule requires a capability, explain one concrete benefit, permit package-level scope where possible, and show a disabled simulation before consent.

Chapter 3: Event-Condition-Action Modeling and Deterministic Rule Engines

Fundamentals

Event-condition-action, or ECA, is the grammar behind most automation systems. An event says something happened, conditions decide whether the current context makes a rule eligible, and actions express the effects the user requested. The apparent simplicity hides hard questions: events may be duplicated or reordered; context can change during evaluation; actions can partially succeed; one action can emit another event; and multiple rules can conflict. A robust engine represents triggers, conditions, and actions as versioned domain data rather than executable Kotlin objects or Android Intents. Evaluation is a deterministic transformation from an event plus a context snapshot and rule set into an execution plan. Side effects occur only after planning, capability checks, and policy checks, making simulation, replay, testing, and audit possible.

Deep Dive

Begin with a canonical event envelope. It needs a stable type, source, occurrence time, observation time, unique or deduplication identity, schema version, sensitivity classification, and typed payload. Occurrence time describes when the outside world changed; observation time records when the app learned about it. That distinction matters when Doze, process death, batching, or network delays are involved. The payload should contain domain values, not BroadcastReceiver objects, Notification instances, or AccessibilityNodeInfo references.

Conditions are pure predicates over the event and an immutable context snapshot. Examples include battery percentage below a threshold, package in an allowlist, local time inside a user-defined window, network unmetered, or a prior action not executed recently. Conditions form trees: all, any, not, comparison, set membership, and bounded temporal relations. Their results should be richer than true or false. A result can be true, false, unknown, or unavailable with evidence. If location is missing, treating “at home” as false hides a capability problem. An explicit unknown result lets the rule choose skip, wait, ask, or degrade.

Actions are commands describing intended effects. They declare input schema, capability requirements, idempotency strategy, timeout, retry policy, sensitivity, user-visibility requirement, and compensation if any. An action descriptor such as “post local notification” can be durable. A runtime adapter turns it into Android calls. This split makes it possible to test plans on the JVM, migrate stored rules, support plugins, and show a dry-run without performing the action.

The engine has two phases. Planning selects enabled rules for an event, evaluates conditions against a snapshot, resolves priority and conflict policies, validates schemas, and produces a plan. Execution checks current capability again and invokes adapters. A plan is immutable and receives a correlation ID. Each step produces a trace entry. Planning should never invoke an Android side effect; otherwise replay is dangerous and debugging becomes nondeterministic.

Re-entrancy needs deliberate control. Suppose a notification action produces a notification event that matches the same rule. The engine can tag causation chains, enforce maximum depth, suppress self-originated events, and use cooldown windows. Cycle prevention belongs to policy, not a scattered adapter workaround. Concurrency needs similar rules. You may serialize all actions per rule, serialize actions by resource key, permit parallel independent actions, or cancel superseded work. The user-facing model must explain the choice.

Delivery semantics are never exactly-once in the absolute sense. A process may die after the external side effect succeeds but before the database records success. Design for at-least-once attempts with idempotency keys where the target supports them, or detect and surface ambiguity where it does not. Webhooks can carry an idempotency key. A local setting action can read current state before changing it. A UI tap may be inherently ambiguous and should not be blindly retried after process loss.

Versioning is part of the language. Stored rule graphs and plugin descriptors must include schema versions. Migrations transform old data into new domain shapes; they do not reinterpret past runs silently. Unknown nodes should make a rule disabled and explainable rather than crash the editor.

Finally, distinguish a deterministic rule engine from an autonomous planner. A user may author a static macro or explicit conditional graph. The engine evaluates that declared graph. It does not ask a model to invent arbitrary UI actions or expand authority. This is essential for safety, predictability, and current AccessibilityService distribution rules.

How This Fits on Projects

Project 3 builds the engine; Project 4 persists and migrates the language. Projects 5-13 add adapters without changing the core. Project 14 replays traces and Project 15 integrates the complete rule lifecycle.

Definitions and Key Terms

  • Event envelope: Versioned, typed record describing an observed occurrence.
  • Context snapshot: Immutable view of relevant state used for one evaluation.
  • Predicate: Pure condition that classifies an event and context without side effects.
  • Execution plan: Immutable list or graph of validated intended actions.
  • Idempotency: Property that repeating an attempt does not create additional unintended effect.
  • Causation chain: Relationship linking events and actions produced by one automation run.

Mental Model Diagram

 raw callback
      |
      v
 [normalize + redact + dedupe] ---> EventEnvelope
                                      |
                                      v
         enabled rules + ContextSnapshot
                                      |
                                      v
       condition tree -> evidence -> conflict policy
                                      |
                                      v
                     immutable ExecutionPlan
                                      |
                         capability + safety gates
                                      |
              +-----------------------+----------------------+
              v                       v                      v
           success                 retryable              ambiguous
              |                       |                      |
              +-----------------------+----------------------+
                                      v
                              redacted RunTrace

How It Works

  1. Normalize a platform callback into a versioned event.
  2. Deduplicate using source-appropriate identity and time bounds.
  3. Take one context snapshot.
  4. Evaluate matching enabled rules without side effects.
  5. Resolve priority, cooldown, cycles, and resource conflicts.
  6. Persist the plan before durable actions begin.
  7. Execute through adapters with timeout and idempotency policy.
  8. Persist step evidence and emit only explicitly permitted derived events.

Invariants: one evaluation uses one snapshot; planning is pure; every side effect belongs to a trace; causation depth is bounded. Failure modes include event storms, mutable context during evaluation, silent unknown conditions, duplicate effects, cycles, partial action sequences, and schema drift.

Minimal Concrete Example

WHEN power.connected
IF battery.percent < 40 AND time.local BETWEEN 06:00..23:00
THEN notify(channel="automation", message="Charging below 40%")

plan:
  rule: low-battery-charge
  condition_results: [true, true]
  required_capabilities: [notification.post]
  idempotency_key: rule-42:event-991:action-1

Common Misconceptions

  • “A rule is just a callback.” Callbacks lack durable schema, simulation, migration, and trace semantics.
  • “Exactly once can always be guaranteed.” External effects and crashes create unavoidable ambiguity.
  • “Unknown context is false.” Unknown is evidence of missing or stale information and needs policy.
  • “Retries are harmless.” UI actions, messages, and purchases can duplicate effects.

Check-Your-Understanding Questions

  1. Why persist an execution plan before durable action execution?
  2. When is an event timestamp insufficient?
  3. How does causation metadata stop a notification loop?

Check-Your-Understanding Answers

  1. It makes the intended work reconstructable after process death and separates planning from effects.
  2. When occurrence and observation differ because the system delayed delivery.
  3. The engine can detect that the triggering event originated from the same action chain and apply suppression or depth rules.

Real-World Applications

Home automation, CI/CD workflows, fraud rules, integration platforms, incident response, business process engines, and notification routing use variations of ECA and durable execution.

Where You Will Apply It

Projects 3-15.

References

  • “Enterprise Integration Patterns” by Gregor Hohpe and Bobby Woolf — Message, Message Channel, Message Router, Idempotent Receiver.
  • “Domain-Driven Design” by Eric Evans — model, aggregate, and bounded-context chapters.
  • “Design Patterns” by Gamma et al. — Command, Composite, State, and Strategy patterns.
  • Google Play AccessibilityService policy: https://support.google.com/googleplay/android-developer/answer/10964491

Key Insight

The rule engine should decide and explain intended effects deterministically; Android adapters should perform those effects without owning the language.

Summary

Typed events, pure conditions, immutable plans, capability-declaring actions, bounded causation, idempotency, and versioned schemas turn “if this, then that” into a trustworthy runtime.

Homework / Exercises

  1. Model a rule with all/any/not conditions and one unavailable context value.
  2. Identify safe retry policies for a webhook, local notification, accessibility tap, and device-policy toggle.

Solutions to the Homework / Exercises

  1. Preserve unavailable as a typed result and define whether the rule skips, waits, or asks; do not coerce it silently.
  2. Webhooks use receiver idempotency; local notifications use stable IDs; accessibility taps avoid blind replay after ambiguity; policy toggles read current state and converge to the desired state.

Chapter 4: Event Sources, Context Sensing, and Backpressure

Fundamentals

Android exposes context through broadcasts, callback APIs, content observers, sensors, UsageStats, notification events, accessibility events, network callbacks, and user entry surfaces. These sources do not share delivery guarantees. Some are sticky snapshots, some are edge events, some are batched, some require the process to be alive, and some are available only after special access. A trigger adapter must convert source-specific behavior into a stable event contract. It also must control volume: accessibility and sensor sources can emit many events per second, while connectivity or package changes may arrive in bursts. Backpressure means the engine has a defined response when events arrive faster than they can be processed—coalesce state, debounce noise, sample, buffer within bounds, drop with metrics, or reject configuration.

Deep Dive

The first design decision is whether a source represents state or occurrence. Battery percentage is state; crossing below 20 percent is a derived occurrence. Network connectivity is state; transition from metered to unmetered is an occurrence. Treating every callback as a meaningful event produces duplicates and storms. A state adapter stores the last normalized value, compares new observations, and emits only relevant transitions. It may still expose raw observations to a diagnostic monitor.

BroadcastReceiver is a delivery entry point, not a work executor. Modern Android restricts manifest-declared implicit broadcasts, with specific exceptions such as boot completion. Context-registered receivers exist only while their registering process and lifecycle remain valid. The receiver should validate the Intent, extract the minimum payload, use goAsync only for a short bounded handoff when appropriate, and enqueue durable work if processing outlives the delivery window. A thread started inside onReceive may die when the receiver returns and the process becomes reclaimable.

Callback APIs such as ConnectivityManager.NetworkCallback or sensor listeners have registration lifecycles. The app must avoid duplicate registration, unregister at the correct time, and reconstruct state after process recreation. For persistent automation, a callback collector may need a legitimate foreground execution mode, a system-supported exemption, or a different formulation using WorkManager constraints. The right answer is not always “keep a service alive.”

UsageStats can inform approximate foreground-app transitions after the user grants Usage Access. It is a historical query surface, not a guaranteed real-time callback. An adapter needs a cursor, overlap window, deduplication, locked-device behavior, retention awareness, and measured latency. NotificationListenerService and AccessibilityService provide richer callbacks but with higher sensitivity and different scope. They should be separate sources rather than alternative implementations hidden under one misleading “app changed” trigger.

Event normalization maps source payloads into domain types. Normalize units, clocks, package identifiers, network classifications, and nullability. Use a monotonic clock for elapsed durations and wall time for user schedules and audit. Record the adapter and platform version so traces remain interpretable. Redact before writing to the event bus.

Backpressure policy depends on semantics. For sensor readings, keep latest or sample a window. For text-change accessibility events, debounce by window and node signature. For notification posts, preserve individual identities but bound historical storage. For a boot reconciliation event, serialize it and make it unique. Bounded queues prevent memory exhaustion. Dropped or coalesced counts belong in health metrics so silence is not confused with success.

Ordering is also source-specific. Events from different adapters have no global order. Even one source can be delayed. The engine should not sort the world by wall-clock and assume causality. It uses causation identifiers for derived events and per-source sequence/cursors where available. Temporal conditions define tolerances: “within five minutes of connecting to Wi-Fi” rather than equality between timestamps.

Testability comes from ports. Each source implements a small interface that emits canonical event envelopes. JVM tests feed synthetic events without Android. Instrumented tests verify actual registration, permission denial, and platform callbacks. A debug-only event injector powers the live monitor and lets a learner test rules without repeatedly changing physical device state.

How This Fits on Projects

Project 2 builds normalization and a live timeline. Projects 5 and 6 add scheduled and notification sources. Projects 8, 11, and 13 add accessibility, screen, and administrative sources. Project 14 subjects all adapters to event storms and process loss.

Definitions and Key Terms

  • Edge event: A discrete transition or occurrence.
  • State observation: A reading that may repeat without a meaningful change.
  • Debounce: Wait for a quiet interval before emitting the latest candidate.
  • Coalescing: Combining multiple observations into one representative update.
  • Backpressure: Policy for demand exceeding processing capacity.
  • Cursor: Durable position used to resume scanning a historical event source.

Mental Model Diagram

 broadcasts   callbacks   historical query   service events   user actions
     |           |              |                  |               |
     +-----------+--------------+------------------+---------------+
                                    |
                       source-specific adapter
                 validate -> normalize -> redact -> classify
                                    |
                     +--------------+--------------+
                     |                             |
                 raw monitor              backpressure policy
                                            |
                          debounce / sample / coalesce / bound
                                            |
                                      canonical event bus

How It Works

  1. Classify the source as state, edge, historical query, or user initiation.
  2. Define its lifecycle and delivery guarantees.
  3. Validate and normalize a minimal payload.
  4. Apply per-source dedupe and backpressure.
  5. Persist a cursor or last state only when required for correctness.
  6. Emit the canonical envelope and source health evidence.
  7. Reconcile registrations and last state after a valid process entry point.

Invariants: adapters never expose framework object lifetimes to the domain; queues are bounded; drops are measurable. Failure modes include receiver timeouts, duplicate callbacks, stale cursors, clock changes, missing unlock, noisy event trees, and unbounded logs.

Minimal Concrete Example

raw: ACTION_POWER_CONNECTED at wall=08:03:10
last_state: power=disconnected
normalized:
  type: power.connection.changed
  payload: {from: disconnected, to: connected}
  source: broadcast.power
  observed_at: 08:03:10.240
  sensitivity: low

Common Misconceptions

  • “Every callback is a unique event.” Many callbacks repeat state.
  • “Broadcast receivers can finish long actions.” Their process priority drops after delivery.
  • “Usage access tells the exact foreground app instantly.” It is a historical and access-controlled signal.
  • “Dropping noisy events is always wrong.” Semantic coalescing is often required, but must be observable.

Check-Your-Understanding Questions

  1. Why derive a battery-threshold crossing from state rather than expose every percentage callback?
  2. Which clocks should a five-minute cooldown use?
  3. What makes a debug event injector safe?

Check-Your-Understanding Answers

  1. It removes duplicates and encodes the user’s meaningful transition.
  2. A monotonic elapsed clock for duration; wall time remains useful for human display.
  3. It is debug-only, visually labeled, produces synthetic source metadata, and cannot grant or bypass capabilities.

Real-World Applications

Wearables, network monitors, home automation hubs, device companions, telemetry collectors, and reactive UIs normalize heterogeneous event sources with backpressure.

Where You Will Apply It

Projects 2, 5, 6, 8, 11, 13-15.

References

  • Android Developers, “Broadcasts overview”: https://developer.android.com/develop/background-work/background-tasks/broadcasts
  • Android Developers, “System restrictions on background tasks”: https://developer.android.com/develop/background-work/background-tasks/bg-work-restrictions
  • Android Developers, UsageStatsManager: https://developer.android.com/reference/android/app/usage/UsageStatsManager
  • “Reactive Design Patterns” by Roland Kuhn and Jamie Allen — flow control and resilience concepts.

Key Insight

An event adapter is a semantic translator and pressure valve, not a thin callback forwarded into business logic.

Summary

Correct triggering requires source classification, lifecycle-aware registration, state-to-edge derivation, normalized envelopes, bounded buffering, measured drops, and honest delivery semantics.

Homework / Exercises

  1. Choose debounce, sample, coalesce, or preserve-all policies for six Android event types.
  2. Design a boot-time reconciliation sequence without doing long work in the receiver.

Solutions to the Homework / Exercises

  1. Preserve distinct notification identities; coalesce network state; debounce text changes; sample high-rate sensors; unique-enqueue boot reconciliation; preserve explicit user commands.
  2. Validate boot state, enqueue unique durable reconciliation, return quickly, then rebuild schedules and health state in a Worker.

Chapter 5: Lifecycle-Aware Scheduling, Durable Work, and Battery

Fundamentals

Android scheduling is a choice among asynchronous in-process work, WorkManager or JobScheduler, alarms, foreground services, and purpose-built APIs. WorkManager is the normal choice for persistent, deferrable, constraint-aware work that should survive process death and reboot. AlarmManager represents time-based wakeups, not a general job engine; exact alarms require special justification and authority on modern Android. Foreground services are for immediate, user-perceptible work that must continue while the user is aware of it, not a loophole for indefinite background execution. Doze, App Standby, OEM policies, quotas, network constraints, user force-stop, reboot, and clock changes affect delivery. An automation app must communicate requested time versus actual time and rebuild system schedules from durable rule intent.

Deep Dive

Start by classifying work on two axes: urgency and durability. A short operation while the app is visible can use a coroutine tied to the appropriate lifecycle. Durable, deferrable work uses WorkManager with explicit constraints, unique names, input references, and retry/backoff. A user-facing clock event may use AlarmManager when WorkManager’s timing is too loose. Immediate work that is noticeable and cannot be deferred may qualify for a foreground service, with the correct service type, visible notification, stop affordance, and background-start eligibility. If a domain-specific API exists, it is often better than any generic mechanism.

WorkManager promises eventual eligible execution, not exact wall-clock delivery. Periodic work has a minimum interval and is subject to system optimization. Constraints such as unmetered network and charging describe eligibility; they do not reserve an execution instant. Unique work prevents duplicate scheduling during reconciliation. The Worker should read current durable state by ID, verify that the rule remains enabled, claim an execution record transactionally, and perform idempotent steps. Passing an entire serialized rule as WorkManager input creates stale execution.

AlarmManager has elapsed-realtime and wall-clock forms. User schedules based on local time need explicit behavior for time-zone changes, daylight-saving gaps and overlaps, manual clock changes, and reboot. Repeating alarms are inexact; often the app should schedule the next single occurrence and recompute after each delivery. Exact access can be denied or revoked, so a rule needs a precision contract: exact required, best effort accepted, or notify the user that the capability is unavailable. General automation should not assume the restricted USE_EXACT_ALARM permission is appropriate for distribution.

Doze batches ordinary alarms, jobs, and network activity. “Allow while idle” and expedited paths are limited resources, not permission to wake constantly. Event-driven designs should prefer natural system callbacks and constraints over polling. Add jitter to server work to avoid synchronized fleets. The app’s diagnostics must measure actual execution delay rather than claim correctness because a schedule API call returned successfully.

Foreground services have become more constrained across recent Android releases. Starting in the background is normally prohibited except documented cases. Types and type-specific permissions must match actual work. A service still runs on the application’s main thread unless work is dispatched appropriately. The user can stop it, and the process can still die. The persistent notification is part of the product contract: it says what is running, why, progress, and how to stop.

Reconciliation connects durable rules to disposable system registrations. On app startup, boot completion, package update, time-zone change, exact-alarm access change, or database migration, a scheduler compares desired registrations with actual scheduled work. It cancels or replaces stale identifiers and records the next expected run. Reconciliation is idempotent and serialized.

Force-stop is a special boundary. Android may cancel alarms and prevent background launches until the user opens the app again. An automation product should explain this rather than attempt to circumvent it. OEM battery controls can create additional delays. A “scheduler health” screen shows last request, actual start, delay, selected mechanism, constraints, retry count, next run, and known restriction state.

Testing uses virtual clocks for domain logic, WorkManager’s testing support for workers, adb commands for Doze and standby simulation, emulator reboots, time-zone transitions, permission revocation, and process kills between side effect and commit. The goal is not merely that work ran once; it is that the app explains every tested delay and avoids duplicate effects.

How This Fits on Projects

Project 5 builds the scheduler and reconciliation loop. Projects 6, 10, and 12 use durable work for notification actions, plugin/webhook jobs, and network delivery. Projects 14 and 15 test process death, Doze, quota, and reboot.

Definitions and Key Terms

  • Deferrable work: Work that may execute later when constraints and system policy allow.
  • Exact alarm: Alarm intended for precise user-facing timing and subject to special rules.
  • Foreground service: User-noticeable ongoing execution with a persistent notification.
  • Reconciliation: Idempotently aligning platform schedules with durable desired state.
  • Doze: Device idle mode that defers background CPU and network work.
  • Force-stop: User/system state that prevents ordinary background restart until user interaction.

Mental Model Diagram

work request
    |
    +-- only while visible? ------------------> lifecycle coroutine
    |
    +-- durable + deferrable? ----------------> WorkManager
    |
    +-- precise user-facing clock event? -----> AlarmManager + access check
    |
    +-- immediate, perceptible, nondeferrable?> foreground service
    |
    +-- purpose-built platform API exists? ---> use that API

all durable paths:
desired rule -> schedule registry -> platform token -> execution claim -> trace
                     ^                                      |
                     +------------- reconciliation --------+

How It Works

  1. Classify work by urgency, durability, precision, visibility, and constraints.
  2. Select the least costly supported scheduling mechanism.
  3. Persist desired execution before registering with the platform.
  4. Use stable unique identifiers derived from durable rule identities.
  5. On wakeup, reload current state and claim work transactionally.
  6. Execute with idempotency, timeout, and typed retry.
  7. Record actual timing and reconcile the next desired registration.

Invariants: a platform token is an index into durable intent, not the source of truth; retries never depend on stale serialized rules. Failure modes include duplicate enqueues, exact-access revocation, DST errors, background FGS rejection, quota exhaustion, force-stop, OEM delay, and alarm/request drift.

Minimal Concrete Example

schedule request:
  rule_id: morning-routine
  local_time: 07:30
  precision: BEST_EFFORT
  next_wall_time: 2026-07-16T07:30:00-03:00
  mechanism: INEXACT_ALARM

trace:
  requested: 07:30:00
  observed: 07:34:18
  delay: 4m18s
  reason: delivered in system batch

Common Misconceptions

  • “WorkManager runs at an exact time.” It runs eligible work under system scheduling.
  • “A foreground service makes the app immortal.” It improves priority for valid visible work but remains governed and stoppable.
  • “Repeating alarms remove schedule logic.” Local-time recurrence still needs timezone and DST semantics.
  • “Boot completed means do all work in the receiver.” The receiver should hand off and return quickly.

Check-Your-Understanding Questions

  1. Why should a Worker load the rule by ID?
  2. What does a scheduler health screen prove that API success does not?
  3. Why schedule one future wall-clock occurrence at a time?

Check-Your-Understanding Answers

  1. The user may edit or disable the rule after it was scheduled.
  2. It shows actual timing, constraint, retry, and restriction behavior.
  3. It allows each next occurrence to incorporate timezone, DST, and rule changes.

Real-World Applications

Sync clients, reminders, backups, fitness tracking, uploaders, calendar apps, device maintenance, and IoT companions all combine durable intent with system scheduling.

Where You Will Apply It

Projects 5, 6, 10, 12, 14, and 15.

References

  • Android Developers, “Background tasks overview”: https://developer.android.com/develop/background-work/background-tasks
  • Android Developers, “Task scheduling”: https://developer.android.com/develop/background-work/background-tasks/persistent
  • Android Developers, “Schedule alarms”: https://developer.android.com/develop/background-work/services/alarms
  • Android Developers, “Foreground services overview”: https://developer.android.com/develop/background-work/services/fgs
  • “Release It!, 2nd Edition” by Michael T. Nygard — stability patterns and timeouts.

Key Insight

Reliable scheduling means persisting user intent, choosing an honest mechanism, measuring actual delivery, and continuously reconciling disposable platform registrations.

Summary

WorkManager, alarms, foreground services, and callbacks solve different problems. Durable IDs, state reload, idempotent claims, timing evidence, and schedule reconciliation make their limitations manageable.

Homework / Exercises

  1. Classify ten automation jobs by the correct execution mechanism.
  2. Write a schedule policy for the DST spring gap and autumn overlap.

Solutions to the Homework / Exercises

  1. Use lifecycle work for visible tasks, WorkManager for durable deferrable jobs, AlarmManager only for clock semantics, foreground service only for qualified perceptible work, and purpose-built APIs when available.
  2. Define whether a nonexistent local time moves forward or skips, and whether an ambiguous local time runs once at the earlier/later offset; surface the choice to the user.

Chapter 6: Intents, Binder IPC, Plugins, and User Command Surfaces

Fundamentals

Android applications collaborate through Intents, PendingIntents, bound services and Binder, Messenger or AIDL interfaces, content providers, broadcasts, URI grants, and app-defined permissions. An automation host also exposes human entry surfaces: launcher shortcuts, Quick Settings tiles, widgets, notification actions, share targets, and voice/App Actions. Each surface is an authority boundary because data and control may cross package, process, or lock-screen boundaries. A safe plugin protocol uses explicit targets, versioned typed envelopes, caller and signer validation, narrow component exports, timeouts, cancellation, and structured errors. A command surface never assumes its service remains alive; it sends a durable command into the same engine used by the main UI. Package visibility is intentionally filtered, so plugin discovery should use targeted queries or an explicit registry rather than indiscriminate installed-app inventory.

Deep Dive

Intents are messages describing an action and optional data. An explicit Intent names a target component or package and is preferred when sending sensitive commands. An implicit Intent asks the system to resolve matching exported components; this is useful for open user-mediated actions but dangerous as a private RPC substitute. Intent extras are untrusted input even when the sender appears familiar. Validate action, schema version, types, sizes, URI schemes, allowed packages, and caller identity where the mechanism exposes it.

PendingIntent delegates the right to perform a future operation with the creator’s identity. Mutability, target explicitness, request-code identity, and lifetime matter. An automation action that stores arbitrary PendingIntents as if they were durable capabilities will eventually hit cancellation, package updates, or changed target state. Treat them as ephemeral tokens, invoke only in the narrow intended context, and report disappearance without unsafe substitution.

Bound services provide a client-server contract. In-process binding can use a local Binder; cross-package plugins can use Messenger, AIDL, or a deliberately small Binder interface. The protocol should be asynchronous at the domain boundary even if a Binder method is synchronous, because remote work can block, crash, or disconnect. Binder calls have transaction size limits and binder death semantics. Large payloads belong in a file or provider with a scoped URI grant rather than an oversized transaction.

A plugin descriptor declares plugin ID, package, signer expectation, protocol version range, triggers/actions, configuration schema, capability requirements, data classifications, and human-readable disclosures. Discovery uses an intent signature in the manifest queries element or a user-selected package. Before execution the host checks the installed package signature against the trusted enrollment record, negotiates protocol version, binds explicitly, sends a request with a correlation and idempotency ID, and enforces deadline and cancellation. The plugin returns a typed success, retryable failure, permanent failure, needs-user-action result, or unsupported-version response. Host and plugin both keep redacted traces.

Signature-level permissions are useful when host and plugins share a signing authority, such as one vendor’s suite. An open ecosystem cannot rely on a single signature, so it needs explicit user trust enrollment, allowlists, clear signer fingerprints, request-scoped confirmations for high-risk actions, and a protocol that grants no ambient access. Exported components must be minimal. Android 12+ requires explicit exported declarations for components with intent filters; Android 16 introduces stricter intent-matching options that should be tested.

Package visibility changes the discovery model on Android 11+. The host sees packages automatically relevant to its interactions plus those covered by targeted queries. QUERY_ALL_PACKAGES is restricted and rarely necessary. A plugin marketplace can publish package IDs and signatures through a server or QR enrollment, while actual interaction uses specific intents. This is more private and more deterministic than scraping the entire device inventory.

Human command surfaces are adapters into the engine. A pinned shortcut references a stable routine ID. A tile models active, inactive, and unavailable truthfully and survives TileService recreation. A widget shows at-a-glance state and sends an immutable PendingIntent or callback. A notification action gives visible user initiation. None should embed a full mutable rule. They dispatch a CommandEnvelope that reloads the current routine and performs the same capability and safety checks as any other trigger.

Lock-screen and background activity rules matter. A command may arrive while the device is locked or the host is backgrounded. Prefer a notification that requests attention over popping an activity. If confirmation is required, store a pending proposal and let the user open the UI through a system-sanctioned action. A foreground service does not generally authorize background activity launch.

How This Fits on Projects

Project 7 builds shortcuts, tiles, widgets, and notification actions. Project 10 builds the plugin SDK. Project 12 uses the same envelope principles for webhooks and Termux. Project 15 exposes one coherent command bus.

Definitions and Key Terms

  • Explicit Intent: Intent directed to a known package or component.
  • Binder: Android’s primary kernel-mediated IPC mechanism.
  • AIDL: Interface definition language for typed Binder contracts.
  • Signature permission: Permission granted to applications signed with a trusted matching certificate.
  • Package visibility: Filter controlling which installed packages an app can discover.
  • Command envelope: Versioned request referencing durable automation intent.

Mental Model Diagram

shortcut  tile  widget  notification  plugin app  webhook bridge
    |       |      |         |             |             |
    +-------+------+---------+-------------+-------------+
                              |
                    validate CommandEnvelope
                              |
             +----------------+----------------+
             |                                 |
       same-package UI                  cross-package IPC
                                        explicit target
                                  signer + caller + version
             |                                 |
             +----------------+----------------+
                              |
                      reload current routine
                              |
                 capability + policy + execution

How It Works

  1. Define a versioned command and result schema.
  2. Declare the smallest required exported discovery surface.
  3. Discover only packages matching targeted queries or explicit enrollment.
  4. Verify caller, package, signer, protocol, schema, size, and requested action.
  5. Persist or enqueue the command using a stable routine ID.
  6. Enforce timeout, cancellation, and Binder death handling.
  7. Return a typed result and record redacted evidence.

Invariants: no cross-app payload becomes executable code; command surfaces recheck current rules; external callers receive only explicitly declared capabilities. Failure modes include intent spoofing, confused-deputy behavior, stale PendingIntents, binder death, transaction overflow, implicit service binding, visibility gaps, and version skew.

Minimal Concrete Example

PluginRequest v2:
  request_id: 42b7...
  action_id: lights.set_scene
  config: {scene: "focus"}
  deadline_ms: 5000
  idempotency_key: run-9/action-2

PluginResult:
  status: NEEDS_USER_ACTION
  reason: target account signed out
  resolution: opaque PendingIntent token

Common Misconceptions

  • “Explicit Intent means trusted input.” It narrows resolution but payload and caller still need validation.
  • “Binder calls are ordinary local calls.” The remote process can block, die, or return malformed data.
  • “Plugin discovery requires all package visibility.” Targeted intent queries and enrollment usually suffice.
  • “Tiles stay alive.” TileService lifecycle is system-controlled.

Check-Your-Understanding Questions

  1. Why should a shortcut contain a routine ID rather than a serialized rule?
  2. When is a signature permission insufficient for a plugin ecosystem?
  3. How does a needs-user-action result differ from failure?

Check-Your-Understanding Answers

  1. The current rule may change, and large mutable payloads are unsafe and stale.
  2. When independently signed third parties must participate; user trust enrollment and protocol authorization are then needed.
  3. It preserves a safe, explicit resolution the user can choose rather than retrying or escalating automatically.

Real-World Applications

Password-manager autofill, media controllers, launcher shortcuts, smart-home plugins, enterprise agent suites, payment apps, and browser providers use Android IPC and delegated user actions.

Where You Will Apply It

Projects 7, 10, 12, and 15.

References

  • Android Developers, “Intents and intent filters”: https://developer.android.com/guide/components/intents-filters
  • Android Developers, “Restrict interactions with other apps”: https://developer.android.com/training/permissions/restrict-interactions
  • Android Developers, “Package visibility”: https://developer.android.com/training/package-visibility
  • Android Developers, “Quick Settings tiles”: https://developer.android.com/develop/ui/views/quicksettings-tiles
  • “Enterprise Integration Patterns” — Message Endpoint, Request-Reply, Correlation Identifier.

Key Insight

Every plugin and command surface is an untrusted request adapter into the same durable, capability-gated command bus.

Summary

Explicit IPC, version negotiation, signer/caller checks, targeted discovery, typed results, durable IDs, and lock-aware user initiation let an automation ecosystem expand without exposing ambient authority.

Homework / Exercises

  1. Threat-model an exported plugin service with five hostile-caller cases.
  2. Design the lifecycle of a Quick Settings tile that invokes a disabled routine.

Solutions to the Homework / Exercises

  1. Include spoofed action, wrong signer, oversized payload, unsupported version, replayed idempotency key, and Binder disconnect.
  2. The tile displays unavailable, a tap opens an explanatory user-approved surface, and it never silently re-enables the routine.

Chapter 7: Accessibility UI Automation and Consent-Driven Screen Understanding

Fundamentals

AccessibilityService can observe accessibility events, retrieve supported window content, traverse AccessibilityNodeInfo trees, invoke semantic actions, perform global actions, and dispatch gestures when configured. These capabilities make deterministic AutoInput-style macros possible, but they are sensitive and fragile. The accessibility tree is not the visual pixel tree: nodes can be missing, recycled, stale, unlabeled, virtualized, or changed by app updates and localization. Semantic selectors should prefer stable resource IDs, package, class, role, content description, text constraints, and structural relationships; raw coordinates are a last resort. MediaProjection is a separate, user-consented session for screen or app-window capture. It does not create silent permanent screenshot authority. Safe automation uses explicit package allowlists, narrow human-authored scripts, visible execution, bounded waits, sensitive-field exclusions, and an emergency stop.

Deep Dive

An accessibility service is enabled by the user in system Settings and bound by Android. Configuration declares event types, package scope, feedback type, flags, window-content retrieval, gesture support, and other capabilities. The service receives event callbacks such as window changes, view clicks, text changes, and content updates. It should filter early by selected packages and event types because unrestricted observation is noisy and sensitive.

AccessibilityNodeInfo represents a snapshot-like handle into a remote UI hierarchy. It can expose package, class, view ID, text, content description, state flags, bounds, actions, parent, and children. A node can become stale after the UI changes. Never persist the node object. Persist a selector description and reacquire from the current root for each step. Recycle semantics vary by API history, but the conceptual rule remains: remote UI objects are transient.

Selector design determines robustness. Prefer a unique resource ID scoped to package. Add semantic constraints such as role/class and visible text only when needed. Text is localized and user-controlled, so exact text-only selectors are brittle. Structural selectors like “editable field below label Email” can survive some layout changes but require bounded traversal. Coordinates depend on density, rotation, insets, keyboard, split screen, and responsive layout. A recorder should show selector confidence and offer alternatives instead of pretending one captured tap is permanent.

Macro execution is a state machine, not a loop of fixed delays. Each step has a precondition, selector, action, completion signal, timeout, retry class, and failure evidence. The runner waits for meaningful events or polls within a bounded deadline, reacquires the tree, and confirms postconditions. Fixed sleep only masks races. If the package changes unexpectedly, a secure window appears, a prohibited field is focused, consent is revoked, or the user presses stop, execution terminates.

Gesture dispatch can provide a fallback for elements without semantic actions. It must be visibly labeled as less robust. Global actions such as Back or Home are explicit steps with policy restrictions. The runner must never automate permission dialogs, credentials, PINs, CAPTCHAs, purchases, money transfers, security warnings, or attempts to bypass another app’s protections. A sandbox target app lets the learner prove architecture without encouraging unsafe automation against third-party products.

Overlays can show a recorder HUD, selector highlight, current step, pause, and emergency stop. SYSTEM_ALERT_WINDOW is special access and subject to touch-obscuring protections. An accessibility overlay may be more appropriate for legitimate accessibility UI, depending on product purpose. The overlay must never imitate system dialogs or capture input deceptively.

MediaProjection provides pixels after explicit user consent. On current Android, each session and token have lifecycle constraints; modern targets require an appropriate foreground service for ongoing projection, and the system shows capture state. A screen-understanding adapter can crop the selected app, run local OCR or visual matching, and discard frames. It should prefer accessibility semantics when available and use pixels for user-assisted inspection rather than bypassing secure or inaccessible content. FLAG_SECURE and system consent are boundaries, not puzzles to defeat.

Distribution policy is as important as API mechanics. A general automation app using AccessibilityService must support a narrow, clearly understood, deterministic user-authored purpose, disclose use prominently, collect affirmative consent, and accurately declare it. It must not mislabel itself as an accessibility tool unless disability assistance is genuinely its core purpose. An AI model may help suggest a selector offline, but it must not autonomously plan and execute open-ended actions through AccessibilityService.

How This Fits on Projects

Project 8 builds the inspector and selector model. Project 9 builds the deterministic macro state machine. Project 11 adds user-consented screen capture and OCR. Projects 14 and 15 test revocation, UI drift, and emergency stop.

Definitions and Key Terms

  • Accessibility event: System callback describing a UI accessibility change or interaction.
  • Accessibility node: Transient semantic representation of part of a window hierarchy.
  • Semantic selector: Query based on stable UI meaning rather than only screen coordinates.
  • Postcondition: Observable state proving a macro step completed.
  • Gesture dispatch: Accessibility capability for synthesized touch paths.
  • MediaProjection: User-consented API for capturing a display or selected app surface.

Mental Model Diagram

 current target app
      |
      +--> semantic tree --------------------+
      |     id / role / label / action       |
      |                                      v
      +--> consented pixels ----------> selector candidates
            crop / OCR / match               |
                                             v
                                  reacquire + verify step
                                             |
                         +-------------------+-------------------+
                         |                                       |
                  semantic action                         gesture fallback
                         |                                       |
                         +-------------------+-------------------+
                                             v
                               postcondition / timeout / stop

How It Works

  1. The user selects an allowed package and starts a visibly controlled recording session.
  2. The inspector captures semantic candidates and, only with consent, optional pixels.
  3. The user chooses a selector and sees stability warnings.
  4. The runner starts a persistent visible controller and execution trace.
  5. Each step reacquires the root, finds a unique candidate, checks prohibitions, acts, and waits for a postcondition.
  6. Revocation, package escape, ambiguity, timeout, secure content, or stop ends the macro.
  7. The trace stores redacted selectors and evidence, never captured secrets.

Invariants: no transient node is persisted; no step acts on multiple ambiguous nodes; no prohibited surface is automated; the user can stop immediately. Failure modes include stale nodes, localization, app redesign, WebView semantics, custom canvas UI, soft keyboard changes, rotation, overlays, locked device, and revoked service access.

Minimal Concrete Example

MacroStep:
  package: com.example.sandbox
  selector:
    view_id: demo_email
    class: android.widget.EditText
  action: SET_TEXT("learner@example.test")
  prohibit_if: password=true OR secure_window=true
  postcondition: node_text_equals(redacted_expected)
  timeout: 3s

Common Misconceptions

  • “The accessibility tree is the screen.” It is a semantic representation supplied by app widgets and may be incomplete.
  • “Coordinates are universal.” Device and layout conditions make them fragile.
  • “Long delays make macros reliable.” State-based waits and postconditions do.
  • “Screen capture can run silently forever once granted.” Projection is session-bound and visibly controlled.

Check-Your-Understanding Questions

  1. Why reacquire the node before every action?
  2. What makes a selector confidence score honest?
  3. When should a pixel match not fall back to a tap?

Check-Your-Understanding Answers

  1. UI changes invalidate remote node handles.
  2. It reflects stable IDs, semantic uniqueness, localization dependence, structural depth, and coordinate reliance.
  3. When the target is ambiguous, secure, outside the allowlisted package, or lacks a safe postcondition.

Real-World Applications

Assistive technology, testing tools, form helpers, device labs, kiosk assistance, RPA, screen annotation, and user-guided capture tools use these mechanisms.

Where You Will Apply It

Projects 8, 9, 11, 14, and 15.

References

  • Android Developers, “Create an accessibility service”: https://developer.android.com/guide/topics/ui/accessibility/service
  • AccessibilityService reference: https://developer.android.com/reference/android/accessibilityservice/AccessibilityService
  • Android Developers, “Media projection”: https://developer.android.com/media/grow/media-projection
  • Google Play AccessibilityService policy: https://support.google.com/googleplay/android-developer/answer/10964491
  • “Designing with the Mind in Mind” by Jeff Johnson — perception and UI interaction chapters.

Key Insight

Reliable UI automation is a consentful state machine over reacquired semantic evidence, not a recording of coordinates and sleeps.

Summary

Package filtering, semantic selectors, transient-node discipline, postconditions, bounded waits, visible control, strict prohibitions, and separate screen-capture consent make UI automation safer and more resilient.

Homework / Exercises

  1. Rank five selector strategies from most to least robust for a localized form.
  2. Draw failure transitions for a three-step macro when the package changes during step two.

Solutions to the Homework / Exercises

  1. Stable resource ID; ID plus role; semantic label and role; bounded structural relation; text-only; coordinate-only last.
  2. Detect package escape before action, cancel remaining steps, stop visible execution, record evidence, and require explicit user restart.

Chapter 8: Security, Observability, Testing, and Compatibility

Fundamentals

Automation software combines high authority with asynchronous failure, so security and observability are one design problem. A trace must explain an action without leaking the sensitive content that enabled it. External commands must be authenticated, authorized, freshness-checked, bounded, and mapped to predeclared actions rather than evaluated as code. Secrets belong in Android Keystore-backed designs and are never exported in support bundles. Testing spans pure rule evaluation, Room migration, scheduler behavior, IPC contracts, permission revocation, process death, accessibility drift, managed-device provisioning, and OS-version compatibility. A green unit suite cannot prove real platform behavior, while manual success cannot prove deterministic semantics. The goal is layered evidence: fast pure tests, instrumented adapter tests, hostile-input tests, lifecycle fault injection, performance and battery measurements, and redacted production diagnostics.

Deep Dive

Begin with a threat model. Assets include user-authored rules, notification and screen content, credentials or webhook secrets, plugin trust records, administrative authority, run history, and the ability to perform actions. Actors include the user, trusted plugin, untrusted installed app, malicious webhook sender, compromised server, accidental misconfiguration, stale package update, and curious support recipient. Entry points include exported components, deep links, bound services, notification actions, PendingIntents, content URIs, network clients, accessibility callbacks, backup/import files, and debug tools.

Authentication answers who sent a request; authorization answers whether that identity may invoke this action with these parameters. A valid HMAC does not authorize arbitrary shell text. The webhook protocol should name a preconfigured routine, carry timestamp, nonce, key ID, body hash, and idempotency ID, then enforce a narrow parameter schema. The app rejects expired timestamps, reused nonces, unknown routines, oversized bodies, disallowed destinations, and invalid signatures. Inbound commands that create meaningful external effects can become proposals requiring local confirmation.

Plugins require package and signer validation on every connection because package contents can change. Exported components use permissions, explicit intents, or caller checks appropriate to the ecosystem. URI grants are narrow and temporary. Deserialization is bounded and versioned. An import file is data, never dynamically loaded executable code. ADB or Termux bridges do not receive an arbitrary command interpreter from the consumer app; they expose allowlisted operations with local configuration and logs.

Sensitive logging is a common self-inflicted breach. Use structured events with a data classification per field. Store hashes, lengths, rule IDs, package IDs when necessary, and categorical outcomes instead of raw text. Correlation IDs connect source, plan, attempts, and results. A support bundle includes app/build version, device/API, capability states, scheduler health, redacted trace summaries, migration versions, and user-selected logs. The user previews it before export.

Observability separates four kinds of failure: trigger was not observed, rule did not match, action was blocked before execution, or adapter execution failed. Without that separation, users report “automation didn’t run” and developers guess. Health metrics track last successful source event, queue depth, dedupe counts, dropped events, schedule delay, plugin connection state, service connection, revocation, retry counts, and emergency stops.

Testing mirrors the architecture. Pure property tests assert deterministic evaluation, bounded causation, and schema migration. Repository tests verify transactions and recovery. WorkManager and alarm tests use test drivers and device-level ADB scenarios. IPC tests include a hostile app signed with a different key, wrong version, replay, timeout, binder death, and oversized input. Accessibility tests run only against the included sandbox target with predictable semantics and deliberate UI versions. MediaProjection tests cover denial, rotation, session stop, and device lock. DPC tests run on disposable emulators.

Process-death tests interrupt at critical windows: after plan commit, during adapter call, after external success but before result commit, and during retry scheduling. Each outcome must be reconstructable, idempotent, or explicitly ambiguous. Network tests inject DNS failure, TLS failure, timeout, 429, 500, malformed JSON, and stale signature. Time tests use injectable clocks and real DST emulator scenarios.

Compatibility is a matrix, not a final check. Track min SDK, target SDK, runtime API, OEM, device form factor, installation source, managed state, and feature availability. Current reference work targets API 36, whose behavior changes include safer intent options and job quota evolution. Test the oldest supported API and at least one modern physical OEM. Adapters own conditional platform behavior and emit one stable domain contract.

Performance tests focus on event storms, database growth, startup reconciliation, accessibility traversal bounds, Compose editor responsiveness, and battery/wakeup behavior. An automation platform that drains the battery will be restricted by users and the OS, reducing its reliability. Correctness includes resource restraint.

How This Fits on Projects

Security requirements begin in Project 1 and harden in Projects 10, 12, and 13. Project 14 builds the full observatory and fault lab. Project 15 cannot finish until the threat model, policy matrix, tests, and support bundle pass.

Definitions and Key Terms

  • Threat model: Structured analysis of assets, actors, entry points, abuse cases, and controls.
  • Correlation ID: Identifier linking all records for one automation run.
  • Replay protection: Rejection of previously accepted authenticated requests.
  • Redaction: Removing or transforming sensitive values before persistence or export.
  • Fault injection: Deliberately triggering failures to verify containment and recovery.
  • Compatibility matrix: Tested combinations of platform, target, device, installation, and authority states.

Mental Model Diagram

 untrusted input -> authenticate -> authorize -> validate -> capability gate
        |                                                |
        +---------------- reject with evidence ----------+
                                                         |
                                                    execute adapter
                                                         |
        +------------------- correlation ID -------------+
        |                |               |               |
      source           plan          attempts         outcome
        |                |               |               |
        +----------------+---------------+---------------+
                             redact by schema
                                   |
                    local diagnostics / previewed bundle

How It Works

  1. Enumerate assets, actors, entry points, and prohibited outcomes.
  2. Attach data classifications and authority declarations to every adapter schema.
  3. Validate and authorize all external inputs before capability checks.
  4. Persist structured, redacted trace transitions with correlation and causation IDs.
  5. Test pure logic, storage, adapters, hostile callers, lifecycle loss, and platform compatibility separately.
  6. Inject failures at side-effect boundaries and classify ambiguity.
  7. Measure queue, wakeup, storage, latency, and battery behavior.

Invariants: logs never become a second sensitive-data store; authenticated requests are still narrowly authorized; debug injection cannot enter release builds. Failure modes include secret leakage, replay, intent spoofing, confused deputy, unbounded traversal, test-only success, incompatible migrations, and missing failure telemetry.

Minimal Concrete Example

RunTrace:
  correlation_id: run-77
  source: notification.posted
  source_payload: {package: com.example.mail, text: REDACTED, length: 86}
  rule: urgent-mail-digest
  decision: MATCH
  action: webhook.send(preconfigured_destination=home-server)
  outcome: RETRY_SCHEDULED
  reason: HTTP_503
  secret_fields_persisted: none

Common Misconceptions

  • “Authenticated means authorized.” Identity does not grant every action.
  • “Debug logs can contain anything.” Debug data is frequently retained, shared, or backed up.
  • “Unit tests prove Android lifecycle behavior.” Device-level tests are necessary for adapters and grants.
  • “Compatibility is just min SDK.” Target SDK, OEM, managed state, and install source change behavior.

Check-Your-Understanding Questions

  1. Why is action ambiguity a valid trace state?
  2. What belongs in a support bundle preview?
  3. Why test a plugin signed by an untrusted key?

Check-Your-Understanding Answers

  1. The external effect may have succeeded before the process died; pretending success or failure can cause unsafe replay.
  2. Exact redacted fields, device/build metadata, capability state, and user-selected trace range.
  3. It proves signer and authorization controls rather than only the happy path.

Real-World Applications

Enterprise automation, RPA, MDM, integration platforms, incident tooling, payment orchestration, and password managers rely on secure command handling and deep diagnostics.

Where You Will Apply It

Projects 1-15, especially 10, 12, 13, 14, and 15.

References

  • Android Developers, “Security best practices”: https://developer.android.com/privacy-and-security/security-best-practices
  • Android Developers, “Safer intents” in Android 16 behavior changes: https://developer.android.com/about/versions/16/behavior-changes-16
  • “Security in Computing” by Charles Pfleeger et al. — access control and software security chapters.
  • “Release It!, 2nd Edition” by Michael T. Nygard — stability, timeouts, and operational visibility.
  • “Test Driven Development: By Example” by Kent Beck — feedback and test design.

Key Insight

In high-authority automation, evidence must be detailed enough to debug behavior and constrained enough not to become another breach.

Summary

Threat modeling, narrow authorization, structured redaction, correlation, layered tests, side-effect fault injection, compatibility matrices, and resource measurements define production readiness.

Homework / Exercises

  1. Write an abuse case for each external entry point in the proposed capstone.
  2. Design four process-death injection points and expected recovery states.

Solutions to the Homework / Exercises

  1. Include spoofing, replay, parameter expansion, oversized data, stale signer, and user-confusion cases with preventive and detective controls.
  2. Before plan commit: no action; after plan commit: resume eligible work; after external success before commit: ambiguous/idempotency check; after failure commit before retry enqueue: reconciliation schedules retry.

Glossary

  • AccessibilityService: User-enabled service that receives accessibility events and may inspect or act on supported UI semantics.
  • Action adapter: Boundary that converts a domain action descriptor into a platform or external effect.
  • App-op: System operation gate that can supplement manifest permission state.
  • At-least-once: Delivery model in which an operation may be attempted more than once.
  • Capability registry: Service that explains current support, authority, health, and degraded behavior for every trigger/action.
  • Causation ID: Identifier connecting an event to the action or event that produced it.
  • Condition tree: Pure Boolean/unknown expression evaluated against an event and context snapshot.
  • Device owner: Administratively provisioned controller for a fully managed device.
  • ECA: Event-condition-action automation model.
  • Foreground service: Immediate, user-perceptible work accompanied by a persistent notification and modern execution restrictions.
  • Idempotency key: Stable request identity used to prevent duplicate external effects.
  • MediaProjection: User-consented, session-scoped display or app-window capture API.
  • Notification listener: User-enabled service that observes notification lifecycle events and allowed actions.
  • Package visibility: Android filtering of which installed applications a package can discover.
  • Profile owner: Administrative controller for a managed profile.
  • Reconciliation: Process of aligning disposable OS registrations with durable desired state.
  • Rule graph: Versioned domain representation of triggers, conditions, and actions.
  • Special app access: Settings-mediated authority outside ordinary dangerous permission dialogs.
  • Unknown condition: Explicit evaluation result indicating missing or unavailable context.
  • WorkManager: AndroidX scheduler for persistent, deferrable, constraint-aware background work.

Why Android Automation Apps Matter

Android is deployed on more than three billion active devices across more than 190 countries, according to Google’s 2025 Android ecosystem update. That scale turns the phone into the most widely available programmable edge computer many people own. Automation can reduce repetitive interaction, bridge inaccessible workflows, coordinate personal devices, create field-worker and kiosk experiences, route urgent information, and connect local context to servers or home systems.

The platform is also intentionally tightening background execution, package discovery, sensitive-data access, screen capture, and inter-app control. Android 16/API 36 continues this evolution with job quota changes and safer-intent behavior. The opportunity is therefore not “find one more bypass.” It is to build automation that composes supported capabilities while preserving user control.

 brittle automation                       capability-aware automation
 +----------------------+                 +---------------------------+
 | always-running loop  |                 | event-driven adapters     |
 | global observation   |                 | selected packages/data    |
 | fixed sleeps/taps    |                 | semantic postconditions   |
 | hidden failure       |                 | redacted execution trace  |
 | grant everything     |                 | progressive consent       |
 +----------+-----------+                 +-------------+-------------+
            |                                               |
            v                                               v
     works on my phone                              explainable product

Modern use cases

  • Personal context routines and user-initiated shortcuts.
  • Assistive deterministic macros for repetitive, non-sensitive app workflows.
  • Notification prioritization and local digests.
  • Enterprise managed-device, kiosk, and field-work policy.
  • Secure device-to-server and Termux integrations.
  • QA and device-lab automation against owned test applications.

Context and evolution

Early Android apps could rely more heavily on long-running services and broad implicit broadcasts. Android 8 introduced major background execution and broadcast limits; Android 11 added package visibility; Android 12 tightened foreground-service starts and exact-alarm access; newer versions continue to require typed foreground services, user-visible capture, and safer IPC. This evolution rewards event-driven, capability-declared, user-visible architecture.

Sources:

  • Google, “The Android Show: I/O Edition 2025”: https://blog.google/products-and-platforms/platforms/android/the-android-show-io-2025/
  • Android Developers, Android 16 behavior changes: https://developer.android.com/about/versions/16/behavior-changes-all
  • Android Developers, background work overview: https://developer.android.com/develop/background-work

Concept Summary Table

Concept Cluster What You Need to Internalize
Android Components and Capability Boundaries Components are entry contracts inside a disposable process; capability availability, authority, lifecycle, policy, and health must be modeled separately.
Permissions, Consent, Privacy, and Policy Progressive consent, least authority, data minimization, revocation, and distribution requirements form one product state machine.
ECA Rule Engines Pure planning over typed events and context produces immutable plans; adapters own side effects, idempotency, and ambiguity.
Event Sources and Backpressure Source-specific semantics must be normalized, deduplicated, pressure-controlled, and made observable.
Scheduling and Durable Work WorkManager, alarms, foreground services, and callbacks solve different problems; durable intent and reconciliation are the source of truth.
IPC, Plugins, and Command Surfaces Every external command is untrusted; explicit targets, signer/caller checks, versioned schemas, and stable IDs protect the engine.
Accessibility and Screen Understanding Semantic selection, reacquisition, postconditions, visible execution, and strict prohibitions replace coordinate-and-sleep fragility.
Security, Observability, Testing, and Compatibility Narrow authorization, redacted traces, layered tests, fault injection, and compatibility matrices define reliable automation.

Project-to-Concept Map

Project Concepts Applied
1. Capability Navigator Components; consent; security and compatibility
2. Context Signal Monitor Components; event sources and backpressure
3. RuleForge Core ECA rule engines; security and testing
4. Durable Automation Library ECA versioning; durable state; testing
5. Timekeeper Scheduler Scheduling; event sources; observability
6. Notification Router Consent; event sources; scheduling; redaction
7. Command Surfaces IPC, command surfaces; components
8. Accessibility Inspector Accessibility; consent; event backpressure
9. UI Macro Runner Accessibility; ECA; scheduling; safety
10. Plugin SDK and IPC Host IPC/plugins; security; compatibility
11. ScreenLens Accessibility/screen understanding; consent; lifecycle
12. Secure Webhook and Termux Bridge IPC; durable work; security
13. Managed-Device Policy Lab Capability boundaries; consent/policy; security
14. Automation Observatory Security; observability; testing; all adapter semantics
15. FlowForge Studio All eight concept clusters

Deep Dive Reading by Concept

Concept Book and Chapter Why This Matters
Components and lifecycle “Operating Systems: Three Easy Pieces” — Processes and Persistence chapters Builds the disposable-process and durable-state mental model.
API and model design “Effective Java, 3rd Edition” — Items 15-25, 50, 78-84 Helps create immutable, defensive, concurrent Kotlin/JVM contracts.
Rule engine architecture “Design Patterns” — Command, Composite, State, Strategy Provides the vocabulary for rules, plans, and adapters.
Messaging and IPC “Enterprise Integration Patterns” — Message, Router, Request-Reply, Idempotent Receiver Maps directly to events, plugins, correlation, and retries.
Boundaries “Clean Architecture” — Chapters on component boundaries and policy Keeps Android mechanisms outside the deterministic core.
Reliability “Release It!, 2nd Edition” — stability patterns, timeouts, and operations Makes failure, retry, and isolation deliberate.
Security “Foundations of Information Security” — access control and risk chapters Grounds consent, least authority, and threat models.
Testing “Test Driven Development: By Example” — Parts I and II Establishes feedback loops for domain logic and adapters.

Official Android documentation is the primary reference for API-level behavior. Books supply architecture and reasoning patterns; they do not override current platform or Play policy.

Quick Start: Your First 48 Hours

Day 1

  1. Read Chapters 1-3 and draw the capability, event, and execution-plan models.
  2. Create the Android Studio project with app, domain, platform-adapters, and test boundaries.
  3. Start Project 1 with three read-only capabilities: notifications enabled, battery optimization state, and exact-alarm support.
  4. Render Available, Needs consent, Unsupported, and Temporarily unavailable states without requesting anything.

Day 2

  1. Add one contextual consent journey and recheck state on return.
  2. Complete Project 1’s process-recreation and revocation tests.
  3. Read Chapter 4 and start Project 2 with power and connectivity signals plus a debug injector.
  4. Save a redacted test transcript and compare it to the Definition of Done.

Path 1: Consumer Automation Builder

  • Projects 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 10 -> 12 -> 14 -> 15

Path 2: AutoInput-Style UI Automation Specialist

  • Projects 1 -> 2 -> 3 -> 4 -> 8 -> 9 -> 11 -> 14 -> 15

Path 3: Enterprise Device Controller

  • Projects 1 -> 3 -> 4 -> 5 -> 10 -> 12 -> 13 -> 14 -> 15

Path 4: Complete Platform Architect

  • Projects 1-15 in order.

Success Metrics

  • You can explain why an action is Available, Needs consent, Temporarily unavailable, Unsupported, or Policy-managed without looking at code.
  • Pure JVM tests can evaluate and replay rules without Android framework dependencies.
  • Every adapter declares authority, sensitivity, lifecycle, timeout, retry, and degraded behavior.
  • Rules survive process death, reboot reconciliation, schema migration, and capability revocation.
  • A notification, plugin, webhook, and accessibility macro each produce one understandable redacted trace.
  • The UI macro stops on ambiguity, package escape, prohibited fields, revocation, or emergency stop.
  • Hostile IPC, replay, oversized input, stale signer, and ambiguous side-effect tests pass.
  • Actual schedule delay and dropped/coalesced event counts are visible.
  • The Play-policy matrix accurately distinguishes consumer, enterprise, and sideload/developer tracks.

Android Automation Capability Matrix

Capability Normal consumer app Extra user/system step Important boundary
Runtime permission Yes In-app system dialog Can be denied or revoked
Notification listener Yes Enable in Settings Sensitive content; service can disconnect
Usage access Yes Special access in Settings Historical/approximate, not a perfect live callback
Exact alarms Conditional Special access on modern Android Use only when timing contract justifies it
Accessibility automation Conditional Enable service in Settings Narrow deterministic purpose, disclosure, policy review
MediaProjection Session-based User consents to capture Visible, revocable, not silent persistent capture
Quick Settings tile Yes User adds tile Service lifecycle is disposable
Plugin IPC Yes Install/enroll plugin Export, signer, caller, schema, and visibility controls
Device policy Managed track Provision profile/device owner Not an ordinary permission
ADB/shell bridge Developer track Pair/authorize outside app Shell is a separate identity, not Play-app authority
Root/privileged permissions No ordinary path System image/root provisioning Explicitly outside consumer architecture

Debugging and Safety Appendix

When an automation “did not run,” classify in this order

  1. Was the trigger source healthy and did it observe the event?
  2. Was the event normalized or coalesced?
  3. Was the rule enabled and did every condition return true?
  4. Did planning reject a cycle, cooldown, schema, or conflict?
  5. Was the required capability available at execution time?
  6. Did Android reject the execution mechanism?
  7. Did the adapter return retryable, permanent, user-action, or ambiguous?
  8. Was the result persisted and rendered?

Never automate

  • Passwords, PINs, one-time codes, CAPTCHAs, biometric prompts, or secure credential fields.
  • Permission grants, accessibility enablement, restricted-setting confirmation, Play Protect warnings, or device-admin enrollment.
  • Purchases, money transfers, legal consent, destructive account actions, or security dialogs.
  • Attempts to defeat FLAG_SECURE, lock screen, app sandbox, SELinux, package signatures, or policy enforcement.

Project Overview Table

# Project Difficulty Time Primary Observable Outcome
1 Capability Navigator Level 1 10-14 h Live permission/capability dashboard
2 Context Signal Monitor Level 2 16-22 h Normalized event timeline
3 RuleForge Core Level 3 22-30 h Deterministic rule trace and simulator
4 Durable Automation Library Level 2 18-26 h Migratable rules surviving process death
5 Timekeeper Scheduler Level 3 20-30 h Requested-vs-actual schedule diagnostics
6 Privacy-First Notification Router Level 3 20-28 h Redacted notification-triggered routine
7 Command Surface Deck Level 2 16-22 h Tile, shortcut, widget, notification entry points
8 Accessibility Inspector Level 3 24-34 h Live semantic tree and selector confidence
9 Consentful UI Macro Runner Level 4 30-42 h Safe deterministic sandbox macro
10 Plugin SDK and IPC Host Level 4 28-40 h Trusted third-party trigger/action plugin
11 ScreenLens Capture Lab Level 3 22-32 h Session-based capture and local OCR
12 Secure Webhook and Termux Bridge Level 3 24-34 h Signed outbound/inbound allowlisted routines
13 Managed-Device Policy Lab Level 4 26-38 h Reversible DPC policy on disposable emulator
14 Automation Observatory Level 3 28-40 h Replay, fault injection, support bundle
15 FlowForge Automation Studio Level 4 50-75 h Integrated Tasker-style capstone

Project List

The projects progress from passive capability inspection to a complete automation platform. Their source summaries intentionally stop short of runnable solutions; the linked expanded files contain staged guidance, architecture, tests, and extensions.

Project 1: Capability Navigator

  • File: P01-capability-navigator.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java; Kotlin Multiplatform for the pure model only
  • Coolness Level: Level 2 — Practical but Forgettable
  • Business Potential: Level 1 — Resume Gold
  • Difficulty: Level 1 — Beginner
  • Knowledge Area: Android components, permissions, consent UX, compatibility
  • Software or Tool: Android Studio, Jetpack Compose, Activity Result APIs
  • Main Book: “Effective Java, 3rd Edition”

What you will build: A Compose dashboard that explains and verifies every automation capability without requesting all authority up front.

Why it teaches Android automation: Every later trigger and action depends on accurately distinguishing support, consent, current health, and administrative mode.

Core challenges you will face:

  • Representing more than Boolean permission state -> maps to capability boundaries.
  • Returning from Settings and re-verifying reality -> maps to lifecycle and revocation.
  • Explaining sensitive access without coercion -> maps to consent and policy.

Real World Outcome

Launching the app shows grouped cards for Notifications, Exact timing, Usage access, Accessibility macros, Screen capture, Plugins, and Managed device. Each card displays one of Available, Needs consent, Temporarily unavailable, Unsupported, or Policy-managed; an evidence line names the exact gate; and an expandable panel explains data used, visible indicators, degraded behavior, and revocation. Tapping “Review notification access” opens the correct system screen. Returning refreshes the card without restarting. Rotating, killing, and reopening the app produces the same truthful state. A “Simulate denial” debug control previews how blocked rules will appear without granting anything.

The Core Question You Are Answering

“What does this app actually have the authority to do right now, and how can it explain that truth to both the user and the executor?”

The answer becomes a reusable runtime contract rather than a collection of UI permission checks.

Concepts You Must Understand First

  1. Components and process lifecycle
    • Which state can disappear with the process?
    • Book Reference: “Operating Systems: Three Easy Pieces” — Processes chapters.
  2. Permission and special-access classes
    • Which grants use dialogs, Settings, roles, session consent, or provisioning?
    • Book Reference: “Foundations of Information Security” — access control chapters.
  3. Immutable state modeling
    • How does the UI render every capability state exhaustively?
    • Book Reference: “Effective Java, 3rd Edition” — Items 15-25.

Questions to Guide Your Design

  1. Which checks are static, dynamic, temporary, or policy-controlled?
  2. How will the app avoid a permission request before the user enables a dependent feature?
  3. What state appears if the manifest declaration is missing despite a user-facing setting?
  4. How does the executor reuse the exact same registry as the editor?

Thinking Exercise

Draw state machines for runtime location, notification access, MediaProjection, and device owner. Mark which transitions the app initiates, which the user controls, and which cannot occur in a consumer install. Then explain why a shared Boolean hasPermission abstraction would lie.

The Interview Questions They Will Ask

  1. “How are runtime permissions different from special app access?”
  2. “How do you detect permission revocation while an app is backgrounded?”
  3. “Why can’t a normal app request device-owner status like a dangerous permission?”
  4. “How would you make a permission onboarding flow testable?”
  5. “What changes when target SDK increases?”

Hints in Layers

Hint 1: Start read-only
Render capability evidence before implementing any journey.

Hint 2: Model a sealed result
Use domain states with reason codes and optional resolution descriptors.

Hint 3: Separate check from resolution
The checker observes; a journey coordinator opens system surfaces and rechecks later.

Hint 4: Test stale assumptions
Grant, background, revoke through Settings, and return without reconstructing the whole app.

Books That Will Help

Topic Book Chapter
API state design “Effective Java, 3rd Edition” Items 15-25
Process lifetime “Operating Systems: Three Easy Pieces” Processes
Consent and access “Foundations of Information Security” Access control

Common Pitfalls and Debugging

Problem 1: “The card stays Available after revocation.”

  • Why: State was cached instead of verified on lifecycle return.
  • Fix: Treat resume as a recheck signal and keep the registry authoritative.
  • Quick test: Revoke in Settings, return with Back, and observe an immediate transition.

Problem 2: “A settings Intent has no handler.”

  • Why: OEM or API-level differences make the assumed resolution unavailable.
  • Fix: capability-check the resolution and provide manual navigation text.
  • Quick test: Run the same journey on two emulator API levels.

Definition of Done

  • At least seven capability types render exhaustive states and reason codes.
  • No permission is requested during app launch.
  • Every journey has rationale, system transition, return verification, denial, and revocation behavior.
  • Process recreation and an unsupported-device case are tested.
  • The registry is usable by UI and headless executor code.

Project 2: Context Signal Monitor

  • File: P02-context-signal-monitor.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java; Scala on the pure event model
  • Coolness Level: Level 3 — Genuinely Clever
  • Business Potential: Level 2 — Micro-SaaS / Pro Tool
  • Difficulty: Level 2 — Intermediate
  • Knowledge Area: Broadcasts, callbacks, Flow, normalization, backpressure
  • Software or Tool: BroadcastReceiver, ConnectivityManager, coroutines/Flow
  • Main Book: “Enterprise Integration Patterns”

What you will build: A live event laboratory for power, network, foreground/background, headset/Bluetooth where supported, and synthetic debug signals.

Why it teaches Android automation: Reliable rules begin with understanding what an Android signal actually guarantees and how noisy callbacks become stable events.

Core challenges you will face:

  • Separating repeated state from meaningful transitions -> maps to event normalization.
  • Registering and unregistering callback sources safely -> maps to component lifecycle.
  • Handling event bursts with visible backpressure -> maps to bounded reactive systems.

Real World Outcome

The app’s Monitor screen shows two synchronized columns. “Raw observations” records adapter callbacks; “Canonical events” shows normalized domain envelopes. Plugging in power yields one power.connection.changed event even if several battery observations arrive. Switching Wi-Fi and cellular shows network state transitions with metering and validation, while a badge reports coalesced callbacks. A debug drawer injects deterministic events. Each timeline row exposes occurrence time, observation time, source, dedupe key, sensitivity class, and whether it was emitted, debounced, coalesced, or dropped.

The Core Question You Are Answering

“When Android tells me something changed, what exactly happened, how durable is that knowledge, and how much noise should enter the rule engine?”

Concepts You Must Understand First

  1. State versus event
    • When does a reading become a transition?
    • Book Reference: “Enterprise Integration Patterns” — Message and Event Message.
  2. Reactive streams
    • What happens when producers outpace consumers?
    • Book Reference: “Reactive Design Patterns” — flow control chapters.
  3. Android callback lifecycle
    • Which registrations survive only while the process is alive?
    • Book Reference: “Operating Systems: Three Easy Pieces” — concurrency and persistence.

Questions to Guide Your Design

  1. Which sources preserve every occurrence and which keep only the latest state?
  2. Where will you use debounce, coalescing, sampling, or bounded buffering?
  3. How will wall-clock changes affect event ordering?
  4. What health signal proves a source is registered and recently active?

Thinking Exercise

On paper, trace ten callbacks: three identical network states, power connected, two battery readings, a network loss/recovery burst, and two injected events. Decide which canonical events exist and justify every drop or coalescing decision.

The Interview Questions They Will Ask

  1. “What restrictions apply to manifest-declared implicit broadcasts?”
  2. “Why should a BroadcastReceiver not start an untracked thread?”
  3. “What is the difference between debounce and sample?”
  4. “How do StateFlow and SharedFlow differ for event sources?”
  5. “How would you test an adapter without manipulating a physical phone?”

Hints in Layers

Hint 1: Make a source port
Every adapter should emit the same domain envelope type.

Hint 2: Preserve diagnostics
Expose raw observations only in debug state; feed normalized events to rules.

Hint 3: Compare last normalized state
Transition events emerge from old versus new values.

Hint 4: Bound everything
Use explicit queue capacity and increment a metric whenever data is coalesced or dropped.

Books That Will Help

Topic Book Chapter
Message semantics “Enterprise Integration Patterns” Message, Event Message
Concurrency “Effective Java, 3rd Edition” Items 78-84
Reactive systems “Reactive Design Patterns” Flow control

Common Pitfalls and Debugging

Problem 1: “One charger action fires several times.”

  • Why: Raw battery and power callbacks were all treated as distinct connection events.
  • Fix: Derive a transition from stored normalized state and deduplicate.
  • Quick test: Connect once and assert one canonical transition despite multiple raw rows.

Problem 2: “Events stop after leaving the screen.”

  • Why: Source lifetime was coupled to the Compose screen unintentionally.
  • Fix: Declare whether the monitor is UI-scoped or automation-runtime scoped and register accordingly.
  • Quick test: Navigate away, trigger the source, and compare behavior to the documented lifecycle.

Definition of Done

  • At least four real sources and one synthetic source use one canonical envelope.
  • Raw and normalized timelines visibly differ.
  • Queue capacity, dedupe, coalescing, and drop counts are observable.
  • Registration lifecycle and process recreation are tested.
  • Sensitive payloads are redacted before persistence.

Project 3: RuleForge Event-Condition-Action Core

  • File: P03-ruleforge-core.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java; Rust for a separate pure engine experiment
  • Coolness Level: Level 4 — Hardcore Tech Flex
  • Business Potential: Level 4 — Open Core Infrastructure
  • Difficulty: Level 3 — Advanced
  • Knowledge Area: Domain modeling, interpreters, state machines, deterministic execution
  • Software or Tool: Kotlin/JVM tests, coroutines, Compose rule editor
  • Main Book: “Design Patterns”

What you will build: A pure, typed ECA engine with condition trees, dry-run planning, conflict policy, causation limits, and execution traces.

Why it teaches Android automation: Tasker-like power comes from a durable language and predictable runtime, not a pile of callback-specific actions.

Core challenges you will face:

  • Keeping planning pure while actions are effectful -> maps to clean boundaries.
  • Representing unknown conditions and partial outcomes -> maps to honest state machines.
  • Preventing loops and duplicate effects -> maps to causation and idempotency.

Real World Outcome

In the Rule Lab, the user constructs “When charger connects, if battery is below 40 percent and local time is before 23:00, post a demo notification.” Pressing Simulate opens a step-by-step trace: event matched, context snapshot ID, each condition and evidence, selected rule priority, required capabilities, planned action, and predicted result. Changing the context to unknown battery state changes the decision to WAIT or SKIP according to policy. A cycle demo shows a derived event blocked at maximum causation depth. The same scenarios run as fast JVM tests without an emulator.

The Core Question You Are Answering

“Can I explain exactly why a rule will act before I let any Android side effect happen?”

Concepts You Must Understand First

  1. Command, Composite, State, and Strategy
    • How do they model actions, condition trees, runs, and policies?
    • Book Reference: “Design Patterns” — corresponding chapters.
  2. Pure functions and immutable data
    • Why is replay unsafe if evaluation performs effects?
    • Book Reference: “Effective Java, 3rd Edition” — Items 15-17.
  3. Idempotent receiver and correlation
    • How do retries and causation remain visible?
    • Book Reference: “Enterprise Integration Patterns” — Idempotent Receiver, Correlation Identifier.

Questions to Guide Your Design

  1. What is the difference between a Rule, Plan, Run, Attempt, and Result?
  2. How do unknown and unavailable propagate through all/any/not trees?
  3. Which conflict policies are global, per rule, or per resource?
  4. How will schema versioning avoid executable class names in saved rules?

Thinking Exercise

Trace two rules triggered by the same event: one enables Focus mode and another disables it. Assign priority, resource key, cooldown, and concurrency policies. Decide whether one is skipped, both serialize, or the conflict blocks the plan.

The Interview Questions They Will Ask

  1. “Why separate planning from execution?”
  2. “What delivery guarantee can you honestly provide across process death?”
  3. “How do you prevent an automation cycle?”
  4. “What does idempotency mean for a UI action?”
  5. “How would you migrate a stored rule language?”

Hints in Layers

Hint 1: No Android imports in domain
If the engine imports Context or Intent, the boundary has leaked.

Hint 2: Make condition evidence data
Return result plus reason, observed value, and freshness.

Hint 3: Persist before side effects later
Design the Plan as an immutable value even before Project 4 stores it.

Hint 4: Property-test invariants
Reordering independent rules should not change their individual decisions.

Books That Will Help

Topic Book Chapter
Engine patterns “Design Patterns” Command, Composite, State, Strategy
Domain boundaries “Clean Architecture” Entities and boundaries
Messaging semantics “Enterprise Integration Patterns” Correlation, Idempotent Receiver

Common Pitfalls and Debugging

Problem 1: “Simulation sends a notification.”

  • Why: Planning and adapter invocation share the same path without an effect boundary.
  • Fix: Make simulation stop at immutable plan creation.
  • Quick test: Run every simulation with adapters that fail if invoked.

Problem 2: “Unknown battery behaves like false.”

  • Why: A nullable value was coerced into a Boolean.
  • Fix: Use an explicit result algebra and a rule-level unavailable policy.
  • Quick test: Evaluate all/any/not with one unavailable operand.

Definition of Done

  • Events, conditions, actions, plans, and results are versioned domain data.
  • Planning has no Android or external side effects.
  • Unknown, unavailable, conflict, cooldown, and cycle states are visible.
  • At-least-once and ambiguity semantics are documented.
  • JVM tests cover deterministic replay and bounded causation.

Project 4: Durable Automation Library

  • File: P04-durable-automation-library.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java; SQL for persistence exercises
  • Coolness Level: Level 2 — Practical but Forgettable
  • Business Potential: Level 2 — Micro-SaaS / Pro Tool
  • Difficulty: Level 2 — Intermediate
  • Knowledge Area: Persistence, migrations, transactions, import/export
  • Software or Tool: Room, SQLite, DataStore, Android Keystore
  • Main Book: “Patterns of Enterprise Application Architecture”

What you will build: A durable rule catalog, execution journal, migration suite, backup format, and process-death recovery boundary.

Why it teaches Android automation: Platform callbacks and system registrations are disposable; user intent and execution evidence must survive them.

Core challenges you will face:

  • Persisting rule graphs without serializing implementation classes -> maps to language versioning.
  • Claiming action attempts transactionally -> maps to duplicate prevention.
  • Migrating and exporting without leaking secrets -> maps to durable privacy.

Real World Outcome

The Library screen can create, duplicate, reorder, enable, disable, export, delete, and restore rules. Force-stopping and reopening preserves rules and run traces. A migration test installs a database snapshot from the previous schema, upgrades, and shows the same logical rule with an explicit migration report. Export preview lists included rule metadata and redacted fields; secrets and ephemeral tokens are absent. A deliberately corrupted import is rejected transactionally without changing existing data.

The Core Question You Are Answering

“Which facts must survive process death, and how do I evolve them without changing what the user’s automation means?”

Concepts You Must Understand First

  1. Repository and Unit of Work
    • Where do persistence transactions end?
    • Book Reference: “Patterns of Enterprise Application Architecture” — Repository, Unit of Work.
  2. Schema evolution
    • How does storage version differ from rule-language version?
    • Book Reference: “Refactoring Databases” — migration chapters.
  3. Sensitive state
    • What must never enter a backup or diagnostic export?
    • Book Reference: “Foundations of Information Security” — data protection.

Questions to Guide Your Design

  1. Which tables represent desired rule state versus historical execution?
  2. How is an action attempt claimed before effect and finalized afterward?
  3. What happens when a plugin action type is unknown after uninstall?
  4. How will large traces be retained, compacted, and deleted?

Thinking Exercise

Draw a crash timeline: plan stored, attempt claimed, webhook accepted, process killed before success commit. Mark which rows exist and how restart decides between retry, query by idempotency key, and ambiguous outcome.

The Interview Questions They Will Ask

  1. “Why use transactions around an execution claim?”
  2. “How do Room migrations differ from JSON import migrations?”
  3. “What is forward compatibility for an unknown rule node?”
  4. “How do you keep secrets out of backups?”
  5. “How would you recover from a failed migration?”

Hints in Layers

Hint 1: Separate desired and observed state
Rules are not run history.

Hint 2: Store type IDs and versioned data
Do not persist Kotlin class names.

Hint 3: Import into staging
Validate and migrate the complete package before one transaction replaces or merges.

Hint 4: Test real snapshots
Migration tests should open actual previous-version databases.

Books That Will Help

Topic Book Chapter
Persistence patterns “Patterns of Enterprise Application Architecture” Repository, Unit of Work, Data Mapper
Architecture “Clean Architecture” Boundaries
Migration discipline “Refactoring, Second Edition” Data refactorings

Common Pitfalls and Debugging

Problem 1: “A renamed Kotlin class breaks saved rules.”

  • Why: Storage encoded implementation identity.
  • Fix: Use stable domain type IDs and explicit migrators.
  • Quick test: Rename the implementation while keeping the type contract unchanged.

Problem 2: “Import partially overwrites rules before failure.”

  • Why: Validation and mutation were interleaved.
  • Fix: Parse, validate, migrate, preview, then commit transactionally.
  • Quick test: Inject one invalid node into a multi-rule import and verify zero changes.

Definition of Done

  • Rules, plans, attempts, results, and capability history have explicit schemas.
  • Real database snapshots pass migration tests.
  • Process death at each attempt boundary has a defined recovery state.
  • Import/export is transactional, versioned, previewed, and redacted.
  • Retention and user deletion apply to run history and support data.

Project 5: Timekeeper Constraint-Aware Scheduler

  • File: P05-timekeeper-scheduler.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java; SQL for schedule registry queries
  • Coolness Level: Level 3 — Genuinely Clever
  • Business Potential: Level 2 — Micro-SaaS / Pro Tool
  • Difficulty: Level 3 — Advanced
  • Knowledge Area: Background work, alarms, time, reboot recovery, battery
  • Software or Tool: WorkManager, AlarmManager, BroadcastReceiver, ADB
  • Main Book: “Release It!, 2nd Edition”

What you will build: A scheduler that chooses honest Android execution mechanisms, reconciles them after reboot/change, and measures requested versus actual execution.

Why it teaches Android automation: Scheduling is where desktop-daemon assumptions collide with Doze, quotas, exact-alarm authority, process death, and user force-stop.

Core challenges you will face:

  • Choosing WorkManager, alarm, foreground, or in-process execution -> maps to lifecycle-aware scheduling.
  • Handling time zone and DST recurrence -> maps to explicit time semantics.
  • Reconstructing registrations from durable intent -> maps to reconciliation.

Real World Outcome

The user schedules one routine for a local time window and another for “when network and charging constraints are satisfied.” A Diagnostics screen shows mechanism, requested time, next registration, actual start, delay, constraints, retry count, and restriction state. Enabling Doze delays best-effort work and the trace explains it. Rebooting the emulator rebuilds schedules exactly once. Changing timezone recomputes wall-clock occurrences. Revoking exact-alarm access disables exact precision while offering a visible best-effort alternative.

The Core Question You Are Answering

“What timing promise can Android honestly keep for this routine, and how will the app prove what actually happened?”

Concepts You Must Understand First

  1. Persistent work and constraints
    • What does WorkManager guarantee and not guarantee?
    • Book Reference: “Release It!, 2nd Edition” — stability and recovery.
  2. Wall versus monotonic time
    • Which clock represents duration and which represents user intent?
    • Book Reference: “Computer Systems: A Programmer’s Perspective” — time measurement sections.
  3. Idempotent reconciliation
    • Why can boot, app start, and permission change all call the same routine?
    • Book Reference: “Enterprise Integration Patterns” — Idempotent Receiver.

Questions to Guide Your Design

  1. What precision choices will the user see?
  2. How will unique work and stable PendingIntent identity avoid duplicates?
  3. What happens at a nonexistent or repeated DST local time?
  4. How does force-stop differ from ordinary process death?

Thinking Exercise

Create a table for: upload logs when unmetered, morning reminder at 07:30, 30-second visible export, and every-15-minute sensor poll. Select an API, reject invalid requirements, and state the user-visible timing contract.

The Interview Questions They Will Ask

  1. “When should you use WorkManager instead of AlarmManager?”
  2. “What restrictions apply to exact alarms on Android 12+?”
  3. “Why doesn’t a foreground service guarantee immortality?”
  4. “How do you restore schedules after reboot?”
  5. “How do you test Doze and App Standby?”

Hints in Layers

Hint 1: Write a decision table
Classify urgency, durability, precision, visibility, and constraints.

Hint 2: Persist desired schedule first
Platform registration is a projection of database state.

Hint 3: Schedule one local recurrence
Compute the next occurrence after each delivery and relevant time change.

Hint 4: Measure delay
Success is not “API accepted”; capture actual start and reason evidence.

Books That Will Help

Topic Book Chapter
Reliability “Release It!, 2nd Edition” Stability patterns
Idempotency “Enterprise Integration Patterns” Idempotent Receiver
Time reasoning “Computer Systems: A Programmer’s Perspective” System-level I/O and time sections

Common Pitfalls and Debugging

Problem 1: “Reboot creates duplicate work.”

  • Why: Boot code blindly enqueued rather than reconciling stable IDs.
  • Fix: Compare desired schedule registry with unique platform work.
  • Quick test: Trigger reconciliation three times and inspect one future registration.

Problem 2: “07:30 runs twice after DST overlap.”

  • Why: Ambiguous local time had no declared policy.
  • Fix: Store a recurrence policy and offset choice.
  • Quick test: Set emulator timezone/date to an overlap and inspect one chosen occurrence.

Definition of Done

  • A decision matrix selects the correct execution mechanism.
  • Work and alarms reference current durable rule IDs.
  • Boot, timezone change, app start, and access change reconcile idempotently.
  • Doze, process death, retry, and exact-access revocation are tested.
  • Requested versus actual timing is visible to the user.

Project 6: Privacy-First Notification Router

  • File: P06-notification-router.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java
  • Coolness Level: Level 4 — Hardcore Tech Flex
  • Business Potential: Level 2 — Micro-SaaS / Pro Tool
  • Difficulty: Level 3 — Advanced
  • Knowledge Area: Notification access, event filtering, privacy, action delegation
  • Software or Tool: NotificationListenerService, WorkManager, Compose
  • Main Book: “Foundations of Information Security”

What you will build: A notification adapter that emits redacted events for selected packages and executes safe, user-configured digest or notification actions.

Why it teaches Android automation: Notifications are a powerful cross-app signal, but their content, actions, connection lifecycle, and privacy requirements demand disciplined handling.

Core challenges you will face:

  • Waiting for service connection rather than assuming grant equals health -> maps to components.
  • Matching without retaining unnecessary message bodies -> maps to minimization.
  • Handling ephemeral notification actions safely -> maps to delegated authority.

Real World Outcome

After a prominent explanation and system enablement, the user selects only the included Test Notifier app. Posting test alerts shows sanitized events with package, channel, category, importance, stable notification key, predicate results, and redacted text metadata. A rule builds a local digest or posts a reminder. Unselected apps never appear. Revoking notification access immediately marks the source unhealthy and disables dependent rules without deleting them. A vanished action PendingIntent yields Needs user action or Permanent failure instead of crashing.

The Core Question You Are Answering

“How can a notification become a useful trigger without turning the automation app into a permanent archive of private conversations?”

Concepts You Must Understand First

  1. Notification listener lifecycle
    • Why does enabled access not guarantee connected service state?
    • Book Reference: “Operating Systems: Three Easy Pieces” — process lifecycle.
  2. Data minimization and redaction
    • Which predicate inputs can be discarded immediately?
    • Book Reference: “Foundations of Information Security” — privacy and data protection.
  3. Delegated actions
    • Why is a PendingIntent an ephemeral authority token?
    • Book Reference: “Security in Computing” — access control.

Questions to Guide Your Design

  1. How does the user select packages and fields before observation begins?
  2. Which notification updates replace prior events and which are new?
  3. What happens if a notification disappears before its action runs?
  4. How will work-profile limitations and disconnected states appear?

Thinking Exercise

Design predicates for “urgent build failure” using package, channel, category, and a one-way keyword match. Decide which raw values are processed in memory, which evidence is stored, and what appears in an exported trace.

The Interview Questions They Will Ask

  1. “How is NotificationListenerService enabled and connected?”
  2. “What sensitive data can a notification contain?”
  3. “How do notification keys and updates affect deduplication?”
  4. “What risks come with invoking notification actions?”
  5. “How would you prove unselected packages are not retained?”

Hints in Layers

Hint 1: Default deny packages
No source enters the engine until explicitly selected.

Hint 2: Compile predicates
Process text in memory and store only matched evidence when possible.

Hint 3: Treat actions as expiring
Resolve and invoke close to execution; return a typed stale-token result.

Hint 4: Build a test notifier
Control notification updates, removal, actions, and sensitive samples.

Books That Will Help

Topic Book Chapter
Privacy design “Foundations of Information Security” Privacy and data protection
Messaging identity “Enterprise Integration Patterns” Message Identifier
Failure handling “Release It!, 2nd Edition” Stability patterns

Common Pitfalls and Debugging

Problem 1: “Access is enabled but no events arrive.”

  • Why: The listener is not connected or is unavailable in the current profile/device mode.
  • Fix: Observe connection callbacks and display grant separately from health.
  • Quick test: Force-stop/reconnect and watch the capability transition.

Problem 2: “Support logs contain message text.”

  • Why: Whole notification objects were serialized.
  • Fix: Map into a schema with explicit redaction at ingestion.
  • Quick test: Search exported diagnostics for seeded secret marker text and require zero matches.

Definition of Done

  • Package observation is opt-in and default-deny.
  • Grant, connected, disconnected, and revoked states are distinct.
  • Sensitive text is minimized before persistence.
  • Post, update, removal, stale action, and revocation paths are tested.
  • A dependent rule degrades visibly without losing its configuration.

Project 7: Command Surface Deck

  • File: P07-command-surface-deck.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java
  • Coolness Level: Level 3 — Genuinely Clever
  • Business Potential: Level 2 — Micro-SaaS / Pro Tool
  • Difficulty: Level 2 — Intermediate
  • Knowledge Area: User entry surfaces, PendingIntent, lock state, process recreation
  • Software or Tool: TileService, App Shortcuts, App Widgets, notifications
  • Main Book: “Design It!”

What you will build: One routine command bus exposed through a Quick Settings tile, dynamic/pinned shortcut, home-screen widget, and notification action.

Why it teaches Android automation: User initiation is the most reliable and policy-friendly trigger, but each Android surface has independent lifecycle and identity rules.

Core challenges you will face:

  • Keeping surface state truthful after process death -> maps to disposable services.
  • Using stable routine IDs and immutable delegation -> maps to command contracts.
  • Handling locked-device confirmation without background UI abuse -> maps to secure initiation.

Real World Outcome

The user publishes a “Focus Routine” to four surfaces. The tile shows Active, Inactive, or Unavailable based on current rule state; a pinned shortcut retains a stable identity across updates; the widget shows last result; and the notification offers Run and Stop. Invoking any surface creates the same CommandEnvelope and one correlated trace. If the routine is disabled or requires unlock, the surface displays an explanation and a user-driven resolution instead of silently changing state or launching an unexpected activity.

The Core Question You Are Answering

“How can many Android entry surfaces invoke one current routine without each becoming a separate, stale automation implementation?”

Concepts You Must Understand First

  1. Command pattern
    • Why should surfaces submit IDs instead of effects?
    • Book Reference: “Design Patterns” — Command.
  2. PendingIntent authority
    • What do mutability and identity change?
    • Book Reference: “Security in Computing” — capability concepts.
  3. System-controlled component lifecycle
    • Why can TileService be recreated at any time?
    • Book Reference: “Operating Systems: Three Easy Pieces” — process chapters.

Questions to Guide Your Design

  1. Which surface states can be rendered without starting the full app?
  2. How are deleted and renamed routines represented?
  3. What action is permitted from a locked screen?
  4. How will duplicate taps become one or multiple commands?

Thinking Exercise

Trace a double-tap on the tile while the process is absent and the routine is already running. Decide command identity, serialization, UI feedback, and whether the second tap cancels, queues, or is ignored.

The Interview Questions They Will Ask

  1. “What is the lifecycle of a Quick Settings tile?”
  2. “How do immutable and mutable PendingIntents differ?”
  3. “Why prefer a notification over a background activity launch?”
  4. “How do shortcut IDs affect backup and restore?”
  5. “How would you keep a widget synchronized with durable state?”

Hints in Layers

Hint 1: One dispatcher
All surfaces call one domain command entry point.

Hint 2: Reload current routine
Never embed the whole rule in an Intent.

Hint 3: Make unavailable a real surface state
Do not turn a missing capability into a no-op.

Hint 4: Test process absence
Invoke every surface after killing the process.

Books That Will Help

Topic Book Chapter
Product architecture “Design It!” Design and boundaries chapters
Command abstraction “Design Patterns” Command
API safety “Effective Java, 3rd Edition” Items 49-52

Common Pitfalls and Debugging

Problem 1: “Tile state is stale until opening the app.”

  • Why: It depended on in-memory state.
  • Fix: Read a small durable projection and request updates when domain state changes.
  • Quick test: Change state, kill process, then open Quick Settings.

Problem 2: “A shortcut runs an old version of the rule.”

  • Why: Serialized rule data was embedded in the shortcut Intent.
  • Fix: Store only stable routine and command IDs.
  • Quick test: Edit the rule, invoke an existing pinned shortcut, and verify current behavior.

Definition of Done

  • Four surfaces dispatch the same versioned command envelope.
  • Stable IDs survive process death and routine edits.
  • Locked, disabled, deleted, and unavailable states are visible.
  • Rapid repeat invocation has a documented concurrency policy.
  • No surface depends on long-lived service instances.

Project 8: Accessibility Inspector

  • File: P08-accessibility-inspector.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java
  • Coolness Level: Level 5 — Pure Magic
  • Business Potential: Level 2 — Micro-SaaS / Pro Tool
  • Difficulty: Level 3 — Advanced
  • Knowledge Area: Accessibility events, semantic trees, selectors, overlays
  • Software or Tool: AccessibilityService, AccessibilityNodeInfo, Compose
  • Main Book: “Designing with the Mind in Mind”

What you will build: A consentful, package-allowlisted live inspector that visualizes semantic UI nodes and produces ranked selector candidates.

Why it teaches Android automation: You cannot build reliable AutoInput-style actions until you understand what the accessibility tree contains, omits, and invalidates.

Core challenges you will face:

  • Reacquiring transient node state -> maps to accessibility lifecycle.
  • Ranking semantic selectors without storing sensitive content -> maps to safe screen understanding.
  • Controlling event storms and overlay interaction -> maps to backpressure and consent.

Real World Outcome

The project includes a Sandbox Target app with forms, lists, localized text, duplicate labels, and a custom-drawn control. After scoped onboarding, the inspector shows the active package, window, event stream, and tree. Selecting a node highlights it through a visible controller and lists candidate selectors: resource ID, role/class, content description, bounded text constraint, structural relation, and coordinate fallback. Each candidate has a confidence explanation. Password nodes are marked prohibited and their values never appear. Leaving the allowlisted package freezes inspection and shows “Outside selected target.”

The Core Question You Are Answering

“What stable semantic evidence does another app expose, and how can I identify one intended control without reading or retaining more than necessary?”

Concepts You Must Understand First

  1. Accessibility node model
    • Why is it not equivalent to pixels or the View object?
    • Book Reference: “Designing with the Mind in Mind” — perception and interaction.
  2. Selector robustness
    • Which properties survive localization and responsive layout?
    • Book Reference: “Refactoring, Second Edition” — stable interfaces.
  3. Sensitive input boundaries
    • How are password and secure content excluded?
    • Book Reference: “Foundations of Information Security” — data minimization.

Questions to Guide Your Design

  1. How will you bound tree traversal and event retention?
  2. What makes a selector unique now versus robust later?
  3. How will WebView, custom canvas, and virtual nodes appear?
  4. Which overlay type and visible controls match the legitimate product purpose?

Thinking Exercise

Given three “Submit” buttons in different windows and one localized label, rank six candidate selectors. Then change orientation and locale on paper and predict which selectors still identify exactly one target.

The Interview Questions They Will Ask

  1. “How does an accessibility service retrieve window content?”
  2. “Why do AccessibilityNodeInfo objects become stale?”
  3. “What selector strategy is most robust?”
  4. “How would you prevent accidental password capture?”
  5. “What Play policy applies to non-accessibility automation tools?”

Hints in Layers

Hint 1: Build the sandbox first
Own every target behavior and failure case.

Hint 2: Filter at the service boundary
Reject non-allowlisted packages before tree traversal.

Hint 3: Store descriptors, not nodes
Persist selector candidates and reacquire later.

Hint 4: Score with evidence
Show why resource ID beats text and why coordinates are fragile.

Books That Will Help

Topic Book Chapter
Human interaction “Designing with the Mind in Mind” Perception and attention
Secure observation “Foundations of Information Security” Privacy
Robust models “Effective Java, 3rd Edition” Items 15-17

Common Pitfalls and Debugging

Problem 1: “A highlighted node no longer exists.”

  • Why: The UI redrew and the remote node became stale.
  • Fix: Persist the selector and reacquire against the current root.
  • Quick test: Refresh the target list between inspect and highlight.

Problem 2: “Typing in a password appears in logs.”

  • Why: Raw text-change events were serialized before classification.
  • Fix: classify and discard prohibited content at ingress.
  • Quick test: Seed a unique secret marker and require zero occurrences in database/export.

Definition of Done

  • Only explicitly allowlisted packages are inspected.
  • Transient nodes never cross the adapter boundary.
  • Selector candidates include confidence and fragility evidence.
  • Password, secure, ambiguous, stale, and custom-view cases are handled.
  • Event volume, traversal bounds, and stop/revocation behavior are tested.

Project 9: Consentful UI Macro Runner

  • File: P09-ui-macro-runner.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java
  • Coolness Level: Level 5 — Pure Magic
  • Business Potential: Level 3 — Service & Support
  • Difficulty: Level 4 — Expert
  • Knowledge Area: State machines, UI automation, gestures, retries, safety policy
  • Software or Tool: AccessibilityService, foreground-visible controls, Room
  • Main Book: “Release It!, 2nd Edition”

What you will build: A deterministic macro recorder/editor/runner that operates only against the sandbox target with semantic steps, postconditions, and emergency stop.

Why it teaches Android automation: It confronts the hard part of AutoInput-like tooling: turning unstable external UI into a bounded, explainable state machine.

Core challenges you will face:

  • Replacing fixed sleeps with state-based waits -> maps to reliable execution.
  • Stopping on ambiguity or prohibited surfaces -> maps to safety policy.
  • Classifying retry versus ambiguous effect -> maps to durable automation semantics.

Real World Outcome

The user records a macro that opens the Sandbox Target, selects a demo form, enters non-sensitive sample data, submits, and waits for a success label. The editor shows selector, precondition, action, postcondition, timeout, and retry policy for every step. During execution, a persistent controller shows current step, elapsed time, Pause, and Emergency Stop. The runner stops if the package changes, a selector finds zero or multiple nodes, a password field appears, the service is revoked, or the success postcondition times out. A coordinate-only step is visibly labeled fragile and disabled by default.

The Core Question You Are Answering

“How can a macro act on a changing external UI while proving that each intended step—not merely a timed tap—actually completed?”

Concepts You Must Understand First

  1. State machines and postconditions
    • What observable fact advances each step?
    • Book Reference: “Design Patterns” — State.
  2. Timeout, retry, and ambiguity
    • Which actions can be safely repeated?
    • Book Reference: “Release It!, 2nd Edition” — timeouts and stability.
  3. Accessibility action hierarchy
    • When do semantic action and gesture fallback apply?
    • Book Reference: Official AccessibilityService guide.

Questions to Guide Your Design

  1. Which prohibited contexts terminate before any action?
  2. What evidence distinguishes not-found from stale, ambiguous, and unsupported?
  3. How does the user regain control at every point?
  4. What process-death point makes a tap outcome ambiguous?

Thinking Exercise

Trace a macro where Submit is tapped, the target app updates, and the automation process dies before recording success. Decide whether restart may tap again, query a postcondition, mark ambiguous, or require user review.

The Interview Questions They Will Ask

  1. “Why are fixed delays brittle in UI automation?”
  2. “How do you handle stale accessibility nodes?”
  3. “What makes an action safe to retry?”
  4. “How do you prevent automation from escaping its target app?”
  5. “What safeguards make accessibility automation policy-aware?”

Hints in Layers

Hint 1: Build an explicit StepState
Waiting, resolving, acting, verifying, succeeded, failed, stopped, ambiguous.

Hint 2: Reacquire before action and verification
Never reuse the recorded node handle.

Hint 3: Separate semantic and gesture adapters
Gesture fallback needs stricter warnings and postconditions.

Hint 4: Kill the process deliberately
Test before action, after action, and before result commit.

Books That Will Help

Topic Book Chapter
State machines “Design Patterns” State
Reliability “Release It!, 2nd Edition” Timeouts and stability
Testing “Test Driven Development: By Example” Parts I-II

Common Pitfalls and Debugging

Problem 1: “The macro sometimes types into the wrong field.”

  • Why: Selector was ambiguous or the package/window changed.
  • Fix: require exactly one allowlisted match and verify focus/postcondition.
  • Quick test: Add a duplicate field and require safe refusal.

Problem 2: “Increasing sleep fixes one phone but breaks another.”

  • Why: Timing substitutes for state.
  • Fix: wait for events and bounded semantic postconditions.
  • Quick test: Add random target delays and require stable success/failure classification.

Definition of Done

  • Every step has precondition, selector, action, postcondition, timeout, and retry class.
  • Package escape, ambiguity, prohibited fields, revocation, and stop terminate immediately.
  • Visible execution controls remain accessible throughout the run.
  • No credential, permission, purchase, security, or financial flow is supported.
  • Process-death outcomes are idempotent or explicitly ambiguous.

Project 10: Plugin SDK and IPC Host

  • File: P10-plugin-sdk-ipc-host.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java
  • Coolness Level: Level 4 — Hardcore Tech Flex
  • Business Potential: Level 4 — Open Core Infrastructure
  • Difficulty: Level 4 — Expert
  • Knowledge Area: Binder IPC, protocol design, package identity, ecosystem architecture
  • Software or Tool: Bound Service, AIDL or Messenger, PackageManager
  • Main Book: “Enterprise Integration Patterns”

What you will build: A versioned SDK and separately installed demo plugin that contributes one trigger and one action to the host.

Why it teaches Android automation: A Tasker-like ecosystem becomes valuable when other apps can extend it without receiving unrestricted control.

Core challenges you will face:

  • Negotiating versions across independently updated packages -> maps to protocol compatibility.
  • Validating package, signer, caller, and capability scope -> maps to IPC security.
  • Containing plugin timeout, crash, and malformed results -> maps to failure isolation.

Real World Outcome

Installing the Demo Plugin makes it appear in a catalog discovered through a targeted intent query. The card shows package, signer fingerprint, protocol range, declared trigger/action, required data, and trust status. After explicit enrollment, the user configures and tests a “Transform text length” action. The host sends a correlated request and renders a typed result. Separate test controls install or simulate a wrong signer, unsupported version, malformed payload, oversized payload, timeout, crash, and replay; each is rejected or contained with a precise diagnostic.

The Core Question You Are Answering

“How can third-party packages add automation power without turning the host into a confused deputy or brittle shared implementation?”

Concepts You Must Understand First

  1. Binder and remote failure
    • Why is a remote call not an ordinary method call?
    • Book Reference: “Enterprise Integration Patterns” — Request-Reply and Correlation.
  2. Package identity and signatures
    • What does a signer prove and when must it be rechecked?
    • Book Reference: “Security in Computing” — authentication and authorization.
  3. Protocol evolution
    • How do capabilities and versions negotiate?
    • Book Reference: “Building Evolutionary Architectures” — fitness and evolution.

Questions to Guide Your Design

  1. What is the smallest exported discovery surface?
  2. Which requests are synchronous acknowledgements versus asynchronous results?
  3. How are cancellation, deadline, and binder death represented?
  4. How does plugin uninstall preserve an understandable disabled rule?

Thinking Exercise

Act as a hostile plugin. Try wrong signer, claimed trusted package ID, replay, recursive callback, huge Bundle, missing field, never-returning request, and malformed resolution PendingIntent. Specify the host’s control for each.

The Interview Questions They Will Ask

  1. “When would you choose AIDL, Messenger, Intent, or ContentProvider?”
  2. “How do package visibility rules affect discovery?”
  3. “How do signature permissions differ from open plugin trust?”
  4. “What is Binder death and how do you recover?”
  5. “How do you version a cross-app contract?”

Hints in Layers

Hint 1: Design the wire schema first
Treat the plugin as if written by another team.

Hint 2: Explicit binding only
Resolve discovery, then bind to the enrolled package/component.

Hint 3: Capabilities, not arbitrary commands
Plugins expose declared action IDs and JSON-like schemas.

Hint 4: Build a hostile fixture app
Happy-path tests cannot prove an IPC boundary.

Books That Will Help

Topic Book Chapter
Messaging protocols “Enterprise Integration Patterns” Request-Reply, Correlation Identifier
Evolution “Building Evolutionary Architectures” Fitness functions
Security “Security in Computing” Authentication and access control

Common Pitfalls and Debugging

Problem 1: “An unrelated app can invoke the host service.”

  • Why: Exported component lacks permission/caller/action validation.
  • Fix: minimize exports and verify caller, signer/enrollment, version, and action scope.
  • Quick test: Invoke from the hostile fixture and require rejection.

Problem 2: “A large result crashes Binder.”

  • Why: Bulk data was sent in a transaction.
  • Fix: bound messages and use scoped URI/file transfer for larger payloads.
  • Quick test: Send boundary-sized payloads and verify typed TooLarge failure.

Definition of Done

  • Discovery is targeted and does not require broad package inventory.
  • Enrollment stores and rechecks package signer identity.
  • Requests and results are versioned, bounded, correlated, timed, and cancellable.
  • Wrong signer, version skew, replay, timeout, crash, malformed input, and oversized payload are tested.
  • Unknown/uninstalled plugin nodes disable safely without deleting user configuration.

Project 11: ScreenLens Capture and OCR Lab

  • File: P11-screenlens-capture-lab.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java; C++ only for an optional image-processing extension
  • Coolness Level: Level 4 — Hardcore Tech Flex
  • Business Potential: Level 2 — Micro-SaaS / Pro Tool
  • Difficulty: Level 3 — Advanced
  • Knowledge Area: Screen capture, lifecycle, local vision, privacy
  • Software or Tool: MediaProjection, VirtualDisplay, foreground service, ML Kit or local OCR
  • Main Book: “Computer Vision: Algorithms and Applications”

What you will build: A user-consented, session-scoped screen inspector that captures the sandbox app, extracts local OCR regions, and compares pixels with accessibility semantics.

Why it teaches Android automation: Pixel understanding can complement missing semantic nodes, but capture tokens, visible system state, secure content, rotation, and privacy make it a distinct capability—not a hidden fallback.

Core challenges you will face:

  • Managing one capture session across consent, projection, display, and stop -> maps to lifecycle.
  • Processing frames without building a screenshot archive -> maps to minimization.
  • Reconciling visual candidates with semantic selectors -> maps to safe screen understanding.

Real World Outcome

Tapping Start ScreenLens opens the system capture chooser. The user chooses the Sandbox Target app or display, after which an ongoing capture indicator and app notification are visible. The app shows a low-rate preview, OCR boxes, recognized sample text, and links when a box overlaps an accessibility node. Rotating the device rebuilds size-dependent resources. Locking the device, stopping from the system chip, revoking service state, or closing the notification ends the session and releases display/image resources. Frames are processed in memory; the default history stores only redacted region geometry and confidence.

The Core Question You Are Answering

“What can pixels reveal when semantics are missing, and how do I use that evidence without pretending screen capture is silent, permanent, or universally permitted?”

Concepts You Must Understand First

  1. MediaProjection session lifecycle
    • Which user action creates authority and what stops it?
    • Book Reference: “Operating Systems: Three Easy Pieces” — resource lifecycle.
  2. Image pipelines
    • How do resolution, crop, frame rate, and backpressure affect memory?
    • Book Reference: “Computer Vision: Algorithms and Applications” — image formation and features.
  3. Privacy by design
    • Which pixels should never persist?
    • Book Reference: “Foundations of Information Security” — privacy.

Questions to Guide Your Design

  1. What is the minimum capture frequency for an inspector?
  2. How will rotation and selected-app resizing update the virtual display?
  3. How does the projection stop callback clean up every resource?
  4. When must visual evidence be rejected as ambiguous or secure?

Thinking Exercise

Draw the ownership graph from consent result to MediaProjection, foreground service, VirtualDisplay, ImageReader, frame, OCR job, and UI. For every stop source, mark the reverse cleanup order and prove no object keeps capturing.

The Interview Questions They Will Ask

  1. “Why is MediaProjection consent session-scoped?”
  2. “What changes for modern target SDKs and foreground service types?”
  3. “How do you handle rotation and virtual-display resizing?”
  4. “How do you prevent frame backpressure and memory leaks?”
  5. “Why should accessibility semantics be preferred to OCR when available?”

Hints in Layers

Hint 1: Model SessionState
Idle, requesting, active, stopping, stopped, error.

Hint 2: Keep latest frame only
An inspector rarely needs an unbounded stream.

Hint 3: Centralize cleanup
All stop paths call one idempotent release routine.

Hint 4: Compare, do not auto-tap
Visual candidates become user-reviewed selector evidence.

Books That Will Help

Topic Book Chapter
Visual processing “Computer Vision: Algorithms and Applications” Image formation and features
Resource lifetime “Operating Systems: Three Easy Pieces” Persistence and concurrency
Privacy “Foundations of Information Security” Data protection

Common Pitfalls and Debugging

Problem 1: “Capture freezes after rotation.”

  • Why: Virtual display and buffers retained old dimensions.
  • Fix: observe size change and recreate/resize the dependent pipeline safely.
  • Quick test: Rotate repeatedly while monitoring frame timestamps and memory.

Problem 2: “Frames continue after the user stops projection.”

  • Why: stop callback did not close every owned resource.
  • Fix: make cleanup centralized and idempotent.
  • Quick test: Stop through system UI and require zero new frames plus released notification.

Definition of Done

  • Every session begins with current user consent.
  • Ongoing capture is visibly indicated and immediately stoppable.
  • Rotation, lock, system stop, app stop, and process death are tested.
  • Frames are bounded, processed locally, and not archived by default.
  • Secure/ambiguous content never becomes an automatic action target.

Project 12: Secure Webhook and Termux Bridge

  • File: P12-secure-webhook-termux-bridge.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java; shell/Python only for the companion Termux endpoint
  • Coolness Level: Level 4 — Hardcore Tech Flex
  • Business Potential: Level 3 — Service & Support
  • Difficulty: Level 3 — Advanced
  • Knowledge Area: HTTPS, authentication, durable delivery, device integration
  • Software or Tool: WorkManager, Android Keystore, HMAC, explicit Intents
  • Main Book: “Enterprise Integration Patterns”

What you will build: Signed outbound webhooks and a narrow inbound proposal channel mapped only to preconfigured routines, plus an explicit Termux companion adapter.

Why it teaches Android automation: Remote and shell ecosystems greatly expand useful actions, but a safe bridge must not become arbitrary remote code execution.

Core challenges you will face:

  • Authenticating, authorizing, and replay-protecting commands -> maps to external trust.
  • Delivering outbound events durably without duplicates -> maps to WorkManager and idempotency.
  • Integrating Termux through a declared contract rather than shell text -> maps to least authority.

Real World Outcome

A context event creates a signed webhook delivery showing destination ID, key ID, body hash, idempotency key, attempt count, HTTP class, and next retry. A controlled receiver verifies the signature and deduplicates repeats. The inbound test relay sends a signed proposal naming an allowlisted routine and bounded parameters; the app either executes a preapproved low-risk routine or posts a local confirmation. The Termux bridge invokes a named companion operation such as “generate device report,” receives a typed result, and never accepts arbitrary command strings. Network loss queues work and later recovery produces one accepted effect.

The Core Question You Are Answering

“How can the phone participate in a larger automation system without turning a stolen key, plugin, or server into unrestricted device control?”

Concepts You Must Understand First

  1. Authentication versus authorization
    • Why does a valid signature not authorize every routine?
    • Book Reference: “Security in Computing” — access control.
  2. Idempotent delivery
    • How does the receiver suppress duplicate effects?
    • Book Reference: “Enterprise Integration Patterns” — Idempotent Receiver.
  3. Secret lifecycle
    • Where do key handles and rotation metadata live?
    • Book Reference: “Foundations of Information Security” — cryptographic key management.

Questions to Guide Your Design

  1. Which exact fields are signed and canonicalized?
  2. How are timestamp skew, nonce reuse, and replay windows handled?
  3. Which inbound routines require local confirmation?
  4. How does Termux advertise capabilities without granting a shell interpreter?

Thinking Exercise

Assume the relay server is compromised. List every action it can propose, every parameter bound, what still requires local user action, and which local data never leaves the phone. Reduce authority until the compromise has a tolerable blast radius.

The Interview Questions They Will Ask

  1. “Why use both HMAC verification and an idempotency key?”
  2. “How do you rotate webhook keys?”
  3. “What retry policy applies to 400, 429, 500, timeout, and TLS failure?”
  4. “Why is an embedded HTTP server on the phone risky?”
  5. “How do you prevent a shell bridge from becoming RCE?”

Hints in Layers

Hint 1: Name destinations and routines
Rules reference enrolled IDs, not arbitrary URLs or commands.

Hint 2: Canonicalize before signing
Define bytes, timestamp, nonce, key ID, and body hash exactly.

Hint 3: Separate proposal from execution
High-risk inbound actions wait for local confirmation.

Hint 4: Test acceptance ambiguity
Kill after receiver acceptance and before local success commit.

Books That Will Help

Topic Book Chapter
Reliable messaging “Enterprise Integration Patterns” Idempotent Receiver, Retry
Security “Security in Computing” Authentication and authorization
Network failures “Release It!, 2nd Edition” Timeouts and stability

Common Pitfalls and Debugging

Problem 1: “Retries create duplicate server actions.”

  • Why: Receiver treats delivery attempts as new commands.
  • Fix: sign and persist a stable idempotency key with bounded retention.
  • Quick test: Replay the exact accepted request and verify one effect.

Problem 2: “A signed request runs any shell command.”

  • Why: Authentication was mistaken for unrestricted authorization.
  • Fix: map allowed operation IDs to fixed companion behavior and validate parameters.
  • Quick test: Send an unknown operation and shell metacharacters; require schema rejection.

Definition of Done

  • Outbound deliveries are signed, durable, retry-aware, and idempotent.
  • Inbound requests enforce freshness, nonce/replay, routine allowlist, and parameter schemas.
  • High-risk actions require local confirmation.
  • Keystore-backed key lifecycle and rotation are documented.
  • Termux integration exposes named capabilities, never arbitrary remote shell text.

Project 13: Managed-Device Policy Lab

  • File: P13-managed-device-policy-lab.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java
  • Coolness Level: Level 4 — Hardcore Tech Flex
  • Business Potential: Level 3 — Service & Support
  • Difficulty: Level 4 — Expert
  • Knowledge Area: Enterprise mobility, policy, provisioning, kiosk
  • Software or Tool: DevicePolicyManager, DeviceAdminReceiver, Android Emulator
  • Main Book: “Software Architecture in Practice, 4th Edition”

What you will build: A separate device policy controller track that applies and reverses a small allowlisted policy set on a disposable managed emulator.

Why it teaches Android automation: Device owner and profile owner unlock legitimate enterprise capabilities that consumer permission flows cannot provide, clarifying the line between product modes.

Core challenges you will face:

  • Provisioning administrative authority outside normal app UX -> maps to capability boundaries.
  • Adapting behavior to device owner versus profile owner -> maps to policy modes.
  • Making policy changes reversible and auditable -> maps to administrative safety.

Real World Outcome

On a factory-reset emulator, the learner provisions the lab DPC using documented development tooling. The app’s Managed Mode dashboard proves owner type and lists supported policies. The user enables an allowlisted kiosk/lock-task configuration or toggles a safe device restriction, sees the system behavior change, and reverses it. Installing the same APK normally on another emulator shows “Not managed” and refuses policy actions. Every change records administrator intent, previous state, desired state, result, and rollback.

The Core Question You Are Answering

“Which automations are legitimate only because an organization provisioned this app as an administrator, and how do I keep that power separate from consumer features?”

Concepts You Must Understand First

  1. Device owner and profile owner
    • Which scope and provisioning flow does each represent?
    • Book Reference: Android Enterprise DPC documentation.
  2. Policy convergence
    • How does desired state differ from one-shot commands?
    • Book Reference: “Software Architecture in Practice” — quality attributes.
  3. Administrative audit and rollback
    • What evidence proves who changed what?
    • Book Reference: “Security in Computing” — administration and audit.

Questions to Guide Your Design

  1. Which policies are supported in each owner mode and API level?
  2. What happens if a partially applied policy sequence fails?
  3. How does deprovisioning restore expected device behavior?
  4. Which test devices may be wiped without risk?

Thinking Exercise

Create a matrix for normal app, legacy device admin, profile owner, device owner, and privileged/system app. Place ten proposed actions into the minimum legitimate mode and reject any that the project should not support.

The Interview Questions They Will Ask

  1. “How does a DPC become device owner?”
  2. “What differs between managed profile and fully managed device?”
  3. “Why can’t a normal app self-grant device-owner authority?”
  4. “How do lock-task and kiosk modes differ from screen pinning?”
  5. “How do you test and roll back device policies?”

Hints in Layers

Hint 1: Use disposable emulators
Provisioning and removal can require destructive setup.

Hint 2: Capability matrix first
Ask DevicePolicyManager what the current owner can do.

Hint 3: Model desired state
Read current policy, apply convergence, verify, then record.

Hint 4: Build rollback before breadth
One reversible policy teaches more than ten unsafe toggles.

Books That Will Help

Topic Book Chapter
Quality attributes “Software Architecture in Practice, 4th Edition” Availability, security, modifiability
Administration “Security in Computing” Access control and audit
Evolution “Building Evolutionary Architectures” Fitness functions

Common Pitfalls and Debugging

Problem 1: “Policy call throws SecurityException on a normal install.”

  • Why: The app is not the required owner/admin mode.
  • Fix: gate every policy through current administrative capability evidence.
  • Quick test: Install normally and require refusal before API call.

Problem 2: “Test device remains stuck in kiosk behavior.”

  • Why: Rollback and deprovisioning were not designed first.
  • Fix: implement verified reversal on a disposable emulator before extensions.
  • Quick test: Apply, reboot, reverse, and verify normal launcher access.

Definition of Done

  • Consumer and managed builds/modes are clearly separated.
  • Owner type and per-policy support are verified before action.
  • At least two safe policies apply, verify, survive/reconcile, and reverse.
  • Normal installs refuse administrative calls safely.
  • Provisioning, audit, rollback, and emulator reset procedures are documented.

Project 14: Automation Observatory and Fault Lab

  • File: P14-automation-observatory.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java; shell only for ADB test orchestration
  • Coolness Level: Level 3 — Genuinely Clever
  • Business Potential: Level 3 — Service & Support
  • Difficulty: Level 3 — Advanced
  • Knowledge Area: Observability, fault injection, privacy, compatibility testing
  • Software or Tool: Android test, WorkManager test APIs, Macrobenchmark, ADB
  • Main Book: “Release It!, 2nd Edition”

What you will build: A redacted event-to-effect trace explorer, replay engine, support-bundle preview, and fault-injection suite across all adapters.

Why it teaches Android automation: A platform with many asynchronous gates is only supportable when “did not run” can be decomposed into trigger, decision, block, attempt, and result.

Core challenges you will face:

  • Connecting evidence without persisting secrets -> maps to structured redaction.
  • Injecting failure around ambiguous side effects -> maps to recovery semantics.
  • Testing OS, target SDK, OEM, and authority combinations -> maps to compatibility.

Real World Outcome

The Observatory screen presents a waterfall for every run: source health, canonical event, matching rules, condition evidence, plan, capability checks, action attempts, retries, and final result. A replay button feeds the redacted event into a simulation, never effects. Fault controls inject process death, timeout, binder death, network loss, HTTP responses, queue overflow, service revocation, and clock shifts. A support-bundle wizard shows exact redacted fields before export. A compatibility dashboard records API, target, device, install source, managed mode, and scenario result.

The Core Question You Are Answering

“Can I reproduce and explain a failed automation without seeing the user’s private content or guessing about Android lifecycle?”

Concepts You Must Understand First

  1. Structured observability
    • How do correlation and causation connect one run?
    • Book Reference: “Release It!, 2nd Edition” — operations chapters.
  2. Fault injection
    • Which failure points expose unsafe retry assumptions?
    • Book Reference: “Test Driven Development: By Example” — test design.
  3. Data classification
    • What evidence remains after redaction?
    • Book Reference: “Foundations of Information Security” — privacy.

Questions to Guide Your Design

  1. Which trace fields are public, sensitive, secret, or prohibited?
  2. How does simulation prove no adapter ran?
  3. Which matrix combinations provide the most risk coverage?
  4. What retention keeps diagnostics useful without indefinite surveillance?

Thinking Exercise

For one webhook and one UI macro, inject process death before plan commit, after claim, during external action, and after effect before result commit. Define database state, replay safety, user message, and next recovery step.

The Interview Questions They Will Ask

  1. “What is the difference between logs, metrics, and traces?”
  2. “How do you diagnose a trigger that never arrived?”
  3. “What is an ambiguous side-effect outcome?”
  4. “How do you prevent PII leakage in diagnostics?”
  5. “What belongs in an Android compatibility matrix?”

Hints in Layers

Hint 1: Design the trace schema
Do not build observability from arbitrary log strings.

Hint 2: Redact before storage
Export-time cleanup is too late.

Hint 3: Make adapters faultable
Inject controlled responses at ports, then verify on-device system cases.

Hint 4: Preview bundles
The user sees included categories and seeded secret scans before sharing.

Books That Will Help

Topic Book Chapter
Operations “Release It!, 2nd Edition” Production diagnostics
Testing “Test Driven Development: By Example” Parts I-II
Security “Foundations of Information Security” Privacy and risk

Common Pitfalls and Debugging

Problem 1: “The trace says failed but not where.”

  • Why: One generic status replaced source, decision, gate, and adapter stages.
  • Fix: model transitions and typed causes at each boundary.
  • Quick test: Simulate source absence, condition false, capability revoked, and adapter timeout; require distinct traces.

Problem 2: “Replay sends the webhook again.”

  • Why: Replay reused execution rather than pure planning.
  • Fix: bind replay to a no-effects simulator.
  • Quick test: Fail the test if any adapter receives a replay call.

Definition of Done

  • Every run has correlated source, plan, gate, attempt, and outcome evidence.
  • Redaction occurs before persistence and seeded secrets never export.
  • Replay is deterministic and effect-free.
  • At least ten fault scenarios and a multi-API compatibility matrix run.
  • Support-bundle retention, preview, export, and deletion are user-controlled.

Project 15: FlowForge Automation Studio

  • File: P15-flowforge-automation-studio.md
  • Main Programming Language: Kotlin
  • Alternative Programming Languages: Java for individual adapters; Rust only for an experimental pure engine
  • Coolness Level: Level 5 — Pure Magic
  • Business Potential: Level 4 — Open Core Infrastructure
  • Difficulty: Level 4 — Expert
  • Knowledge Area: Platform architecture, UX, policy, reliability, ecosystem
  • Software or Tool: Complete Android/Jetpack stack from Projects 1-14
  • Main Book: “Fundamentals of Software Architecture”

What you will build: A polished Tasker-style automation studio integrating deterministic rules, safe adapters, plugins, schedules, diagnostics, and emergency controls.

Why it teaches Android automation: Integration forces capability, lifecycle, UX, safety, storage, compatibility, and ecosystem decisions to coexist as one product.

Core challenges you will face:

  • Keeping feature adapters independent behind one stable rule language -> maps to modular architecture.
  • Making powerful capability state understandable during authoring and execution -> maps to consent UX.
  • Shipping with policy, threat, test, performance, and recovery evidence -> maps to production readiness.

Real World Outcome

FlowForge opens to an Automation Library with status, trigger summary, required capabilities, last result, and next run. The visual editor creates typed trigger-condition-action graphs, previews data use, simulates decisions, and refuses unsupported combinations. The Permission Center explains every grant. The Run screen shows a live redacted trace and global Stop. The final demo includes a context rule, scheduled rule, selected-app notification trigger, sandbox UI macro, plugin action, signed webhook/Termux operation, ScreenLens inspection, and managed-emulator policy—each in its legitimate mode. Backup/restore, migration, revocation, reboot, plugin uninstall, network outage, UI drift, and process death all produce clear degraded states.

The Core Question You Are Answering

“Can one automation product be powerful across consumer, plugin, remote, accessibility, and enterprise modes without hiding authority differences or becoming impossible to debug?”

Concepts You Must Understand First

  1. Modular architecture and bounded contexts
    • Which modules own domain, adapters, policy, and UI?
    • Book Reference: “Fundamentals of Software Architecture” — modularity and trade-offs.
  2. Evolutionary architecture
    • Which fitness functions prevent capability and privacy regression?
    • Book Reference: “Building Evolutionary Architectures” — fitness functions.
  3. Operational readiness
    • Which evidence proves release safety?
    • Book Reference: “Release It!, 2nd Edition” — operations and stability.

Questions to Guide Your Design

  1. How does the editor represent unavailable actions without deleting them?
  2. What is the module and protocol boundary for every adapter?
  3. Which product flavor supports Play, enterprise provisioning, or developer bridges?
  4. Which global stop and revocation actions must take effect synchronously?

Thinking Exercise

Produce a release architecture decision record for AccessibilityService. Compare removing it, Play-distributed narrow deterministic use, enterprise-only use, and sideload-only use. Include product value, policy, data, testing, support, and failure trade-offs.

The Interview Questions They Will Ask

  1. “How would you architect a Tasker-like application?”
  2. “How do you evolve a plugin and rule ecosystem?”
  3. “How do you prevent capability escalation through composition?”
  4. “How do you test process-death and OEM background behavior?”
  5. “What would you remove from the first public release and why?”
  6. “How do you prove the emergency stop works?”

Hints in Layers

Hint 1: Integrate contracts, not implementations
Each project should already expose a stable port.

Hint 2: Build vertical slices
One trigger, condition, action, trace, and failure path before adding breadth.

Hint 3: Define product modes
Consumer, managed, and developer-only capabilities have separate onboarding and builds.

Hint 4: Use release gates
Threat model, policy declaration, migration, fault suite, battery, and secret scan block release.

Books That Will Help

Topic Book Chapter
Architecture trade-offs “Fundamentals of Software Architecture” Modularity and architecture characteristics
Evolution “Building Evolutionary Architectures” Fitness functions
Production “Release It!, 2nd Edition” Stability and operations

Common Pitfalls and Debugging

Problem 1: “Adding one adapter changes the core rule engine.”

  • Why: Platform-specific configuration leaked into domain types.
  • Fix: use versioned capability/action descriptors and adapter-owned configuration schemas.
  • Quick test: Remove the adapter module and ensure the engine still parses an unavailable node safely.

Problem 2: “The app works only with every capability granted.”

  • Why: Feature boundaries and degraded modes were never exercised.
  • Fix: run the full matrix with each sensitive capability denied or revoked.
  • Quick test: Start with zero grants and enable one routine progressively.

Definition of Done

  • The complete app works from zero-grant onboarding through progressive capability use.
  • All fifteen project contracts integrate without Android dependencies in the core engine.
  • Consumer, managed, and developer-only modes are visibly and technically separated.
  • Threat model, policy matrix, migration suite, fault suite, compatibility matrix, battery checks, and secret scans pass.
  • Global stop, per-rule disable, capability revocation, and data deletion are verified.
  • A new plugin/action can be added without modifying core evaluation semantics.

Project Comparison Table

Project Difficulty Time Depth of Understanding Fun Factor
1. Capability Navigator Level 1 10-14 h Foundation ★★★☆☆
2. Context Signal Monitor Level 2 16-22 h High ★★★★☆
3. RuleForge Core Level 3 22-30 h Very high ★★★★★
4. Durable Automation Library Level 2 18-26 h High ★★★☆☆
5. Timekeeper Scheduler Level 3 20-30 h Very high ★★★★☆
6. Notification Router Level 3 20-28 h High ★★★★☆
7. Command Surface Deck Level 2 16-22 h Medium ★★★★☆
8. Accessibility Inspector Level 3 24-34 h Very high ★★★★★
9. UI Macro Runner Level 4 30-42 h Very high ★★★★★
10. Plugin SDK Level 4 28-40 h Very high ★★★★★
11. ScreenLens Level 3 22-32 h High ★★★★★
12. Webhook and Termux Bridge Level 3 24-34 h High ★★★★☆
13. Managed-Device Lab Level 4 26-38 h Very high ★★★★☆
14. Observatory Level 3 28-40 h Very high ★★★★☆
15. FlowForge Studio Level 4 50-75 h Mastery ★★★★★

Recommendation

If you are new to Android: Build Projects 1-5 in order. They teach the platform contract before sensitive automation.

If you specifically want AutoInput-like skills: Build Projects 1-4, then 8, 9, 11, 14, and 15. Always use the owned sandbox target.

If you want a viable automation product: Focus on Projects 1-7, 10, 12, 14, and 15. Plugins and diagnostics create more durable value than depending on fragile UI macros for every action.

If you want enterprise control: Add Project 13 as a separately provisioned mode; do not blur it into consumer onboarding.

Final Overall Project: FlowForge Device Automation Platform

The Goal: Evolve FlowForge Studio into an automation platform with independently versioned host, plugin SDK, managed-device adapter, and optional local bridge.

  1. Stabilize the rule language and publish compatibility tests.
  2. Separate consumer, enterprise, and developer distribution tracks.
  3. Add a signed plugin catalog with capability review.
  4. Build a device-local observability and redacted support workflow.
  5. Run policy, threat, migration, compatibility, fault, performance, and battery release gates.

Success Criteria: A fresh device can install the consumer build, create useful rules with only progressive authority, observe every result, and revoke access safely. A managed emulator can add administrative actions without changing consumer authority. A third-party plugin can extend the host without bypassing signer, schema, capability, and user trust controls.

From Learning to Production: What Is Next

Your Project Production Equivalent Gap to Fill
Capability Navigator Permission and trust control plane Localization, accessibility, analytics minimization, OEM journeys
RuleForge Workflow runtime Formal schema governance, concurrency load, compatibility program
Timekeeper Scheduling service Fleet metrics, OEM support matrix, SLOs
UI Macro Runner Mobile RPA adapter Target contracts, drift detection, policy review, support costs
Plugin SDK Developer ecosystem Signing program, documentation, conformance suite, revocation
Webhook Bridge Integration gateway Key rotation, tenant isolation, abuse monitoring
Managed-Device Lab EMM/DPC product Android Enterprise enrollment, compliance, admin operations
Observatory Support platform Privacy review, retention controls, crash/telemetry governance

Summary

This learning path covers native Android automation through fifteen hands-on projects.

# Project Name Main Language Difficulty Time Estimate
1 Capability Navigator Kotlin Level 1 10-14 h
2 Context Signal Monitor Kotlin Level 2 16-22 h
3 RuleForge Core Kotlin Level 3 22-30 h
4 Durable Automation Library Kotlin Level 2 18-26 h
5 Timekeeper Scheduler Kotlin Level 3 20-30 h
6 Notification Router Kotlin Level 3 20-28 h
7 Command Surface Deck Kotlin Level 2 16-22 h
8 Accessibility Inspector Kotlin Level 3 24-34 h
9 UI Macro Runner Kotlin Level 4 30-42 h
10 Plugin SDK and IPC Host Kotlin Level 4 28-40 h
11 ScreenLens Capture Lab Kotlin Level 3 22-32 h
12 Secure Webhook and Termux Bridge Kotlin Level 3 24-34 h
13 Managed-Device Policy Lab Kotlin Level 4 26-38 h
14 Automation Observatory Kotlin Level 3 28-40 h
15 FlowForge Automation Studio Kotlin Level 4 50-75 h

Expected Outcomes

  • You can design a deterministic, persistent, capability-aware automation engine.
  • You can select supported Android APIs without treating broad authority as a shortcut.
  • You can build consentful notification, accessibility, plugin, screen, remote, and managed-device adapters.
  • You can prove behavior under denial, revocation, process death, reboot, Doze, version skew, UI drift, and hostile input.
  • You can assess Play-distribution, enterprise, and sideload/developer trade-offs before implementation.

Additional Resources and References

Official Android platform

  • Application fundamentals: https://developer.android.com/guide/components/fundamentals
  • Background work: https://developer.android.com/develop/background-work
  • Broadcasts: https://developer.android.com/develop/background-work/background-tasks/broadcasts
  • AlarmManager guidance: https://developer.android.com/develop/background-work/services/alarms
  • NotificationListenerService: https://developer.android.com/reference/android/service/notification/NotificationListenerService
  • AccessibilityService guide: https://developer.android.com/guide/topics/ui/accessibility/service
  • Package visibility: https://developer.android.com/training/package-visibility
  • Quick Settings tiles: https://developer.android.com/develop/ui/views/quicksettings-tiles
  • MediaProjection: https://developer.android.com/media/grow/media-projection
  • Device policy controller: https://developer.android.com/work/dpc/build-dpc
  • Android 16 behavior changes: https://developer.android.com/about/versions/16/behavior-changes-all

Policy and distribution

  • Google Play AccessibilityService policy: https://support.google.com/googleplay/android-developer/answer/10964491
  • Google Play Developer Program Policy: https://support.google.com/googleplay/android-developer/answer/17105854
  • Google Play Device and Network Abuse: https://support.google.com/googleplay/android-developer/answer/16559646

Books

  • “Effective Java, 3rd Edition” by Joshua Bloch — durable JVM API design.
  • “Enterprise Integration Patterns” by Gregor Hohpe and Bobby Woolf — messaging, routing, correlation, and idempotency.
  • “Release It!, 2nd Edition” by Michael T. Nygard — failure containment and production evidence.
  • “Clean Architecture” by Robert C. Martin — dependency and policy boundaries.
  • “Foundations of Information Security” by Jason Andress — authority, risk, and privacy foundations.