In September 2025, three researchers took apart SafetyCore.
SafetyCore is the Android system service behind Sensitive Content Warnings in Google Messages, and it classifies images on the device. Google built it that way for the obvious reason, and says so plainly in its own support documentation: classification "happens on-device," and the feature "doesn't send identifiable data or any of the classified content or results to Google servers." The privacy argument for that design is sound, and I am not going to argue with it.
The researchers pulled the model out anyway. It was a ResNet variant. They converted it to ONNX, loaded the weights with onnx2torch, recovered the architecture, and then manipulated the model to get past its own detection. Their own summary of the result is that this was enough for "effectively rendering the protection ineffective."
Read what happened there carefully. A safety control was placed on the device because that was the private thing to do. Placing it on the device is what handed every attacker a local, inspectable, differentiable copy of the detector they wanted to evade. The privacy win and the safety loss were not two decisions that happened to collide. They were one decision, seen from two directions.
The privacy claim is true. The claim people infer from it is false.
Most writing about on-device AI makes a claim about data movement, and that claim is usually correct. Inference on the device means the input does not travel to a data centre. That is a real gain, it is underrated, and I am not here to dispute it.
What goes wrong is the inference drawn from it. "The data never leaves the device" gets read as "there is no attack surface" and, more quietly, as "there is nothing left to operate." Both readings are wrong, and they fail for the same structural reason.
Here is the claim this article owns:
On-device inference does not remove your attack surface or your operational burden. It relocates the first onto hardware your adversary controls, and the second onto a fleet you cannot reach. Privacy moves from a boundary you operate to a boundary the user operates, which is a genuine improvement. Control does not move with it. Neither does liability.
One part of that claim is measurable, and it needs a name, because it governs almost everything else.
The Revocation Horizon
I am going to call the elapsed time between deciding to change a model's behaviour and the last device in your fleet actually running that change the Revocation Horizon.
To disambiguate, since both words are loaded for this audience: this has nothing to do with certificate revocation, and nothing to do with any product named Horizon. It is the revocation of model behaviour, and "horizon" in the sense control theory uses it, a time window you cannot see past. It is also not public-key infrastructure's revocation latency, which is a per-certificate, per-event quantity. This is a distribution over a whole fleet, and its upper percentile is the number that governs your incident response.
For cloud inference the Revocation Horizon is close to zero. You deploy, and the next request runs the new behaviour. Worth stating plainly, because the whole argument rests on it: in cloud inference, the request is the check-in. There is no separate moment when the device has to come and ask whether anything changed. Serving the request and enforcing the policy are the same event.
Move inference onto the device and those two events come apart. Now the model runs whether or not anything checked in. Your ability to change its behaviour depends on a second, independent event that you do not control and cannot schedule.
Everything with a clock on it is downstream of that number. A jailbreak you patch today stays live on your fleet for one Revocation Horizon. A guardrail you tighten takes one Revocation Horizon to bind. A regulatory marking requirement that changes takes one Revocation Horizon to satisfy. If you have never measured yours, you do not know how long any of your fixes take to matter.
What the fleet numbers actually look like
Apple publishes device adoption, and Apple runs the best-updating large consumer fleet in existence. As measured on 7 June 2026, roughly nine months after release, iOS 26 was on 86% of iPhones introduced in the previous four years and 79% of all active iPhones. For iPadOS 26 the same figures were 79% and 68%.
Look at the second number in each pair. Nine months in, with nag screens and overnight auto-install and a vendor that controls the whole stack, one iPhone in five and one iPad in three is not running the current operating system.
I phrase it that way deliberately. The 21% is not all on last year's release; it is spread across several older ones, and you do not get to know how far back the tail runs. Apple's figures are also measured from devices that connect to the App Store, so they are censored on exactly the population that worries you, a problem that comes back when we try to measure your own fleet.
Android is worse, and also harder to measure honestly. StatCounter's July 2026 pageview share puts Android 16 at 25.71%, thirteen months after its June 2025 release, with 17.45% on Android 15 and 14.88% still on Android 13.
Google retired the Android version distribution dashboard. developer.android.com/about/dashboards now publishes only Vulkan and OpenGL ES distribution, and points developers at their own Play Console reach data instead. So there is no first-party Android version distribution figure for 2026, and the third-party sources disagree: StatCounter says 25.71% for Android 16 in July 2026 while AppBrain reports 24.1%. They weight by pageviews and by app installs respectively. Cite both, or cite neither, but do not call either one official.
Those are operating system numbers, and your app is not the operating system. I use them because they are the empirical ceiling on the last term of your own horizon. When the platform vendor takes nine months to reach 79% of its own fleet, an app has no basis for assuming it will do better.
The wrong way: a cloud-era safety story running on a local model
Here is the shape of a safety story I have seen ship more than once. Every control in it is real, and every one worked in the cloud version of the same product. The change that moved inference on-device altered exactly one line in this file, and it was not one of the controls.
private const val REFUSAL = "I cannot help with that right now."private const val RATE_LIMITED = "You have reached today's limit."private const val BLOCKED = "This feature is unavailable on this device."enum class IntegrityVerdict { GENUINE, TAMPERED, UNKNOWN }// Facade. The real Play Integrity flow requests a token and decodes it on// your server; a local synchronous verdict like this is itself the bug, and// it is a bug you cannot fix without a network round-trip.interface AttestationFacade { fun verdict(): IntegrityVerdict }// Shipped: the assistant, with the safety story we had before inference moved.class OnDeviceAssistant( private val model: LocalLlm, // weights bundled in the APK private val remoteConfig: FirebaseRemoteConfig, private val integrity: AttestationFacade, private val backend: QuotaService, private val userId: String,) { suspend fun answer(prompt: String): String { // Control 1: kill switch, flipped server-side if the model misbehaves. if (!remoteConfig.getBoolean("assistant_enabled")) return REFUSAL // Control 2: per-user abuse throttle, counted by our backend. if (!backend.claimQuota(userId)) return RATE_LIMITED // Control 3: run only where Play Integrity says the device is genuine. if (integrity.verdict() != IntegrityVerdict.GENUINE) return BLOCKED // Control 4: guardrails live in the system prompt, hot-updatable. val system = remoteConfig.getString("system_prompt") return model.generate(system, prompt) }}That code is coherent: it compiles, the control flow is sound, and a reviewer scanning for missing checks will find none. Four independent safety controls guard a single inference call.
Now put that binary on a phone in aeroplane mode, or on a phone whose owner last opened the app in March. Control 1 reads a cached config. Control 2 fails, and whichever way you wrote the failure branch is now your actual abuse policy. Control 3 cannot reach Google. Control 4 hands the model a stale system prompt.
model.generate runs regardless. It is the only line in the function that does not need the network.
Why all four controls need the device to come to you
Take them one at a time, against what the platforms actually document.
Kill switch. Firebase Remote Config defaults to a minimum fetch interval of 12 hours in production. Real-time Remote Config exists precisely to beat that, holding an open connection so the server can push an invalidation signal the moment a new version is published. It also carries this, in Google's own documentation: it "automatically stops listening for updates when the app enters the background and restarts when the app is foregrounded." A kill switch on that transport reaches a device only while a human is looking at your app. There is a second ceiling underneath it: 20 million concurrent connections per project, and past that point "incremental real-time connection requests may be rejected, and the client SDK will automatically fall back to the standard fetch mechanism." At fleet scale, the fallback is the 12-hour path.
Throttle. A per-user quota counted on your backend counts requests that reach your backend, and this one has two failure modes depending on what the migration did to it. Keep the call, as the code above does, and every offline inference is unmetered while your dashboard shows a flat and healthy request count. Delete it, which is what the latency argument for going on-device pushes you toward, since a network round-trip in front of a local model gives back the latency you moved it to gain, and the control does not degrade. It stops existing, and nothing in your dashboards changes, because the requests it used to count were never created.
Attestation. Play Integrity requires a network connection. Google is most explicit about this for the companion-device check, which needs the target device "awake and have an active internet connection" and times out after 30 seconds when it is unreachable, and the dependency is structural rather than specific to that flow. It is a server-side control that tells your backend a device looks genuine. It can say nothing at all about a device that never contacts your backend, which is the exact device running your model offline. Attestation-gated feature disable is a real mechanism, and it is real only for online features.
Hot-updatable prompt. This one is the most interesting, because the failure is not that it breaks. It silently becomes a different mechanism. A system prompt delivered by Remote Config inherits every property above, so your guardrail is now exactly as fresh as the user's last foreground session on a network.
The pattern under all four: every control you own is enforced where something crosses a boundary you operate. Move inference inside the device and the inference path stops crossing that boundary. These controls do not weaken one by one. They all stop applying at once, for a single reason, and your monitoring looks unchanged because it was measuring traffic that no longer exists.
For each control in your safety story, ask one question. Does enforcing this require a request to cross a boundary I operate? Every yes is a control that on-device inference deletes. Ask it of patterns you already trust, too. The tool execution firewall works because every tool call passes a checkpoint you own, and moving the model that decides those calls onto the device does not move the checkpoint along with it.
Four deployment tiers, four Revocation Horizons
There is no single horizon for all of on-device AI. It stratifies by where the weights live, and the spread between the best and worst tier is wide enough that treating them as one category is the mistake underneath most arguments about this.
Tier 1, weights in the app binary. Your horizon is store review, plus whatever staged rollout you chose, plus device check-in and user consent. Android gives you the strongest hard-stop primitive in mobile here, and it has a limit worth memorising. Update priority is an integer from 0 to 5, set through Edits.tracks.releases, and the documentation is explicit: "Priority can only be set when rolling out a new release and cannot be changed later." So on the Tuesday you discover last month's model is misbehaving, you cannot reach back and mark that release urgent. You publish a new one and wait. The escalation path has the lag built into it. On iOS there is no equivalent primitive at all, and pulling an app from sale does not remove it from a single device that already has it.
Tier 2, model downloaded at runtime. Decoupling model version from app version is the highest-leverage change available, and it moves the horizon to hours or days. Fetching the artifact yourself from object storage is what actually buys the decoupling, and it is worth being careful about which mechanisms deliver it, because the first-party one does not.
Google's managed option is Play for On-device AI, in beta as of August 2026, which packages models as AI packs inside your app bundle with install-time, fast-follow or on-demand delivery. It is a real improvement on shipping weights inside the base APK, and Play patches only what changed. It is also explicit about the thing that matters here: "AI packs are updated together with the app binary." The model rides the app release. So the managed path gives you better delivery economics at Tier 1's Revocation Horizon, not Tier 2's, and reaching Tier 2 still means hosting the artifact yourself and writing your own download, versioning, integrity check and rollback.
The size limits shape which tier a model can even reach. An individual AI pack can be up to 1.5 GB compressed, and 4 GB is the ceiling on the total app size generated from your bundle. A quantized model comfortably under 1.5 GB has options. A larger one is structurally pinned to whichever delivery path can carry it, which in practice means the biggest models on a device are the ones with the longest horizon and the least room to manoeuvre.
There is a regression underneath all this. Firebase ML, the first-party product that gave you a console button to push a new model to a fleet, is deprecated and shuts down on 15 June 2027. Google's migration guidance for anyone using it to host models for local inference is to "migrate your apps to use Cloud Storage instead," which means writing that download, versioning, rollback and staleness logic yourself. Play for On-device AI is a successor for packaging and delivery, not for out-of-band model updates, since its packs move with the binary. The tooling here is churning rather than maturing, and the thing you built against in 2024 has a 2027 shutdown date.
Tier 3, server flags gating local inference. Real-time Remote Config drives the horizon down to a single foreground session, a genuine two-order-of-magnitude win over Tier 1. It does not remove the horizon. It converts app-update lag into session lag, which is shorter on average and still unbounded in the worst case, because a dormant install has no next session and an offline device has no transport.
Tier 4, platform-managed models. Gemini Nano through AICore, or Apple's Foundation Models framework. This tier deserves its own section, because it does not shorten your horizon so much as remove your standing to have one.
The strongest argument against this, and where it stops working
I want to state the counter-argument at full strength, because it is better than most rebuttals of this thesis, and because one piece of evidence for it is the platform vendor conceding the exact point.
Google deprecated its own Neural Networks API in Android 15. The migration guide says why, and it reads almost as a restatement of this article's thesis in Google's voice: after that API shipped, "the high rate of innovation in the field meant that developers needed tools and infrastructure that update frequently." So Google replaced a machine learning acceleration layer pinned to the operating system release cadence with runtimes that update independently of it. A vendor shipped infrastructure on a slow update channel, measured the consequence, and moved off it.
Put the rest of the counter-argument alongside that. Gemini Nano is distributed and updated by AICore, entirely outside your binary. Apple ships Foundation Models with guardrails that are always applied and, in the framework documentation's words, "currently, you cannot disable it." Play Asset Delivery decouples model from app. Real-time Remote Config invalidates in seconds. Priority 5 in-app updates can block use of the app outright. Play Integrity gates features on a server verdict. Every control this article says you lost has a shipping replacement, most of them documented on developer.android.com, and a competent 2026 team can drive the horizon down to hours. On that reading, the thesis describes 2022 practice and calls it a law.
That argument is substantially right, and it changes what the rest of this article can claim. It does not survive three things.
The first is the floor. Not one of those replacement controls can act on a device that is offline or dormant, and each says so in its own documentation: Remote Config stops listening in the background, Play Integrity needs a live connection and gives up after 30 seconds, in-app update prompts need the user to open the app. Play's background auto-update is the fair concession here, since it installs over Wi-Fi with no session required, and the floor still holds on offline and dormant devices alone. Shortening a horizon is not the same as closing it. Cloud inference has no tail at all, because the request is the check-in, and that asymmetry is not immature tooling. It is what "on-device" means.
Second, and more weakly, the managed tooling is churning rather than maturing on this specific axis. Firebase ML has a 2027 shutdown date, its replacement for hosted models is object storage plus your own code, and Play for On-device AI, the closest first-party successor, is in beta and ties model updates to the app binary by design. I would not rest the argument on this leg alone, and the first and third legs do not need it.
The third is the subject of the next two sections.
Tier 4: the platform owns the model, you own the liability
Tier 4 is the best available answer to the horizon problem, and reading Google's own documentation for it is uncomfortable.
On distribution, the Gemini Nano documentation says AICore "manages the distribution of Gemini Nano and handles future updates," and that "you don't need to worry about downloading or updating large models over the network." On safety, the same page says AICore "has several built-in safety features." Then, a little further down: "Developers are solely responsible for the safety of their API client and their app's user experience."
Both statements are reasonable on their own. Together they describe a position I would push back on in a design review. You are answerable for the behaviour of a model you cannot pin, cannot version, cannot inspect, and cannot roll back.
Your Revocation Horizon for a model-level fix did not shrink at Tier 4. It went to infinity, because the lever is no longer yours. Someone else's horizon may well be short, and Google's probably is. That is a different property from yours, and not one you can measure, put in an SLO, or show an auditor.
Be precise about what is and is not documented here. Google does not publish the Gemini Nano model update channel. Several developer blogs assert that models arrive through Play system updates; the official documentation I can find says distribution is AICore-managed with network access routed through Private Compute Services, and specifies a full Android over-the-air update only for changes to the package binding allowlist. Apple's third-generation Foundation Models announcement of 8 June 2026 similarly does not disclose delivery or update mechanics for its 3B on-device model.
Google and Apple both leave the model update channel undocumented. For a team that has to answer an auditor asking which model version produced a given output, that silence is the finding.
Why the same quantized model does not behave the same on every device
There is a belief among practitioners that local inference gives you a frozen, reproducible environment: you know exactly which weights, which quantization, which version. On your own workstation that is true, and it is one of the genuine pleasures of running models locally.
Across ten million consumer devices it inverts twice over.
It inverts once because "frozen" at fleet scale means unrevocable, which is the argument above. It inverts a second time because the model is not actually frozen. Google's LiteRT delegate documentation states that "delegates usually perform computations at a different precision than their CPU counterparts. As a result, there is an (usually minor) accuracy tradeoff associated with utilizing a delegate for hardware acceleration." The same page describes an all-or-nothing failure mode: "If you provide a floating-point model to a delegate that only supports 8-bit quantized operations, it will reject all its operations and the model will run entirely on the CPU."
So which arithmetic your model runs is a function of which accelerator it landed on, and whether it runs on the accelerator at all is a function of operator coverage on that device.
None of this is an argument against putting small models on devices. I have argued the opposite, that small language models are infrastructure rather than scaled-down chatbots, and that SLM-first systems need their own composition patterns. The point here is narrower and it is about operations: the artifact you shipped is not reliably the artifact that runs, and nothing in your telemetry tells you which one did.
Quantization adds a second axis, and the peer-reviewed numbers are more interesting than the averages suggest. Evaluating quantized instruction-tuned models up to 405B parameters, Lee and colleagues measured Llama-3.1-8B against FP16 and found 8-bit methods essentially free: FP8 at +0.11%, GPTQ 8-bit at +0.24%. Four-bit methods cost 1 to 2 points on average, with AWQ 4-bit at -1.58% and GPTQ 4-bit between -1.42% and -2.23%.
Averages hide the part that matters. That study's worst single-task result for Llama-3.1-8B was GSM8K under GPTQ 4-bit, down 6.67 points. At 70B on the harder leaderboard, GPTQ 8-bit lost 3.36% on average with GPQA down 11.47 points; at 405B, SmoothQuant W8A8 fell 2.93% and 9.23% on the two leaderboards respectively.
The study's own conclusion names the categories that suffer. Quantized models generally beat smaller models "except in hallucination detection and instruction-following tasks."
One caveat on transferring those numbers, in the same spirit as the others in this article. GPTQ, AWQ and SmoothQuant are server-side methods applied to server-class checkpoints. A mobile stack uses different ones: LiteRT int4 and int8, Apple's palettization, GGUF K-quants in the llama.cpp lineage. Their error characteristics are not interchangeable, and I could find no published evaluation of instruction-following degradation on a Core ML or LiteRT artifact specifically. The direction is well supported. The magnitude on the thing you actually ship is not something I can source.
Read that as a security finding rather than a benchmark finding, and read the comparison precisely, because it is narrower than it looks. What the study measured there is quantized-larger against smaller-full-precision, not one model at two precisions. That is exactly the substitution a memory budget forces on a mobile team: take the bigger model at 4-bit, or the smaller one intact. The finding says the first option is not a safe drop-in for the second on instruction following. And instruction-following is the capability guardrails are built on. A system prompt is an instruction, a refusal policy is an instruction, a tool-use restriction is an instruction. Your red team signed off on one of those two models, and no on-device telemetry will tell you when the other one disobeys.
Thermal behaviour adds a third axis. The MobiCom 2024 MELT work, measured on 2024-era flagships two silicon generations back, recorded an iPhone 14 Pro reaching 47.9 degrees Celsius during conversational inference, with sustained throughput dropping in two distinct steps at the 20th and 32nd prompts as the device changed power modes. Peak instantaneous draw was above 18 W on the iPhone and 14 W on a Galaxy S23. Metal-accelerated iPhones showed 78.93% higher generation throughput on average than OpenCL-accelerated Android devices. Below 4-bit, the same study found models "mostly hallucinating or plainly repeating the prompt" at 3B parameters and under.
One honest gap. Google documents that delegates compute at different precision, and the quantization literature measures what precision costs on benchmarks. I could not find a published measurement of how much the outputs of one quantized model actually diverge across device tiers in a real fleet. The mechanism is vendor-documented; the magnitude is unmeasured. For a deployment pattern this widely shipped, that absence is itself a statement about how mature on-device operations are.
Hardware will not rescue this, and the most credible person to say so is not a critic. Vikas Chandra, a distinguished scientist at Meta, published a state-of-the-union on on-device language models in January 2026. Its flat verdict is that "TOPS alone doesn't tell you much." His numbers explain why. Mobile neural accelerators run 35 to 60 TOPS, which is real compute. Mobile memory bandwidth runs 50 to 90 GB/s against 2 to 3 TB/s in a data centre, a gap he puts at 30 to 50 times, and available memory is "typically limited to <4GB even on high-end devices."
Autoregressive decode is bandwidth-bound rather than compute-bound. Generating one token means streaming the active weights through the accelerator and multiplying them by a single skinny activation vector. Divide bandwidth by active weight size and you have your ceiling: a model with 1 GB of active weights tops out somewhere near 50 to 90 tokens per second on that hardware, and it does not matter whether the accelerator claims 35 TOPS or 60. That is the ceiling and not the number you will see, since real systems reach a fraction of peak bandwidth and the throttling above pulls it down further. Prefill is compute-bound and does benefit from the TOPS. Decode, which is what your user is waiting on, does not.
What unlimited offline queries buy an attacker
This is the part that is independent of the Revocation Horizon, and the reason a shorter horizon is a mitigation rather than a fix. Even at a one-hour horizon, the weights are on hardware the attacker owns.
Before the evidence, a distinction the word "attacker" hides, because it decides how much of this section applies to you.
Sometimes the device owner is the adversary. That is SafetyCore, and it is every content filter, parental control, licence check and anti-cheat measure: the model is a gate against the person holding the phone. Sometimes the adversary is a third party, and the owner is the beneficiary, which covers most assistants, summarisers and translation features. Those two cases have opposite economics. Someone who strips the guardrail off their own commodity assistant has produced an uncensored small model, and uncensored small models are already a free download. The effort buys them nothing.
So the guardrail-removal argument below bites hard in two situations: when the model constrains its own host, and when the weights carry something not otherwise obtainable, such as a proprietary fine-tune, personal data, or credentials for a tool the model can call. Where neither holds, the real exposures are narrower and still worth naming, and they are intellectual property loss and the surrogate attack described at the end of this section. The rest of this section is about the cases where it does bite.
Start with extraction, because the numbers are unambiguous. A large-scale study of 46,753 apps found 1,468 with machine learning models, of which 41% shipped models with no protection at all, "trivially stolen from app packages." The authors then extracted models from 66% of the apps that did claim protection. Five years later, THEMIS reported extracting every plaintext model from a set of 403 real-world apps, and a 90.48% success rate against the encrypted models in that same set, against 33.33% for prior work. Read it as a result on one paper's sample rather than an industry-wide rate. The ICSE 2024 DeMistify work reports extracting and successfully re-running models from 1,250 of 1,511 top apps, or 82.73%. Shipping weights to a device is a distribution decision before it is a security one, which is the same tension that runs through the argument about who open weights actually democratise.
Encryption is worth doing and it is not a boundary. Runtime instrumentation attacks the moment of decryption rather than the file, so encrypting the artifact moves the extraction point without removing it. Apple's Core ML encryption is the best-engineered mainstream version, with the compiled model AES-128 encrypted and the plaintext existing only in memory. One detail in it is worth noticing on its own terms: the decryption key is fetched from Apple on the app's first launch. So the strongest on-device model protection in mainstream mobile needs a network round-trip, which sits awkwardly beside the claim that on-device means nothing needs the network.
Hardware-backed execution is the usual next suggestion. THEMIS characterises trusted-execution-environment protection as theoretically superior but impractical at current deployment scales, and I have no measured overhead figure to offer either way.
Extraction is step one of a tooled pipeline, and that is what makes it consequential.
Consider what holding the weights does to an attack. Greedy Coordinate Gradient, the canonical jailbreak from Zou and colleagues, needs gradient access, which is what makes it a white-box attack. The roughly 256,000 model evaluations it runs are the price that access buys you, and they are local forward passes over candidate token substitutions rather than calls to anyone's API. Query-efficient black-box methods exist because most targets never expose gradients at all: PAIR jailbreaks within about 20 queries, Tree of Attacks reports 11.8 on Vicuna-13B and 90% success on GPT-4 in 28.8, and a 2026 preprint reports averages of 1.357 queries on Gemini and 1.512 on GPT-4 against undisclosed model versions.
That last number cuts both ways, and I would rather say so than lean on it. If frontier models fall to roughly one or two remote queries, then unlimited local querying is not the dramatic unlock it first appears to be, because the black-box path was already cheap.
What on-device deployment actually changes is two things, and neither depends on query budget. The attacker gets gradients, which makes the whole optimisation-based family available against your specific artifact rather than a similar one. And your shipped model becomes a free, exact, permanently available surrogate for building prompts that transfer to your other deployments, including the cloud endpoints you thought were the guarded ones. Bishop Fox has productionised Greedy Coordinate Gradient as Broken Hill, explicitly so it no longer needs the 80 GiB datacentre accelerators the original paper used, and the prompts it generates transfer to instances configured differently from the one used to build them. Shipping the weights is what supplies the surrogate.
Then there is the cheapest attack of all. Arditi and colleagues showed at NeurIPS 2024 that refusal in language models is mediated by a single one-dimensional subspace, across 13 open-weight chat models up to 72B parameters. Erasing that direction stops the model refusing harmful instructions. No fine-tuning is required; it is implementable as a rank-one weight orthogonalisation, and the community ships it under the name abliteration.
Your shipped guardrail is close to one matrix multiply from gone. Not one exploit, one training run, or one clever prompt. On a quantized mobile artifact it is dequantize, edit, requantize, repack, which adds an afternoon rather than a research programme. Later work also finds refusal is not perfectly one-dimensional in every model, so this is not universal. It is cheap enough that the distinction rarely helps you.
A 2026 systematic review of on-device inference attacks and defences found the literature badly lopsided. Roughly 25% of attack papers target intellectual-property theft while about 50% of defence work addresses it, and adversarial attacks account for roughly a third of the attack literature with no defence papers paired with them anywhere in that corpus. Scope that correctly: the general adversarial-robustness literature is large, and what is missing is work evaluating it under mobile deployment conditions. The review is also a May 2026 preprint. The gap is in on-device-specific defence, not in the field.
Two smaller exposures are worth knowing about, stated at the confidence the evidence supports.
Android's Auto Backup is opted in by default. android:allowBackup defaults to true, and for apps targeting API 23 and above the default set includes shared preferences, files in internal storage from getFilesDir(), and databases from getDatabasePath(). Those are precisely where a mobile engineer would put conversation history, a prompt log, or a cached context file. Excluding them takes an explicit android:dataExtractionRules entry on Android 12 and above. "The data never leaves the device" and "we never wrote exclusion rules" cannot both be true. Two caveats keep this honest. A 25 MB per-app quota means large artifacts fail to back up rather than leaking, which skews exposure toward small high-signal files. Backups are also end-to-end encrypted with the device credential on Android 9 and above, so the change is one of scope and jurisdiction rather than plaintext exposure to Google.
Key-value caches are the second exposure. NDSS 2026 work on cache privacy establishes that a key-value cache is a sensitive artifact from which input can be recovered. It gives two routes: inverting the cache using known weight matrices, and generating candidate caches from a local model instance to match against the target. That paper's threat model is multi-tenant serving rather than on-device, so applying it here is my extension rather than its conclusion. What transfers is the mechanism: inversion needs the weights, the collision attack needs a local model instance, and on-device deployment hands over both for free.
I should also say what I did not find. There is no CVE I could locate for on-device AI cache or model-artifact leakage. Given the systematic review's finding about missing defence literature, I read that as under-reporting rather than absence, but I am not going to imply an incident I cannot cite.
The right way: bound the staleness, fail closed, measure the floor
No control reaches a device that is offline, so the fix is not a control. Make staleness an explicit, bounded, observable input to every inference decision, and put nothing behind the offline path that you would ever need to revoke.
// Policy arrives as signed bundles, versioned independently of both the APK// and the model. Staleness is an input to the decision, not an assumption.// Duration, Clock and Instant need API 26+ or core library desugaring.class GuardedAssistant( private val model: LocalLlm, private val policy: PolicyStore, private val localBudget: LocalRateLimiter, private val telemetry: Telemetry, private val clock: Clock,) { // Derived from incident tolerance, then checked against the DAU // distribution. Two thresholds, because one is not deployable: degrade // first, deny second. See the discussion below for how to pick them. private val softPolicyAge: Duration = Duration.ofHours(24) private val hardPolicyAge: Duration = Duration.ofDays(7) sealed class Denied { object NoPolicy : Denied() data class Stale(val age: Duration) : Denied() object ImplausibleClock : Denied() object DisabledByPolicy : Denied() object LocalCapReached : Denied() } // Carries the denial reason out to the caller instead of a bare null. class PolicyError(val reason: Denied) : Exception(reason.toString()) suspend fun answer(prompt: String): Result<String> { // policy.current() returns signature-verified bundles only. // An unverifiable bundle is NoPolicy, not a usable policy. val current = policy.current() ?: return Result.failure(PolicyError(Denied.NoPolicy)) // Two clocks. The signed issuedAt is authoritative for intent; the // monotonic elapsed time since the last verified fetch is what a // device owner cannot wind back. Take the more pessimistic answer. val wallAge = Duration.between(current.issuedAt, clock.instant()) val monotonicAge = policy.elapsedSinceLastVerifiedFetch() val age = maxOf(wallAge, monotonicAge) // A negative age means the wall clock moved backwards. On hardware // the owner controls that is a tamper signal, not a fresh policy. if (wallAge.isNegative) { telemetry.recordDenial(Denied.ImplausibleClock, current.version) return Result.failure(PolicyError(Denied.ImplausibleClock)) } // Fail closed on staleness, in two stages. An offline device loses // capability first and the feature second; it never silently loses // the guardrail. The wrong version got this branch backwards. if (age > hardPolicyAge) { telemetry.recordDenial(Denied.Stale(age), current.version) return Result.failure(PolicyError(Denied.Stale(age))) } val effective = if (age > softPolicyAge) current.degradeToConservative() else current if (!effective.featureEnabled) { telemetry.recordDenial(Denied.DisabledByPolicy, effective.version) return Result.failure(PolicyError(Denied.DisabledByPolicy)) } // Enforced on-device, so it survives having no network. A backend // quota cannot count requests that never reach a backend. if (!localBudget.tryConsume(cost = 1, cap = effective.perDeviceDailyCap)) { telemetry.recordDenial(Denied.LocalCapReached, effective.version) return Result.failure(PolicyError(Denied.LocalCapReached)) } val output = model.generate(effective.systemPrompt, prompt) // The horizon is a metric. Emit it, or it is not an SLO. Queued // locally and backfilled, because this crosses the same boundary // every control above does. telemetry.recordInference( policyAge = age, policyVersion = effective.version, degraded = age > softPolicyAge, modelVersion = model.version, delegate = model.activeDelegate, ) return Result.success(output) }}Three of the original four controls have a successor here. One does not, and that is worth more of your attention than the three that do.
The kill switch became a staleness bound. Rather than reading a cached flag and trusting it, the code degrades at one threshold and refuses at a second. An offline device loses capability before it loses the feature, and it never silently keeps the feature while losing the guardrail.
Two thresholds rather than one, because the single-threshold version is a teaching example and this is the deployable one. Pick them by asking how long you are willing to keep running behaviour you have already decided to change, then check that answer against your own daily-active distribution and accept the feature-loss rate it implies. A 24-hour hard denial sounds rigorous and will cut off every user who spends a weekend away from a network. There is also a failure mode worth designing against explicitly: if your policy service goes down for longer than the bound, every device in the fleet fails closed at once, and you have converted a config outage into a total outage. Ship a signed conservative fallback policy inside the binary and fall back to that rather than to nothing.
The throttle moved on-device. A local rate limiter enforces a cap that a backend quota service cannot, because the requests never reach a backend. It is weaker than a server-side per-account budget, and it runs.
Policy separated from both the binary and the model, so it carries its own version and its own horizon. Guardrail changes no longer wait on a store review.
Attestation has no successor. Play Integrity decodes its verdict on your server, so a device that never contacts your server cannot be evaluated, badly or otherwise. Nothing in GuardedAssistant replaces it, because nothing can. I would rather name the control I could not replace than present a tidy four-for-four table, and the honest statement is that on-device inference removes device attestation from your safety story and gives you nothing back.
Which points at the limit of the whole pattern. A staleness bound enforced on the device is a control against drift and neglect, not against a determined device owner. The two-clock check above raises the cost of winding a system clock back, and a sufficiently motivated owner still holds the hardware. That is not a flaw in the pattern. It is the thesis: nothing enforced on a device defends against the person holding it.
The horizon became telemetry, which has the same hole as everything else. Every inference emits the policy age it ran under, alongside the model version and which delegate served it, and that is what makes the delegate-divergence and quantization problems debuggable at all. But telemetry crosses the same boundary those four controls did. The staleness denials you most need in aggregate are the ones from devices that cannot deliver them. So queue locally with a bounded buffer, timestamp against a monotonic source so backfilled events are not misdated, and accept that a device which never reconnects is invisible in both directions: you cannot reach it, and you cannot count it. Designing this deliberately matters for the same reason traditional monitoring breaks on autonomous systems: the unit of work you need to reason about is not a request your infrastructure ever saw.
Then measure the thing, with an instrument whose blind spot you state up front:
// Tier 1 instrument: how long an available app update has gone uninstalled.// Only ever runs on a device that reached Play. See the censoring note below.appUpdateManager.appUpdateInfo.addOnSuccessListener { info -> if (info.updateAvailability() == UPDATE_AVAILABLE) { val staleness = info.clientVersionStalenessDays() if (staleness == null) { // Unknown staleness is not zero staleness. Counting it as fresh // biases the metric toward the answer you were hoping for. telemetry.recordStalenessUnknown(priority = info.updatePriority()) } else { telemetry.recordStaleness(days = staleness, priority = info.updatePriority()) } }}Report the p50 and the p95 of that distribution, and then report the number that makes them honest.
Here is the trap, and it is the one I would have walked into. That callback only runs on a device that opened your app, reached Play, and had an update waiting. The devices that define the tail, the offline and the dormant and the ones behind a network that blocks Play, never execute it. They are not outliers in the distribution. They are absent from it. So the p95 you compute is a p95 over the reachable fleet, censored on precisely the population this whole article is about, and Apple's adoption figures carry the same bias for the same reason, since they are measured from devices that talk to the App Store.
Publish it as a pair. Take installs from the Play Console, subtract 30-day-active devices, and express the remainder as a percentage. Then the sentence you can defend is: our Revocation Horizon is nine days at p95 across the 86% of the fleet we can see, and unbounded across the other 14%. That is a worse-sounding number and a far more useful one, and it is the only version an incident review will not tear apart.
One more scoping note. clientVersionStalenessDays measures the age of the app binary, which makes it the right instrument for Tier 1 and the wrong one for Tiers 2 and 3, where model and policy versions are deliberately decoupled from the binary. There, the measurement you want is the policyAge the GuardedAssistant above already emits on every inference, plus the model artifact's own version. Measuring binary age in a Tier 2 deployment is how you end up reporting a horizon for an artifact you are not shipping.
Every on-device path, whatever its tier, runs through one gate that cloud inference never reaches. That is why the tiers converge rather than differing all the way down, and it is what the diagram below traces.
flowchart TD
D["You decide to change<br/>the model's behaviour"]
D --> CLOUD["Cloud inference:<br/>deploy to your service"]
CLOUD --> CDONE["Next request runs it.<br/>The request IS the check-in."]
D --> Q{"On-device:<br/>where do the weights live?"}
Q -->|"Tier 1: in the app binary"| T1["Store review, then staged<br/>rollout, then user updates"]
Q -->|"Tier 2: fetched at runtime"| T2["Publish artifact; app<br/>checks on next launch"]
Q -->|"Tier 3: flag-gated"| T3["Push config invalidation"]
Q -->|"Tier 4: platform-managed"| T4["No lever. The platform<br/>decides, and does not say when."]
T1 --> GATE{"Is the device reachable in time?<br/>Online; and for flag pushes,<br/>foregrounded"}
T2 --> GATE
T3 --> GATE
GATE -->|Yes| EFFECT["Change takes effect"]
GATE -->|"No: offline, dormant,<br/>or never opened again"| STALE["Still running the old<br/>behaviour. Unbounded."]
style D fill:#4A90E2,color:#FFFFFF
style CLOUD fill:#6BCF7F,color:#2C2C2A
style CDONE fill:#6BCF7F,color:#2C2C2A
style Q fill:#7B68EE,color:#FFFFFF
style T1 fill:#E74C3C,color:#FFFFFF
style T2 fill:#FFA07A,color:#2C2C2A
style T3 fill:#FFD93D,color:#2C2C2A
style T4 fill:#95A5A6,color:#FFFFFF
style GATE fill:#7B68EE,color:#FFFFFF
style EFFECT fill:#98D8C8,color:#2C2C2A
style STALE fill:#C2185B,color:#FFFFFF
Does on-device processing reduce your GDPR and EU AI Act obligations?
Short answer: it changes them, and in at least one respect it makes them harder.
GDPR Article 4(2) defines processing as "any operation or set of operations which is performed on personal data," and then enumerates operations rather than venues. Nothing in that definition turns on whose silicon executes. Article 4(7) makes you a controller if you determine "the purposes and means of the processing," which is a question about who decided what happens, not about where it ran. Ship an app that decides what the local model does, when, and to which data, and you have determined purposes and means. On-device relocates the processing. Controllership stays put.
The counter-position is argued seriously, so it deserves naming: a developer who never receives or accesses the data has a role confined to the determination stage, and cannot meaningfully discharge an Article 15 access request or an Article 17 erasure request against data sitting in someone's pocket. That is true and it does not help you. Being unable to reach the data is an architectural choice you made, not a defence you acquired, and the inability to answer for what your system did is the thesis of this article restated in a legal register.
There is a sharper point in the ePrivacy Directive. The EDPB's Guidelines 2/2023 on the technical scope of Article 5(3) frame applicability around four elements: information, terminal equipment, gaining access, and stored information and storage. Information there covers non-personal as well as personal data, and the guidelines list "certain local processing" among the in-scope techniques. The consent trigger in Article 5(3) attaches to storing or accessing information on the user's terminal equipment, rather than to transmitting it anywhere.
An on-device feature that reads a user's photos or messages to feed a local model is doing the thing that rule regulates. "It never leaves the device" is a defence against a different rule.
There is an exemption, and it matters more than it first appears. Article 5(3) does not require consent where the access is strictly necessary for a service the user explicitly requested. A feature the user actively invokes, asking for this photo to be summarised, is a serious candidate. Background classification the user never asked for is the weakest possible candidate. That is precisely the shape of the service this article opened with, which is the uncomfortable part: the exemption is strongest for the features nobody worries about and absent for the one that scans by default.
I could not read the specific use-case paragraph in Guidelines 2/2023 that sets out when local processing falls in scope, so I am deliberately not stating that condition. The four-element framing and the phrase "certain local processing" are well corroborated. The precise trigger is not something I am willing to paraphrase from secondary sources.
Two more instruments matter, one of them on a clock.
EU AI Act Article 50 became applicable on 2 August 2026, nineteen days before this article was published. Paragraph 2 obliges providers of systems generating synthetic audio, image, video or text to ensure outputs "are marked in a machine-readable format and detectable as artificially generated or manipulated." Where inference runs goes unmentioned, because it does not matter to the obligation. What does matter is where the marking logic lives. Watermarking schemes of the SynthID kind bias token sampling at generation time, so the scheme is code that runs beside the model rather than metadata attached afterwards. A cloud provider whose marking scheme changes updates a service, and every output is compliant within minutes. An on-device provider ships a binary and waits one Revocation Horizon. The AI Office's Code of Practice on transparency of AI-generated content is new and voluntary, which means the scheme is going to move. Article 50 compliance is now a function of your fleet's Revocation Horizon.
Two precisions before you act on that. Article 50(2) carves out systems performing an assistive function for standard editing that do not substantially alter the input, which covers a fair share of on-device features. And the marking duty in 50(2) binds providers, while the deepfake disclosure in 50(4) binds deployers, so which one you are decides what you owe. Article 25 is the sharp edge for anyone shipping on Gemini Nano or Apple's Foundation Models: put your name or trademark on a high-risk system and you become its provider. You can become the provider of a model you cannot pin, version, inspect, or roll back.
Article 12 sets up a structural tension worth seeing early, with a scope caveat that matters. It requires high-risk systems to "technically allow for the automatic recording of events (logs) over the lifetime of the system," to support post-market monitoring and risk identification. On-device inference produces logs on the device, where the provider cannot read them, and Google's AICore documentation states that it isolates each request and "doesn't store any record of the input data or the resulting outputs after processing." A design choice made for privacy directly obstructs a record-keeping duty written for accountability. Any audit-trail machinery that satisfies this obligation server-side assumes the events reach somewhere you control, which is the one assumption on-device inference removes. Article 12 binds high-risk systems only, so this does not touch a consumer photo-summarisation feature today. That tension becomes binding the moment an on-device feature lands in a high-risk category, and by then the architecture has already shipped.
One further reading, offered as an argument rather than a finding. EDPB Opinion 28/2024 holds that a model trained on personal data cannot be assumed anonymous, and sets a two-part test: anonymity requires that both the likelihood of extracting personal data from the model and the likelihood of obtaining it through queries are insignificant. Look at that test through the extraction and query-cost evidence above. Shipping a fine-tuned model inside an app binary distributes it to every device in the fleet and, per the extraction literature, to anyone who unpacks the package. Unlimited offline querying with no rate limit is the most favourable possible condition for the second half of the test. On-device deployment makes the EDPB's anonymity test harder to pass, not easier. The Opinion does not address on-device deployment, so this is my reading applied to a case it does not cover.
The twist: the best privacy engineering of this era went into a data centre
If the argument is that you cannot verify or revoke what runs on hardware you do not control, the strongest evidence is where the industry's most rigorous privacy work actually landed.
Apple's Private Cloud Compute publishes measurements of all code running in production to an append-only, cryptographically tamper-proof transparency log. Once a release is in that log it cannot be removed without detection. Apple also commits to publishing production software images for inspection, provides a Virtual Research Environment that lets outside researchers boot a real release and run inference against it, puts source on GitHub, and extends its Security Bounty to compromises of it.
Now try to name the on-device equivalent. Continuous attestation that the model artifact on the phone is the one you shipped: nothing. An append-only log of what actually ran: the platform explicitly does not keep one, and on AICore it is designed not to. Third-party verification of any of it: nothing.
Two honest qualifications, because the comparison is easy to overstate and I would rather narrow the claim than have it picked apart.
The first is that those properties belong to Apple, not to you. A developer building on Private Cloud Compute gets no transparency log of their own and no revocation control over Apple's models either. The comparison is not cloud beating device; it is a platform vendor's capability against an application developer's, and the developer loses on both sides. The second is that Apple's own architecture argues the other way: Foundation Models run on-device by default and escalate to Private Cloud Compute only when the local model is insufficient. Apple ships on-device first.
That concession does not rescue the developer, and seeing why is the point. The escalation path is Apple's to attest and Apple's to revoke, which is Tier 4 again under a different name. So the claim worth defending is narrower than "the best privacy engineering went to a data centre." It is that these verifiability properties only became constructible once someone controlled the execution environment end to end, and on the phone nobody offers them to you, Apple included. The user's data genuinely stopped travelling. Your ability to prove anything about the system handling it never arrived.
Checklist: shipping an on-device model you can still control
Decisions, ordered by what they cost you when you get them wrong.
- Never bundle weights in the app binary if you can fetch them at runtime. This is the largest available reduction in Revocation Horizon, and it is the one that decouples model version from app version. Note which mechanism actually decouples: Play for On-device AI updates its AI packs with the app binary, so reaching Tier 2 means hosting the artifact yourself. Size ceilings shape the choice, at 1.5 GB compressed per AI pack and 4 GB for the total app.
- Fail closed on policy staleness, with a bound you chose on purpose. An offline device should lose the feature, never the guardrail. If you take one thing from this article into code, take this branch.
- Enforce rate limits on-device as well as server-side. A backend quota counts requests that reach the backend, and local inference produces none.
- Deliver guardrails as signed policy bundles, versioned separately from both the binary and the model. Then a guardrail change does not wait on store review.
- Set
inAppUpdatePriorityat release time to the level you would want if this build turned out to be the one you needed off the fleet. You cannot raise it later, and the day you want to is the day you find that out. That argues for a deliberate non-zero default rather than priority 5 on everything, which users route around and learn to dismiss. - Write
android:dataExtractionRulesto exclude every AI artifact from Auto Backup. Conversation history, prompt logs and cached context ingetFilesDir()or a SQLite database are opted into cloud backup by default. - Emit policy age, policy version, model version and active delegate on every inference. Without the delegate you cannot debug tier-dependent behaviour at all.
- Measure your Revocation Horizon and publish it as a pair, not a number. Aggregate
clientVersionStalenessDaysfor the p95, then state what share of installs it could not see, since that instrument only runs on devices that reached Play. A p95 with no censoring rate beside it is the reassuring half of the answer. Anyone asking how fast you can respond to a model incident needs both halves. - Test on the low tier of your fleet, not the high one. A 4-bit model on a device that fell back to CPU is a different model from the one your red team approved, and instruction-following is among the capabilities quantization damages most.
- Put nothing behind the offline path that you would ever need to revoke. This is the design constraint the other nine items exist to make affordable. Features that must be revocable in minutes belong behind a network boundary, and that means a server.
That last one reads as a retreat and is not. On-device inference is the right call for a large class of workloads, and the privacy gain is real rather than marketing. What it demands is deciding, before you ship, which behaviours you are willing to leave running on a device you cannot reach, for at least as long as your measured p95 says, and for an unbounded time on the share of the fleet that p95 never saw. Answer that honestly and on-device AI is a strong tool. Skip the question and you have not moved your risk anywhere. You have posted it to a few million devices and thrown away the receipt.
References
Papers
- Guyomard, V., Mauvisseau, M., and Paindavoine, M. (2025). Breaking SafetyCore: Exploring the Risks of On-Device AI Deployment. arXiv:2509.06371. https://arxiv.org/abs/2509.06371
- Sun, Z., Sun, R., Lu, L., and Mislove, A. (2020/2021). Mind Your Weight(s): A Large-scale Study on Insufficient Machine Learning Model Protection in Mobile Apps. arXiv:2002.07687. https://arxiv.org/abs/2002.07687
- Huang, Y., Zhang, Z., Zhao, Q., Yuan, X., and Chen, C. (2025). THEMIS: Towards Practical Intellectual Property Protection for Post-Deployment On-Device Deep Learning Models. arXiv:2503.23748. https://arxiv.org/html/2503.23748
- DEMISTIFY: Identifying On-device Machine Learning Models Stealing and Reuse Vulnerabilities in Mobile Apps (2024). IEEE/ACM ICSE 46. https://dl.acm.org/doi/abs/10.1145/3597503.3623325
- Nayan, T., Guo, Q., Al Duniawi, M., Botacin, M., Uluagac, S., and Sun, R. (2024). SoK: All You Need to Know About On-Device ML Model Extraction - The Gap Between Research and Practice. 33rd USENIX Security Symposium. https://www.usenix.org/conference/usenixsecurity24/presentation/nayan
- Tsiatsikas, Z., Fakis, A., Karopoulos, G., Kouliaridis, V., and Anagnostopoulos, M. (2026). Protecting On-Device AI Inference: A Systematic Review of Attacks and Defence Mechanisms. arXiv:2605.29450. https://arxiv.org/abs/2605.29450
- Zou, A., Wang, Z., Carlini, N., Nasr, M., Kolter, J. Z., and Fredrikson, M. (2023). Universal and Transferable Adversarial Attacks on Aligned Language Models. arXiv:2307.15043. https://arxiv.org/abs/2307.15043
- Arditi, A., Obeso, O., Syed, A., Paleka, D., Panickssery, N., Gurnee, W., and Nanda, N. (2024). Refusal in Language Models Is Mediated by a Single Direction. NeurIPS 2024. arXiv:2406.11717. https://arxiv.org/abs/2406.11717
- Chao, P., et al. (2023). Jailbreaking Black Box Large Language Models in Twenty Queries. arXiv:2310.08419. https://arxiv.org/abs/2310.08419
- Mehrotra, A., et al. (2023). Tree of Attacks: Jailbreaking Black-Box LLMs Automatically. arXiv:2312.02119. https://arxiv.org/abs/2312.02119
- CoP: Agentic Red-teaming for Large Language Models using Composition of Principles (2026). arXiv:2506.00781. https://arxiv.org/abs/2506.00781
- Shadow in the Cache: Unveiling and Mitigating Privacy Risks of KV-cache in LLM Inference (2026). NDSS 2026. arXiv:2508.09442. https://www.ndss-symposium.org/ndss-paper/shadow-in-the-cache-unveiling-and-mitigating-privacy-risks-of-kv-cache-in-llm-inference/
- Laskaridis, S., Katevas, K., Minto, L., and Haddadi, H. (2024). MELTing point: Mobile Evaluation of Language Transformers. MobiCom 24. arXiv:2403.12844. https://arxiv.org/abs/2403.12844
- Lee, J., Park, S., Kwon, J., Oh, J., and Kwon, Y. (2024). A Comprehensive Evaluation of Quantized Instruction-Tuned Large Language Models: An Experimental Analysis up to 405B. arXiv:2409.11055. https://arxiv.org/html/2409.11055v1
Regulatory instruments and guidance
- Regulation (EU) 2016/679 (GDPR), Article 4. https://gdpr-info.eu/art-4-gdpr/
- Regulation (EU) 2024/1689 (EU AI Act), Article 50, applicable 2 August 2026. https://artificialintelligenceact.eu/article/50/
- Regulation (EU) 2024/1689 (EU AI Act), Article 12, record-keeping. https://artificialintelligenceact.eu/article/12/
- EDPB. Guidelines 2/2023 on Technical Scope of Art. 5(3) of the ePrivacy Directive, v2.0 (October 2024). https://www.edpb.europa.eu/system/files/2024-10/edpb_guidelines_202302_technical_scope_art_53_eprivacydirective_v2_en_0.pdf
- EDPB. Opinion 28/2024 on certain data protection aspects related to the processing of personal data in the context of AI models (17 December 2024). https://www.edpb.europa.eu/system/files/2024-12/edpb_opinion_202428_ai-models_en.pdf
Platform documentation
- Apple. App Store - Devices and OS Adoption (measured 7 June 2026). https://developer.apple.com/support/app-store/
- Apple Security Research. Private Cloud Compute: A new frontier for AI privacy in the cloud. https://security.apple.com/blog/private-cloud-compute/
- Apple Security Research. Security research on Private Cloud Compute. https://security.apple.com/blog/pcc-security-research/
- Apple Machine Learning Research (8 June 2026). Introducing the Third Generation of Apple's Foundation Models. https://machinelearning.apple.com/research/introducing-third-generation-of-apple-foundation-models
- Android Developers. Support in-app updates. https://developer.android.com/guide/playcore/in-app-updates/kotlin-java
- Android Developers. Neural Networks API Migration Guide. https://developer.android.com/ndk/guides/neuralnetworks/migration-guide
- Android Developers. Gemini Nano. https://developer.android.com/ai/gemini-nano
- Android Developers. AICore. https://developer.android.com/ai/aicore
- Android Developers. Back up user data with Auto Backup. https://developer.android.com/identity/data/autobackup
- Android Developers. Overview of the Play Integrity API. https://developer.android.com/google/play/integrity/overview
- Android Developers. Play Integrity API additional tools (companion-device check). https://developer.android.com/google/play/integrity/additional-tools
- Apple Developer. Foundation Models framework (guardrails). https://developer.apple.com/documentation/foundationmodels
- Android Developers. Play for On-device AI (beta). https://developer.android.com/google/play/on-device-ai
- Google. Understand sensitive content warnings in Google Messages. https://support.google.com/messages/answer/15724426
- Google AI Edge. LiteRT Delegates. https://developers.google.com/edge/litert/performance/delegates
- Firebase. Real-time Remote Config. https://firebase.google.com/docs/remote-config/real-time
- Firebase. Firebase ML (deprecation notice, shutdown 15 June 2027). https://firebase.google.com/docs/ml
Measurement and practitioner sources
- Chandra, V., and Krishnamoorthi, R. (24 January 2026). On-Device LLMs: State of the Union, 2026. https://v-chandra.github.io/on-device-llms/
- StatCounter. Mobile Android Version Market Share Worldwide, July 2026. https://gs.statcounter.com/android-version-market-share/mobile/worldwide
- Bishop Fox. Broken Hill: A Productionized Greedy Coordinate Gradient Attack Tool for LLMs. https://bishopfox.com/tools/broken-hill
- Securing. From .mlmodel to .mlmodelc: How Apple Encrypts and Delivers ML Models. https://www.securing.pl/en/from-mlmodel-to-mlmodelc-how-apple-encrypts-and-delivers-ml-models/
Related Articles
- Building a Production MCP Server: Architecture, Pitfalls, and Best Practices
- Unified Observability Across Agent Fleets: Building the Control Plane Metric Layer
- Compliance, Audit Trails, and Regulatory Requirements for Agentic Systems
- The Agent Trust Problem: Why Security Theater Won't Save Us from Agentic AI



