Runtime and integration

Gate Android Local AI Readiness Before First Unlock

Distinguish first unlock after reboot from screen relock, defer private model-task state, and limit pre-unlock work to justified device-encrypted metadata.

Review status: Fact and editorial QA complete; owner review pending · 2026-10-07 · Fact IDs: ANDROID-PRIVACY-01, ANDROID-PROCESS-RESTORE-2026-01, ANDROID-DIRECT-BOOT-2026-10

Direct answer

Start with the product requirement, not the Direct Boot API. For most on-device AI workflows, the correct state immediately after reboot is “waiting for this user to unlock.” A saved ready flag, a prior model load, or an alarm scheduled before shutdown does not prove that the model file, user history, or inference task is accessible before the first unlock. If no user-visible or system-critical action must happen in that interval, leave components unaware of Direct Boot, keep ordinary data in the default credential-encrypted (CE) storage, and initialize local inference after unlock. Android file-based encryption exposes two app storage contexts with different availability. CE storage is the default and is unavailable until that user successfully unlocks after boot. Once unlocked in the current boot session, CE stays available even if the screen is locked again; a later screen relock is not another first-unlock boundary. Device-encrypted (DE) storage is available before and after that unlock, but it is still encrypted. DE is not a general-purpose place for private data merely because it is readable earlier. Android recommends keeping files in CE whenever possible and limiting DE to information that must be available during Direct Boot. An app does not run during Direct Boot by default. A component that has a justified pre-unlock responsibility must be explicitly marked android:directBootAware and use a device-protected storage context for the data it needs. That choice is component- and storage-specific; it does not make the whole app or its model pipeline ready. A notification scheduler might need a small schedule marker, for example, but that is not a reason to move a full model, prompt history, audio transcript, photo, health note, or other user content into DE. Keep pre-unlock metadata minimal, non-sensitive, versioned, and independently useful without opening model input. At component startup, first call UserManager.isUserUnlocked() for the current user. If it is already true, continue on the unlocked path immediately rather than waiting for an ACTION_USER_UNLOCKED broadcast that may have occurred before the component started. If it is false and a running feature needs an unlock notification, dynamically register a BroadcastReceiver from that running component for ACTION_USER_UNLOCKED, then recheck state to cover an unlock racing with registration and handle the transition idempotently. Do not assume that a manifest-declared receiver will receive ACTION_USER_UNLOCKED. By contrast, ACTION_LOCKED_BOOT_COMPLETED is for an eligible manifest-registered android:directBootAware component with the required RECEIVE_BOOT_COMPLETED permission and registration. These events are not interchangeable with an ordinary screen-on or screen-unlocked callback. In a device with a work profile or separate user challenge, assess that context user's unlock state rather than borrowing the primary user's state; each storage boundary follows the relevant user. Model readiness should therefore be a state machine, not one persisted Boolean: locked-before-first-unlock, optional minimal-DE action complete, waiting-for-user-unlock, CE accessible, model asset checked, runtime initialized, and task ready are distinct states. Do not read a model from CE before unlock, and do not treat a DE metadata record saying “downloaded” as proof that the asset is currently mounted, complete, or loadable. After USER_UNLOCKED, re-resolve the asset location and identity, verify the checks the app actually supports, initialize the runtime, and offer a fresh task. If a needed asset is missing and the network is unavailable, remain not-ready and explain the next action. Do not silently start a large repair download, infer consent from boot, or move data between CE and DE to make an automatic task appear successful. Test this boundary with a dedicated disposable device or test profile that has a lock-screen credential. Reboot and stop at the lock screen; verify only explicitly designated components run and only the intended DE metadata is readable. Then unlock the current user, observe the unlock transition, and test CE-backed model availability and a new local task. Lock the screen again without rebooting and confirm that this is not misclassified as pre-first-unlock. Repeat after another reboot, and separately exercise a work-profile challenge only if the product supports that user mode. Record OS build, user/profile, storage context, event, file identity, network state, and result. This method does not establish that Cove has a Direct Boot receiver, pre-unlock inference, or any particular readiness behavior. The governing distinction is not “encrypted versus unencrypted”: both CE and DE are encrypted storage domains. It is whether the current user's credential-protected key is available in this boot session, and whether the feature has a real need to act before that moment. Keep private model-task data in CE by default. Move only the minimum explicitly justified pre-unlock metadata into DE, and only after a privacy and recovery review. If the task can wait, defer it. That produces a smaller pre-unlock surface and avoids claiming that a locally stored model automatically runs before first unlock.

A model task is requested immediately after reboot

A user restarts an Android device and opens the lock screen before entering the credential for the current user. The app previously stored a selected model and task preference, but the model and private history live in normal app storage. A product proposal suggests moving both to DE so work can start automatically.

Decision

First determine whether any user-facing function truly must run before first unlock. If none does, wait for the current user to unlock and leave model and task data in CE. If a narrow action is necessary, expose only its minimum non-private metadata through an explicitly Direct-Boot-aware component.

Expected outcome

The app reports a truthful locked/waiting state, does not access CE or move user content early, and checks the model again after the unlock event before accepting a new task.

Evidence to collect

The claim becomes reviewable only when the following evidence is attached to the same artifact and test run:

  • Current-user unlock and storage context
  • Minimal pre-unlock data inventory
  • First-unlock readiness and network-denied outcomes

A runtime comparison is publishable only when artifact identity, build configuration, selected backend, task fixture, and failures are recorded.

Implementation workflow

  1. Write down the pre-unlock user need. Name the exact action, its user or system beneficiary, and why it cannot wait until first unlock. If the only reason is faster startup or a saved ready flag, defer it; do not enable Direct Boot for convenience alone.
  2. Classify every file and state by user sensitivity. Inventory model assets, prompts, task inputs, histories, health or media records, preferences, and small scheduling metadata. Keep private data and anything not required before unlock in CE; do not move an entire model or user task just to avoid a wait state.
  3. Choose a minimal DE contract only when justified. For a genuine pre-unlock need, identify the specific small non-private fields, retention period, and component that needs them. Mark only that component Direct-Boot-aware and obtain its DE context explicitly; keep ordinary screens and inference setup on their post-unlock path.
  4. Gate behavior on the current user state. At component start, first call UserManager.isUserUnlocked() for that context user and proceed immediately if it is already true. If locked, a running component may dynamically register a BroadcastReceiver for ACTION_USER_UNLOCKED and recheck state after registration; do not rely on a manifest receiver or wait for an event that already passed. LOCKED_BOOT_COMPLETED instead belongs to a manifest-registered, eligible android:directBootAware component with the required RECEIVE_BOOT_COMPLETED permission and registration.
  5. Revalidate assets after unlock. Whether startup finds the user already unlocked or a registered running component receives the unlock transition, resolve the model path again, check exact artifact identity and whatever integrity evidence is configured, then initialize the runtime. A stored DE marker or pre-reboot “ready” status is not proof of current file access or successful runtime load.
  6. Test locked boot, first unlock, and later relock separately. On a credential-protected disposable device or profile, reboot and inspect the locked phase, unlock and test a new task, then relock the screen without rebooting. Record each current-user state, storage read, event, network condition, and failure without asserting Cove already implements a receiver.

Keep each transition observable. A failure should identify the stage, artifact, runtime, and recovery action without logging private user content.

Acceptance criteria

  • The feature has a documented pre-first-unlock requirement; absent that need, no component is made Direct-Boot-aware and model work waits for unlock.
  • Private inputs, prompts, history, and model-task state remain in CE by default; any DE fields are minimal, non-private, justified, and owned by an explicitly aware component.
  • Tests distinguish locked boot, current-user first unlock, ordinary screen relock, and any separately challenged profile; a component starting after unlock checks current state instead of waiting for a missed event, and model readiness is re-established rather than inferred from a stored flag.

Decision table

DimensionChoice or evidenceHow to interpret it
Defer until first unlockDefault local-AI pathKeeps private model and task data in CE and avoids a pre-unlock component when no real action must run early.
Use minimal DE metadataNarrow Direct Boot behaviorCan support a justified pre-unlock action, but only for explicitly scoped non-private state and an aware component.
Move model and task history to DEBroad pre-unlock storageExpands exposure and migration complexity without proving the model is ready or that inference should start before user unlock.
Treat screen relock as CE unavailableRepeated-lock interpretationIncorrect after the user has unlocked in the current boot; CE remains available until the device restarts.

Failure patterns to prevent

  • Moving private content into device-encrypted storage
  • Treating restored ready flags as artifact access

Also prevent silent fallback, unpinned artifacts, missing cancellation, and conclusions that combine unlike configurations. Store unsuccessful runs alongside successful ones.

Minimum reproducibility record

LayerRecord
DeviceManufacturer, model, chipset, RAM class, operating-system build
SoftwareApplication version and git commit
ModelFamily, variant, revision, format, file length, hash, quantization
RuntimeName, revision, requested backend, observed backend evidence
WorkloadFixture revision, input hash, prompt hash, output policy
OutcomeCompleted, failed, cancelled, fallback, and privacy-safe diagnostics

Release checklist

  • ☐ The primary query is answered without an unsupported number.
  • ☐ Every artifact and runtime is pinned.
  • ☐ The representative task and failure policy are explicit.
  • ☐ Lifecycle, cancellation, cleanup, and fallback are tested.
  • ☐ User-content and network boundaries are documented.
  • ☐ Result wording applies only to the recorded configuration.
  • ☐ The page links to raw method or evidence when results are added.

Sources and related evidence

Chinese deployment and troubleshooting content is organized in the .奇连 AI 端侧专题.

Frequently asked questions

Does credential-encrypted storage become unavailable whenever the screen locks?

No. CE becomes available after the current user first unlocks following boot and remains available if the screen is locked again. A new reboot creates the next first-unlock boundary; test that separately from an ordinary screen relock.

Should a local model or prompt history be moved into DE to speed up startup?

Not by default. Android says to use CE for private data or data not needed during Direct Boot, and recommends CE files whenever possible. Use DE only for the minimum non-private information required for a proven pre-unlock action.

How should the app handle the user-unlock notification?

At component startup, first check UserManager.isUserUnlocked() for the current user and continue immediately if already true. If locked, a running component should dynamically register a BroadcastReceiver for ACTION_USER_UNLOCKED and recheck state; do not assume a static manifest receiver gets that event. LOCKED_BOOT_COMPLETED instead uses an eligible manifest-registered android:directBootAware component and the required RECEIVE_BOOT_COMPLETED permission and registration.

Does ACTION_LOCKED_BOOT_COMPLETED mean model inference can start?

No. It is a locked-boot event for eligible Direct-Boot-aware components when DE is available. It does not grant CE access, prove a model asset is readable, initialize a runtime, or show that an inference request is appropriate before user unlock.

Can a primary-user unlock state stand in for a work profile?

No. Check the relevant current user or profile, especially when a work challenge controls its CE storage. Do not use one user’s unlock event as evidence that another profile’s credential-protected files are available.