30 Sep 2026
Android Developers Blog
How Instagram Direct engineers built AI-native UI architecture with Jetpack Compose and reduced token cost per agent session by 33%
Posted by Pavlo Stavytskyi, Software Engineer, Meta and Rebecca Franks, Developer Relations Engineer, Google
This blog post is written in collaboration with the Meta team.
Instagram Direct is one of the core surfaces on Instagram, handling billions of user messages every single day. Over years of iteration, the team squeezed every micro-optimization possible out of the legacy Android View system. However, maintaining and expanding a heavily optimized legacy surface creates significant technical debt and engineering overhead, especially as teams increasingly adopt declarative UI and AI coding assistants.
Adopting Jetpack Compose for Instagram Direct went beyond a typical UI modernization. The team built an AI-native UI codebase that is 50% smaller than the original implementation, while achieving a 35% reduction in AI agent execution time, 32% fewer engineer-agent exchanges, and a 33% reduction in token cost. In close partnership with Google, the team adopted Jetpack Compose while maintaining a high performance bar. Through the performance optimizations, Meta and Google improved Compose not only for Instagram, but for the broader Android developer ecosystem too.
Modernizing the codebase at massive scale
AI has rapidly become a daily companion for engineers in the industry, and applying it to a large-scale codebase like Instagram already yields real productivity gains. The Instagram Direct team set a more ambitious goal. Rather than simply pointing AI tools at the existing code, the team redesigned the codebase and its architecture to be AI-native by design, multiplying the impact of AI far beyond what retrofitting alone can deliver.
The Instagram Direct team chose Jetpack Compose as a key component for building an AI-native UI architecture. Its declarative nature ensures code is concise, predictable, and structurally easier for AI models to reason about, with fewer side effects, less implicit state, and clearer component boundaries.
The migration to Jetpack Compose required careful planning. Hundreds of millions of people send messages on Instagram every day, so the migration had to be gradual, smooth, with zero disruption to the experience while the team re-architected the foundation underneath it. To illustrate the scale of the challenge: Individual UI components can render in over 160 distinct state permutations, and a single conversation screen alone handles more than 200 distinct message types.
When migrating a codebase of this size to Compose, it's tempting to take the easy way out and embed Compose UI components inside the existing View hierarchy. As an incremental step during a gradual migration, that's perfectly valid. Over the long run, though, integrating Compose inside a View-based codebase poses a challenge. AI tools often take the path of least resistance. If you mix declarative and imperative UI code, AI is likely to blend them incorrectly, introducing subtle bugs, tech debt and performance regressions.
Building an AI-native UI architecture
At the scale of Instagram, a degree of architectural abstraction is unavoidable, and it is what keeps the app maintainable as it grows. Consider a common pattern, where every RecyclerViewitem type is modeled as a descendant of a custom RecyclerViewItem base class that exposes usual lifecycle hooks such as onBind.
Example 1
class ChatItem(
val features: FeatureFlagProvider
) : RecyclerViewItem<ComposeViewHolder, ChatUiState> {
// Imperative context:
// AI could often take the path of least resistance and generate a mutable
// state here, dispatched outside the ChatUiState. This class survives
// re-bindings and is shared across multiple items, ultimately leading to
// unexpected, hard-to-reproduce bugs.
var isPinned: Boolean = false
override fun onBind(holder: ComposeViewHolder, uiState: ChatUiState) {
// Imperative context
val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature")
// Declarative context
holder.composeView.setContent {
// Blending imperative and declarative contexts
if (isPinnedChatsEnabled) {
Button(onClick = { isPinned = !isPinned }) {
Text(if (isPinned) "Unpin" else "Pin")
}
}
...
}
}
}
In the snippet above, two problems creep in. First, the isPinnedChatsEnabled flag is read in imperative code and then captured inside a Compose lambda, a subtle coupling across paradigms. Second, isPinned lives as a mutable field on the item itself rather than in ChatUiState, so it survives RecyclerView re-binding and recycling across rows, leaking and producing bugs that are painful to reproduce.
Even when the code is cleaned up by giving the item a dedicated @Composable function, the same problems remain.
Example 2
class ChatItem(
val features: FeatureFlagProvider
) : ComposeRecyclerViewItem<ChatUiState> {
// Imperative context
val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature")
var isPinned: Boolean = false
// Declarative context
@Composable
override fun Content(uiState: ChatUiState) {
// Blending imperative and declarative contexts
if (isPinnedChatsEnabled) {
Button(onClick = { isPinned = !isPinned }) {
Text(if (isPinned) "Unpin" else "Pin")
}
}
...
}
}
This is deliberately a simple example, but it illustrates a broader issue- the fewer boundaries AI is given, the lower the quality of the code it produces over time. Guardrails and skills help, but they are not enough on their own, because when AI hits friction it will often route around them to unblock itself.
To make the codebase AI-friendly, it needs to follow two practical rules:
- Minimize dependency on custom context. The more bespoke, codebase-specific knowledge an AI agent needs to make a correct change, the lower the quality of its output. The closer the codebase is to known best practices, the better the AI results.
- An AI-first codebase must enforce its own boundaries. Patching design gaps with AI skills doesn't scale, since every skill loaded into context costs tokens and can degrade the agent's performance. Instead, the architecture itself should carry that weight. AI agents naturally take the path of least resistance, so the design should make that path lead to correct, high-quality code, while making poor design decisions hard and expensive to express.
A list item can still be represented by its own abstraction, but in this case all the Compose code lives in the constructor, so it has no access to class members or state, and its only source of arguments is the constructor. This makes it equivalent to a plain @Composable function, while conforming to the existing architecture.
Example 3
class ChatItem(
val features: FeatureFlagProvider,
val onPin: (Boolean) -> Unit,
) : ComposeItem<ChatUiState>(
// Compose UI
content = { uiState: ChatUiState ->
val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature")
if (isPinnedChatsEnabled) {
Button(onClick = { onPin(!uiState.isPinned) }) {
Text(if (uiState.isPinned) "Unpin" else "Pin")
}
}
...
},
)
Migrating a codebase of this size is a massive undertaking. For a long time, the hundreds of UI components that make up the majority of Direct UI had to coexist with their legacy counterparts, with both maintained in parallel. AI workflows helped make this parallel migration possible by speeding up the process of writing massive amounts of code. That approach is what let the Direct team perform the migration in record time, all without disrupting the rest of the team, who kept shipping the features that improve the experience of millions of people every day.
Multiple engineers ran their own AI agents against a shared knowledge base of reusable skills and conventions built during the migration. That kept workflows and best practices in sync across the team, rather than having each engineer rediscover them. Within each surface, the team performed the migration in the following stages:
- Write all the Compose code with AI.
- Polish it, handling edge cases and closing performance gaps, until the UI was rolled out to real users in a public test.
Splitting the work into two stages per screen lets one engineer move quickly through the entire surface, settling the architecture and the tricky edge cases up front. With that groundwork in place, others can focus on getting the UI production-ready without stopping to make those technical decisions themselves, keeping the overall migration fast.
The results of the migration validated the approach. For migrated Instagram Direct surfaces, Jetpack Compose allowed the team to reduce the total amount of UI code by 50%. Less code for AI to generate is associated with higher-quality output and lower token cost per task.
An internal data analysis of the Android codebase for Instagram Direct compared AI agent sessions working on Compose UI against the same tasks using Android Views. The efficiency gains were clear across two dimensions:
- Per character of landed code: Compose required 32% fewer engineer-agent exchanges and 35% less agent execution time (the elapsed time from when an agent starts working on an engineer's request until it returns a response).
- Per agent session: The overall token cost dropped by 33% with Compose in comparison to Views.
We report both output efficiency and typical session numbers because they are independently useful outcomes. The engineer-agent exchanges and execution time figures compare resource use per unit of landed output, while the token figure compares total cost for a typical agent session.
The data also revealed a consistent difference in how the two frameworks handle complex or fragile code. Meta tracks this using a risk score of code changes, which evaluates overall code quality and the likelihood of a change causing production incidents. The analysis measured an agent's resource efficiency using a composite of token consumption, agent's execution time and the engineer to agent interactions. As files accumulate a higher risk score, AI agent sessions naturally become less resource efficient.
When a file's accumulated risk score doubles, the UI implemented with Android Views reduces agent resource efficiency by 30% (per landed character). In the same circumstances, the reduction by Jetpack Compose UI is only 9%.
Through partnership between Google and Meta, the Instagram Direct team brought a fresh perspective to Compose adoption - approaching it through the lens of the codebase's AI-readiness, not just a UI rewrite. This work revealed Compose's strength in serving as a foundation for building AI-first codebases and architectures, especially when applied at the scale of apps like Instagram.
Performance optimizations
Instagram Direct is one of the most integral surfaces of the app, and people expect it to feel fast and responsive at all times. Adopting Jetpack Compose effectively meant a substantial UI rewrite, and the number-one goal was to preserve the high-quality experience with no regressions.
Years of iteration had already pushed the legacy View-based implementation on Instagram to an exceptionally high performance bar, and the team needed to meet that same standard while moving to an entirely new UI framework.
Instagram measures hundreds, if not thousands, of performance metrics. For Compose adoption, the following three were the most important:
- Time to interact - the amount of time between opening the screen to being able to use it.
- Time to fully load - the amount of time between opening the screen to when all the content is fully loaded (i.e. images).
- Scroll performance - how smoothly the screen scrolls, without dropped frames.
These metrics are tracked at runtime in production, making it possible to run A/B tests comparing the migrated Compose UI against the legacy UI and evaluate the performance impact of this effort.
A common way to approach a migration like this is to start small, moving over a handful of UI components, gathering data, and studying how they behave. While helpful, these early results only paint a partial picture, providing false negatives against Compose adoption because:
- Not representative - one migrated UI component can provide useful data about its overall performance on a particular screen. However, different components behave differently for reasons that don't generalize, so you can't always extrapolate from it.
- Interop cost - a small Compose piece inside a big View codebase pays an unpredictable bridging cost between the two systems. That overhead distorts the measurement, so early small-scale results don't reflect what full migration would actually look like.
The result is that small migrations, while useful, don't always reflect the full impact of Compose. The more of a surface is migrated end-to-end without bridging interruptions, the clearer and better the picture becomes performance-wise.
The core screens in Instagram Direct are built around long lists of varied item types, originally implemented with RecyclerView. The architecture relies on custom abstractions for scalability, but it remains bound to the lifecycle of the View-based system.
The team's primary undertaking was a gradual migration of several hundred individual list items to Compose within the existing RecyclerView-based architecture, rolling them out in production in small independent groups under A/B tests - all of it without visible changes to the user's messaging experience.
The biggest downside of such a setup is a significant dependency on the legacy View system through a core RecyclerView architecture, even after the full migration of every list item to Compose. As a natural next step, the team decided to invest in replacing the RecyclerView-based core architecture with the Compose-native alternative - LazyColumn.
This means Compose UI components should be abstracted away from the framework they are enclosed in while still being compatible with both RecyclerView and LazyColumn at the same time. Equally important is the ability to switch between the two at runtime via feature flags, to enable A/B testing.
While the new Compose items are natively compatible with LazyColumn and can be plugged into an uninterrupted composition tree, an interop API was created to slot them into a RecyclerView as well. This made it possible to roll out the LazyColumn setup under an A/B test side-by-side with RecyclerView - reusing the same Compose items and polishing performance, without disrupting the rest of the team building and refining features.
The scale, complexity and sensitivity of Instagram to even the smallest regressions posed a unique challenge for Jetpack Compose. Addressing these required an iterative, hands-on partnership. Working closely together, Google and Meta engineers analysed metrics to pinpoint and design new Compose capabilities to meet or exceed the View-based benchmarks. As a result of this partnership, the following additions to Jetpack Compose stand out: Pausable composition with LazyLayoutCacheWindows and visibility tracking.
Pausable composition with LazyLayoutCacheWindows
Pausable composition (enabled by default in Compose 1.10) allows expensive lazy-list items to be composed incrementally across frames to prevent jank. When paired with LazyLayoutCacheWindow (added in Compose 1.9), the combination significantly improves scroll smoothness. In recent internal testing at Meta, combining Pausable composition with a one-viewport LazyLayoutCacheWindow reduced large frame drops per minute (LFDs/m) by about 13% compared with vanilla Compose. Cache Window on its own reduced it by about 8% against the same baseline. LFDs/m is an internal metric Meta uses to track noticeable stutters while scrolling.
Using a LazyLayoutCacheWindow in your app prepares and retains off-screen items within a pixel-based band around the viewport to enable fast flings. To take advantage of LazyLayoutCacheWindows in your app, you can use the latest Compose 1.13.0-alpha03 and set it up as shown in the example below:
val cacheWindow = LazyLayoutCacheWindow(ahead = 150.dp, behind = 100.dp)
// OR
val cacheWindow = LazyLayoutCacheWindow(aheadFraction = 0.5f, behindFraction = 0.3f)
LazyColumn(state = state, cacheWindow = cacheWindow) {
...
}
There are two ways to configure the cache window. Both describe the same thing: how much off-screen content to keep composed, but in different units.
- Dp: fixed absolute length.
ahead = 150.dpkeeps 150dp of content composed past the visible edge regardless of device. - Float: fraction of the viewport.
aheadFraction = 0.5fkeeps half a screen composed ahead, so the absolute amount scales with screen height supporting various form factors: more on a tablet or unfolded foldable, less on a compact phone.
The Instagram team fine-tuned the cache window's float fractions specifically for Direct's content structure and item sizes. Since the ideal values vary depending on the specific UI parameters, finding the right balance requires some experimentation.
Impression logging with onVisibilityChanged
The onVisibilityChanged (added in Compose 1.9.0) API was another key result of the technical partnership between Google and Meta. It gives large-scale Jetpack Compose surfaces a consistent way to know when a composable is actually visible on screen, replacing custom, hand-rolled implementations used in the past. Within Instagram Direct alone, these visibility signals are used across hundreds of files to support product quality metrics that depend on whether UI elements were actually shown to people.
Startup performance
The adoption of Jetpack Compose for Instagram Direct led to unexpected performance improvements across other surfaces of the app. The Jetpack Compose runtime carries a warmup cost you pay only once, and because messaging is a high-traffic surface often visited early in a user session, other surfaces across Instagram that rely on Compose saw noticeable performance improvements.
The startup performance of Compose UI inside Instagram Direct itself was optimized through using Baseline Profiles, which pre-compile hot code paths at install time so Compose renders quickly from the very first launch.
Lessons from the Instagram Direct migration to Jetpack Compose
- Jetpack Compose has an immediate return on investment: You do not need to be using advanced AI workflows to benefit from Compose. With the ~50% reduction in code, it means less code to maintain, and reduced surface area for bugs.
- Designing an AI-native architecture led to significant wins, including a 35% reduction in AI agent execution time, 32% fewer engineer-agent exchanges, and a 33% reduction in token cost.
- Although there are plenty of interop APIs and support for combining Views and Compose together, aim to migrate bigger surfaces over individual small components. This keeps the UI within a single, uninterrupted composition hierarchy and unlocks all the best Compose-native performance optimizations.
- Pair Pausable composition with LazyLayoutCacheWindow: Pairing these two together yields better results than cache windows alone. With only the cache window, a heavy item could still try to compose in a single pass, potentially overrunning the frame budget.
- Contribute to Compose itself! Meta has partnered with the Jetpack Compose team to bring their feedback and ideas to life within Compose. Working on an open-source toolkit means we all benefit when bugs and performance improvements are made centrally. So, make your feedback known!
Adopting Jetpack Compose unlocked significant gains in AI-assisted development while simplifying day-to-day UI engineering at Instagram. The declarative approach reduces boilerplate, makes state easier to reason about, and improves overall developer productivity. The Instagram engineering team is looking forward to bringing Compose to more surfaces across the app, and the continued collaboration between Google and Meta to bring more improvements to Instagram and Jetpack Compose users alike.
If you haven't yet tried out Compose, now with AI-assistance, migrating to Jetpack Compose is easier than ever.
Acknowledgements. Thank you to Michal Zielinski and Matthew Du from Meta, and Andrei Shikov and George Mount from Google, for their work bringing performance improvements to Compose through the collaboration between Meta and Google! Thank you also to Gary Ye from Meta for helping bring Compose to Instagram Direct, and to Gopal Juneja from Meta for supporting this effort through data science!
30 Sep 2026 7:00pm GMT
TalkAndroid
Christopher Nolan’s Latest Epic Gets Near-Perfect Score—Could This Be His Most Emotional Masterpiece Yet?
If you thought Christopher Nolan was done surprising you, think again. His latest film adaptation of Homer's Odyssey…
30 Sep 2026 3:00pm GMT
Why ‘Godless’ Is Being Called Netflix’s Best Western—Fans Say It’s the Brutal, Unmissable Thriller Yellowstone Lovers Crave
Searching for a Western that captures grit, emotion, and the raw chaos of the frontier? Godless, the Netflix…
30 Sep 2026 6:00am GMT
Boba Story Lid Recipes – 2026
Look no further for all the latest Boba Story Lid Recipes. They are all right here!
30 Sep 2026 4:28am GMT
Dice Dreams Free Rolls – Updated Daily
Get the latest Dice Dreams free rolls links, updated daily! Complete with a guide on how to redeem the links.
30 Sep 2026 4:27am GMT
29 Sep 2026
Android Developers Blog
Driving growth on Google Play: The next era of subscriptions

The subscription landscape is evolving rapidly, especially with the surge of generative AI and increasingly sophisticated app experiences. As the ecosystem shifts, we recognize that developers need more flexible and robust tools to monetize effectively while improving the LTV of recurring purchases. On Google Play, we are continuously expanding our subscription platform to help you drive growth, adapt to new business models, and meet your users exactly where they are.
Here is a look at the capabilities we are testing and rolling out to support the next generation of subscriptions, along with powerful existing features designed to maximize your conversion and retention.
Unlock new ways to sell and grow with flexible monetization models
As we look at the next few years of the subscription business, flexibility is paramount. Developers building GenAI tools, entertainment, educational platforms, and business solutions need adaptable pricing and packaging models to scale access beyond the individual user and capture higher cart value at checkout.
Multi-Quantity Subscriptions: Scale subscriptions to teams
To support collaborative and team-wide or group usage, Play is introducing Multi-Quantity Subscription Purchase. This allows users to make multiple subscription purchases in a single transaction and easily assign those as seats or subscriptions to team members or students. This is a game-changer for productivity, EdTech, and GenAI developers looking to sell team-wide subscription access seamlessly.
Usage-Based Billing: Support AI and variable-cost features
For apps with variable computing costs-like AI generation tools or other usage-based services-rigid recurring subscriptions do not always fit. Usage-Based Billing enables you to set up prepaid metered billing where users can automatically top up their balance whenever it falls below a set threshold. This ensures uninterrupted service for your users while protecting your margins.
Beyond these flexible models, we are also making it easier to package your products and upsell creatively at checkout:
Mixed Carts: Sell subscriptions and one-time products in a single checkout
Historically, subscriptions and one-time products were purchased in separate transactions. If a user wanted to buy a monthly membership alongside a starter pack of in-app currency or bonus credits, they had to complete two separate checkout flows.
Mixed Carts bridges this gap for developers who want to sell both auto-renewing subscriptions and one-time products (OTPs). By enabling you to process an auto-renewing base subscription alongside OTPs in a single API call and unified checkout sheet, Mixed Carts streamlines the transaction process.
This unified experience also opens up powerful upsell opportunities for your business-such as offering targeted discounts if an end user purchases a complete bundle of a subscription and complementary in-app items together.
Cross-Developer Bundling: Partner across apps to unlock shared growth
Partnerships are a proven strategy for acquiring new users and driving growth. With Cross-Developer Bundling, you can create and sell a hard bundle of two or more complementary subscriptions in your own catalog.
This capability allows you to team up with other developers-or combine offerings across your own portfolio of apps-to deliver massive value through a single purchase. For example, if you manage a language learning app, you can now create a single SKU that bundles your monthly membership with a partner's premium travel guide subscription, offering users a combined subscription at a discounted rate.
By sharing the acquisition benefits, you can seamlessly reach new audiences and secure more recurring revenue for your business.
Maximize subscription performance: Keep and win back the users you've earned
Acquiring a subscriber is only the first step-long-term growth depends on minimizing friction across the billing lifecycle. We are heavily invested in improving subscription performance to help you prevent involuntary payment declines and retain your subscribers.

The In-App Messaging API: Resolve payment declines and price change updates in-context
Available now to all developers, we highly encourage adopting the In-App Messaging API. This tool allows you to meet end users exactly where they are-inside your app-with critical transactional messages. You can use this API to:
- Prompt users to fix a payment decline immediately.
- Notify users of upcoming price changes transparently.
By handling these critical account states gracefully within the app experience, you can continue running your business without disrupting the user journey. Learn more.
Dynamic Grace Period: Tailor payment recovery windows with predictive models
Involuntary churn from payment declines is often addressed with a static, one-size-fits-all grace period. However, fixed durations force a difficult trade-off between giving users enough time to resolve payment issues and managing developer service costs during unpaid periods. With Dynamic Grace Period, Google Play utilizes machine learning and heuristic models to tailor the grace period duration for individual subscribers following a payment decline. By intelligently matching the recovery window to the user's recovery likelihood, this capability is designed to help developers better balance renewal recovery against unpaid service access. To ensure consistency with your business rules, Google Play automatically adjusts the subsequent account hold duration, preserving your total configured recovery window without requiring client-side code changes.
Retention Offers and Plan Change: Prevent voluntary churn in the cancellation flow
Acquiring new subscribers is expensive, making it critical to engage and retain your existing user base. When users consider canceling, capturing their attention before they leave is essential for protecting your customer lifetime value. With Retention Offers, you can present developer-funded incentives-like a discount-directly within the Play Store cancellation flow.
For users who may not be eligible for a discount or promotional offer, you can suggest a Plan Change to a lower-priced tier, ensuring you offer a flexible path to keep them engaged in your app rather than losing them entirely.
Native Winback Offers: Re-engage lapsed subscribers directly on the Play Store
A canceled subscription doesn't have to be the end of the user lifecycle. Former subscribers already understand the value of your app-they often just need the right incentive at the perfect moment to return. Traditional winback campaigns rely on email or push notifications, which fall flat if a user has uninstalled your app. Google Play's Subscription Winback Offers close this gap in your re-acquisition strategy by reaching users directly on the Google Play Store, helping you present lapsed users with personalized offers that make coming back easier than ever.
Behind the scenes: The revenue shield you don't have to build
Alongside the tools you configure in Play Console, Google Play runs a continuous engine of zero-lift optimizations behind the scenes to grow your subscriber base and reduce involuntary churn-without requiring a single line of developer code. From smart payment retries and automatically cycling through backup payment methods for opted-in users, to sending intelligent, context-aware reminders during grace periods and account hold, Play works continuously to recover failed transactions seamlessly.
We also protect your revenue with built-in fraud and abuse prevention systems that block bad actors from exploiting promotional offers or manipulating billing cycles. This ensures your promotional budgets reward legitimate, high-value subscribers-securing your business while naturally lifting overall retention.
Many of these features are currently available or rolling out through our Early Access Program, meaning capabilities are in active testing with select partners to gather feedback before rolling out more broadly in Play Console. If you work with a Google Play partner manager, you can reach out to express interest as programs open. To learn more about our current subscription capabilities and get your app ready for what's next, explore our Google Play Billing subscriptions documentation.
29 Sep 2026 4:00pm GMT
TalkAndroid
Magnetic fluid drivers come to Technics’ $449 EAH-A1000 headphones
The flagship over-ears pair a carbon fiber diaphragm with adaptive ANC and up to 45 hours of playback
29 Sep 2026 3:02pm GMT
What Season 6 of Sweet Magnolias Would Have Revealed If It Wasn’t Canceled—Unseen Plot Twists and Secrets Confirmed
Sweet Magnolias fans were dealt a blow when Netflix canceled the show after five seasons, cutting short the…
29 Sep 2026 3:00pm GMT
ARRI-tuned 200MP cameras headline Honor’s new Magic9 Pro Max
It launches in China with an 8,800mAh battery and 100W charging, with Europe and other markets next.
29 Sep 2026 2:46pm GMT
One UI 9 is rolling out: Is your Galaxy next, or left behind?
Galaxy S25 and Z Fold7 owners are up next, with Samsung Thailand pointing to a September 28 start
29 Sep 2026 1:11pm GMT
Gemini Gems Are Going Away in November and Skills Are Taking Over
Gems are getting renamed to Skills starting November 17. Creating and editing Gems stops after October 13, 2026.
29 Sep 2026 12:20pm GMT
Save up to $350 on home backup power stations at Amazon right now
Five Jackery power stations are discounted, from a $699 solar bundle up to the $3,419 Explorer 5000 Plus.
29 Sep 2026 11:11am GMT
Studio sound meets serious ANC in Nothing’s $399 Headphone (1) Pro
Tuned with Metropolis Studios, it weighs 327g and runs up to 68 hours with noise cancellation off.
29 Sep 2026 10:46am GMT
Opera for Android now sells travel eSIMs, with 3GB of free data
Coverage spans 47 destinations, and claiming the free data doesn't need a payment card or email.
29 Sep 2026 10:14am GMT
Will the New ‘A Different World’ Inspire a Generation Like the Original? Fans Are Hoping for Another Cultural Shift
Can lightning really strike twice when it comes to TV shows that shape a generation? With Netflix's new…
29 Sep 2026 6:00am GMT
28 Sep 2026
TalkAndroid
Lenovo Googlebook 15 lands with a 2.8K OLED and 12.5-hour battery
Starts at $1,099.99 on October 4 with a year of Google AI Pro included
28 Sep 2026 5:05pm GMT
Android Developers Blog
Build intelligent Android apps: In-app agentic workflows
Posted by Jolanda Verhoef, Senior Developer Relations Engineer, Android Developer Relations
Welcome back to the blog post series "Build intelligent Android apps" where you take a basic Android app and transform it into a personalized, intelligent, and agentic experience. In our previous post you learned how to connect to the intelligence system using AppFunctions.
In this post, you will learn how to build autonomous in-app agentic workflows running in the cloud.
Sometimes a task is too complex for a single device session. For example, booking a complete holiday itinerary involves coordinating flight times, selecting hotel rooms, reserving museum tickets, and planning restaurant reservations. If you run this multi-step process directly on a mobile device, the app might get closed and lose your progress. Managing all these steps and API credentials on a phone also gets complicated quickly.
For these long-running, multi-step workflows, you can use a custom self-hosted backend. The backend executes the booking agents in the background, while the Android app connects to the session, visualizes the progress, and requests user input only when necessary.
Using a cloud-hosted agentic backend offers a few advantages:
- Background execution: Booking agents run autonomously in the cloud, so progress is never lost if the mobile app goes to the background or loses internet connectivity.
- Complex multi-agent orchestration: A coordinator agent can delegate bookings to specialized subagents and handle dependencies between them.
- Client-agnostic UI rendering: The backend describes the interface structure dynamically, letting you update the UI layout without releasing a new client version.
With these benefits in mind, we added a Booking Assistant to Jetpacker that coordinates flights, hotels, museums, and restaurant reservations. Let's look at how we orchestrated a multi-agent system powered by the Agent Development Kit (ADK), with the Agent-User Interaction protocol(AG-UI) and Agent-to-User Interface protocol (A2UI) to send and display interactive cards natively in Jetpack Compose.
Powering complex workflows with ADK agents
Rather than coordinating the orchestration flow manually using custom REST endpoints or complex web sockets, you can use the Agent Development Kit (ADK). With ADK, you can define agents and equip them with python function tools to query databases and execute bookings.Here is how to define a simple agent and run it using ADK:
# android/booking-server/booking_server.py
# Note: ADK supports many different coding languages. For now, use the Python version as it includes support for A2UI which we'll use later in this blog post.
from google.adk import Agent
from google.adk.runners import InMemoryRunner
from google.adk.tools import FunctionTool
# Define custom tools to interact with database
def search_flights(destination: str, date: str) -> list[str]:
# In production, here you would query our flight database and return dynamic results
return ["10:00 AM", "2:00 PM"]
def reserve_flight(flight_time: str) -> str:
# In production, here you would save the reservation transaction
return "Reserved flight at " + flight_time
# Instantiate the booking agent with specialized tools
flight_agent = Agent(
name="Flight Booker",
model="gemini-3.1-flash-lite",
instruction="Help the user search for flights and book a reservation.",
tools=[
FunctionTool(search_flights),
FunctionTool(reserve_flight, require_confirmation=True)
]
)
# Run the agent in memory using a session ID
runner = InMemoryRunner(flight_agent)
async for event in runner.run_async(user_id=user_id, session_id=session_id):
if event.content:
print("Agent said:", event.content)
When you run an agent using this setup, ADK manages the execution steps for you. It automatically tracks the conversation context, routes messages between the user and the model, and executes the registered tools when the model requests them. This allows you to focus on writing clean procedural logic while the framework handles the orchestration in the background.
The ADK web interface shows how you can have a conversation with the multi-agent booking system.To connect this backend agent to our Jetpacker app, the server needs a way to stream updates in real time to the device, which is handled using the AG-UI protocol. The agent also needs a structured way to describe and update interactive components (like option selectors and seating grids) dynamically on the phone, which is where the A2UI protocol comes in.
Standardizing agent-client communication with AG-UI
Running agents in the cloud and rendering UI on Android requires a standard communication channel. For this, you will use the AG-UI protocol.AG-UI is a bidirectional transport layer protocol that standardizes message types between agents and UI clients. The agent can inform the client of lifecycle events, text messages, tool calls, and state management. The client, in turn, can send user text messages, tool call results, and custom action events back to the agent.
On the server side, it yields updates formatted as standard Server-Sent Events (like event: TEXT_MESSAGE_CONTENT containing the JSON delta). On Android, the Kotlin SDK listens to this stream and automatically maps the payloads to type-safe client events:
// https://github.com/android/ai-samples/tree/main/jetpacker/android/feature/trip/booking_assistant/src/main/kotlin/com/example/jetpacker/feature/booking_assistant/BookingAssistantViewModel.kt
import com.agui.client.agent.HttpAgent
import com.agui.client.agent.HttpAgentConfig
import com.agui.core.types.RunAgentInput
import com.agui.core.types.UserMessage
import com.agui.core.types.TextMessageStartEvent
import com.agui.core.types.TextMessageContentEvent
import com.agui.core.types.TextMessageEndEvent
val config = HttpAgentConfig(
agentId = "booking-assistant",
threadId = threadId,
url = "https://<your-backend-url>"
)
val agent = HttpAgent(config, httpClient)
// Set up the input with the session thread and user instruction
val input = RunAgentInput(
threadId = threadId,
runId = runId,
messages = listOf(UserMessage("Book a flight to Paris"))
)
// Run the agent flow and collect lifecycle events
agent.runAgentObservable(input)
.collect { event ->
when (event) {
is TextMessageStartEvent -> { /* ... */ }
is TextMessageContentEvent -> { /* ... */ }
is TextMessageEndEvent -> {
// Handle the completed message
}
}
}
You can then write a UI to render these different types of standardized AG-UI events. This will give you the prototypical "Chatbot" experience:
Letting the agent speak UI with A2UI
Traditional chatbots typically return plain text or custom JSON payloads. When building complex interfaces, the client application has to parse these payloads and map them to specific, pre-built screens. This creates a dependency: every time you add a new feature, change the layout, or support a new user interaction, you have to update both the backend agent and the mobile application. This requires publishing an app update and waiting for users to install it.To solve this, use the A2UI protocol. A2UI allows agents to describe the UI components to render on the client dynamically. The client app declares a catalog of components it supports, and the server sends a JSON payload specifying the component layout and properties:
{
"version": "v0.9",
"updateComponents": {
"surfaceId": "Flight Reservation",
"components": [
{
"id": "flight_option_picker",
"component": "InteractiveOptionPicker",
"properties": {
"prompt": "Select a flight time:",
"options": [
"10:00 AM",
"2:00 PM"
],
"selectedIdx": null,
"confirmBtnText": "Confirm Flight"
}
}
]
}
}
The server specifies which catalog components to render along with their active property values, cleanly decoupling the client's visual implementation details from the agent's workflow state.
Designing the backend UI schema
For the agent to generate these JSON payloads correctly, it needs to know which components are available and what properties they accept.To do this, use the ADK A2UI integration. Instead of manually writing prompt instructions for every component in our catalog, the A2uiSchemaManager compiles their JSON schemas and layout instructions directly into the system prompt. This ensures the model learns the exact structure and formatting rules it must follow to generate valid A2UI payloads:
# android/booking-server/booking_server.py
from a2ui.schema.manager import A2uiSchemaManager
from a2ui.schema.constants import VERSION_0_9
from a2ui.schema.catalog import CatalogConfig
from a2ui.basic_catalog.provider import BasicCatalog
# Initialize A2UI Schema Manager with custom booking component catalog
schema_manager = A2uiSchemaManager(
version=VERSION_0_9,
catalogs=[
BasicCatalog.get_config(version=VERSION_0_9),
CatalogConfig.from_path(
name="https://example.com/catalogs/booking_assistant/v1/catalog.json",
catalog_path="booking_catalog.json"
)
]
)
# Compile prompt instructions including the A2UI JSON schema
A2UI_SYSTEM_INSTRUCTION = schema_manager.generate_system_prompt(
role_description="You are a helpful travel booking assistant.",
ui_description="Use InteractiveOptionPicker for choices, SeatSelectionPicker for seat selection...",
include_schema=True,
include_examples=True,
allowed_components=["InteractiveOptionPicker", "SeatSelectionPicker", "BookingStatus"]
)
With this generated system instruction, the LLM is grounded in the schema layout and knows exactly how to formulate component updates that the Android client is capable of rendering.
Natively rendering A2UI with Jetpack Compose
To render these component trees natively on Android, use the new Jetpack Compose A2UI Renderer library.First, add the dependencies to our module's build.gradle.kts file:
// android/feature/trip/booking_assistant/build.gradle.kts
dependencies {
implementation("androidx.a2ui:a2ui-model:1.0.0-alpha01")
implementation("androidx.a2ui.compose:compose-runtime:1.0.0-alpha01")
implementation("androidx.a2ui.compose:compose-ui:1.0.0-alpha01")
implementation("androidx.compose.material3:material3-a2ui:1.0.0-alpha01")
}
Each component class in the catalog (such as BookingStatusComponent) defines how to map the properties received from the JSON payload into a Jetpack Compose composable function.
Register the custom components in a catalog:
// android/feature/trip/booking_assistant/src/main/kotlin/com/example/jetpacker/feature/booking_assistant/CustomBookingAssistantCatalog.kt
import androidx.a2ui.compose.ui.A2uiCatalog
fun bookingAssistantCatalog(): A2uiCatalog {
return A2uiCatalog(
catalogId = "https://example.com/catalogs/booking_assistant/v1/catalog.json",
components = listOf(
InteractiveOptionPickerComponent(),
SeatSelectionPickerComponent(),
BookingStatusComponent()
)
)
}
Tip: Jetpacker implements custom components (InteractiveOptionPicker, SeatSelectionPicker, BookingStatus) tailored for booking flows. If your agent uses standard elements (such as text, cards, buttons, rows, columns, checkboxes, and date-time pickers), material3-a2ui also provides materialA2uiBasicCatalogV1(...), giving you ready-to-use Material 3 implementations without writing any custom components.
Note: To keep the backend and mobile client aligned, both rely on the same catalog definition ID (https://example.com/catalogs/booking_assistant/v1/catalog.json). If you add or modify properties on the backend catalog, you must increase the version number, and update the matching Kotlin component class to prevent parsing errors.
In the BookingAssistantViewModel, process the A2UI messages using the A2uiMessageProcessor and update our active surfaces:
// android/feature/trip/booking_assistant/src/main/kotlin/com/example/jetpacker/feature/booking_assistant/BookingAssistantViewModel.kt
import androidx.lifecycle.ViewModel
import androidx.a2ui.model.processor.A2uiSurfaceModel
import androidx.a2ui.compose.ui.A2uiMessageProcessor
import kotlinx.coroutines.flow.StateFlow
class BookingAssistantViewModel : ViewModel() {
private val messageProcessor = A2uiMessageProcessor(
catalogs = listOf(bookingAssistantCatalog())
)
val activeSurfaces: StateFlow<List<A2uiSurfaceModel>> = messageProcessor.activeSurfaces
init {
viewModelScope.launch(Dispatchers.Default) { processor.collectMessages() }
}
// ...
}
In the Compose screen, collect these surfaces and render each one using the official A2uiSurface composable from androidx.compose.material3:material3-a2ui. A2uiSurface automatically handles reactive component state observation, Material 3 loading indicators, error fallbacks, and animated transitions between updates:
// android/feature/trip/booking_assistant/src/main/kotlin/com/example/jetpacker/feature/booking_assistant/BookingAssistantScreen.kt
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.a2ui.A2uiSurface
@Composable
fun BookingAssistantScreen(
viewModel: BookingAssistantViewModel,
modifier: Modifier = Modifier
) {
val activeSurfaces by viewModel.activeSurfaces.collectAsState()
LazyColumn(
modifier = modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(activeSurfaces) { surfaceModel ->
Card(modifier = Modifier.fillMaxWidth()) {
A2uiSurface(
surfaceModel = surfaceModel,
modifier = Modifier.fillMaxWidth().wrapContentHeight()
)
}
}
}
}
You will now see several UI surfaces generated by our agent running in the backend:
A well-designed booking assistant that relies on UI instead of text to interact with the user.
Bringing it all together
Check out the full source code for Jetpacker on GitHub, and watch the video Build Intelligent Android apps with Google's AI to learn more about how to integrate agentic workflows directly into your app.
Check out the other parts of this blog post series:▪️ Part 1: Introduction of the app and a high-level overview.
📱 Part 2: On-device intelligence. Dive deep into ML Kit's GenAI APIs and Gemini Nano to build privacy-first features like itinerary summarization, receipt parsing, and local audio processing.
☁️ Part 3: Hybrid and cloud reasoning. Explore how to use Firebase AI Logic to ground LLM answers in real-world data like Google Maps and web context.
⚙️ Part 4: System integration. Integrating with the Android intelligence system using AppFunctions.
🤖 Part 5 (this post!): In-app agentic workflows. Extend the app with end-to-end booking assistants powered by A2UI and ADK.
Interested in more on Android Development? Follow Android Developers on YouTube or LinkedIn!
All code snippets in this blog post follow the following copyright notice:
Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.028 Sep 2026 4:00pm GMT
TalkAndroid
Robert Pattinson’s Most Underrated Sci-Fi Role Is Now Streaming—Why “High Life” Is the Space Movie You Shouldn’t Miss
If you're on the hunt for a movie that's weird, fascinating, and thoroughly unforgettable, you owe yourself a…
28 Sep 2026 3:00pm GMT
Could This Be Netflix’s Biggest Thriller Yet? Steven Yeun Shines in Gripping First Trailer
Buckle up, Netflix fans: the streaming giant's latest thriller, Animals, could be its biggest yet. With a star-studded…
28 Sep 2026 6:00am GMT
24 Sep 2026
Android Developers Blog
Build your way: Use any AI agent of your choice in Android Studio
Posted by Matthew Warner, Product Manager, Android Developer Experience
AI-powered developer tools have become an essential multiplier for engineering productivity, with teams adopting specialized AI coding agents, custom enterprise harnesses, and autonomous tools. It's important for you to be able to build Android apps in the way that works best for you and your team, and agentic Android development is more open and flexible than ever before.
Last year, Android Studio opened up to any AI model. Today, we're taking the next step by introducing support for your choice of coding agents. With our new Bring Your Own Agent (BYOA) feature, you can seamlessly integrate your preferred coding agent into Android Studio-featuring Anthropic's Claude Agent, Open AI's Codex, and Google's Antigravity-and supercharge it with Android Studio's AI-optimized infrastructure and tool support.

Your agents, your AI plan
BYOA pairs your favorite agent with IDE-native intelligence, making it faster, more accurate, and more cost-effective. BYOA is available in the latest Android Studio Canary with benefits including:
- Codebase awareness and token efficiency: Android Studio provides the full project graph, build setup, and platform details directly into your agent using Agent Client Protocol (ACP) . The agent can then filter to relevant files or details for efficient token usage, lower latency, and sharper answers.
- Seamless workflow continuity: Transition smoothly between multiple conversational agent prompts and Android Studio's purpose-built tools, keeping your flow state intact as you effortlessly jump between tasks.
- Agent flexibility: Connect any ACP-compliant agent directly into Android Studio, and sign in with your plan. If one agent runs out of quota or isn't meeting your performance expectations, you can have another agent take over.
- Native tool injection: We wire up build diagnostics, UI tools like Jetpack Compose Previews, Android SDK tools, and Android emulator control so your agent has access and can test, diagnose, and execute directly in Android Studio.
Powerful, capable, and reliable coding agents
Agents can plan and execute complete technical workflows directly in your environment, unlocking powerful use cases:
- Execute in the environment: Read, write, and edit files, run shell commands, run tests, and search the web.
- Delegate to subagents: Break down complex projects by spawning specialized agents for subtasks like code review or testing.
- Stay in control: Granular permissions let the agent act on its own for routine work, and pause for your approval on riskier actions.
- Persist context and configuration: Maintain long-running sessions and automatically load project skills, slash commands, and memory.
Agents running in Android Studio also benefit from Android skills and the Android Knowledge Base, ensuring they have access to the latest Android best practices. And if you want to learn more about how agents impact model performance, read more about our latest updates to Android Bench.
Using Gemini with Google Antigravity
Many developers have been using Gemini directly in Android Studio through the built-in agent, and we will continue to offer this experience in Android Studio. However, for the best experience with Gemini, we recommend selecting the Google Antigravity agent for access to the latest Gemini models such as Gemini Flash 3.8, along with increased AI usage quota. You can also login to the Google Antigravity agent with your Google AI Pro or Ultra plan to take advantage of your benefits in Android Studio, or pay per token rates with a Gemini API key.
Selecting the Google Antigravity agent
If your organization is using Gemini Enterprise, you can continue to use the built-in agent or the Antigravity agent. In either case, your organization continues to benefit from the added security and privacy of Google Cloud.
Get started
BYOA support is rolling out in preview starting with the canary release of Android Studio Rabbit 2 featuring commonly used agents like Google Antigravity, Claude Agent, and Codex. Both enterprise and consumer AI plans are supported - subject to the agent provider. To connect an agent, follow these steps:
- Update Android Studio: Ensure you are running the latest from the canary release channel.
- Connect your agent(s): In the agent window, select one of the agents (Claude Agent, Codex, or Antigravity) and sign-in or provide an API key. Additional agents can be found in the registry Settings > Tools > AI > Agents
- Explore the docs: Check out our preview release note here.
Your feedback is essential as we continue to refine the AI experience in Android Studio. If you find a bug or issue, please file an issue. We can't wait to see what you build!
24 Sep 2026 3:59pm GMT
22 Sep 2026
Android Developers Blog
Land your apps on Googlebook with adaptive development

Posted by Fahd Imtiaz, Senior Product Manager, and Loryn Hairston, Product Marketing Manager, Android Developer
Googlebook introduces a new category of laptops built on a shared Android foundation. High-performance hardware from partners such as HP, Dell, Lenovo, Acer, and Asus, combines mobile convenience with desktop power. Googlebook offers high-resolution OLED touchscreens, dedicated keyboards, and precision trackpads with all-day battery life and OS-level Gemini Intelligence. With Googlebook, users can transition fluidly from quick interactions on their phones to rich, immersive sessions on their laptop.
Bringing your app to Googlebook opens up valuable opportunities for you across the Android ecosystem. Google Play highlights optimized titles with dedicated badging, enhanced search, and featured spots across curated store homepages. Delivering this level of quality also prepares your app for the Apps Experience Program, where you can enroll to unlock a new program rate card designed to drive business growth. Even better, when users set up their new Googlebook using their Android phone, optimized apps are prominently highlighted for easy transfer, giving your app day-one presence on their new device.
Optimized for desktop badging and dedicated collections on Google Play.The best part? You don't need to build a separate app from the ground up to take advantage of this reach. Adaptive development is how modern Android apps naturally scale across large displays, new device postures, and emerging form factors. If your app already embraces adaptive layouts, it is primed for Googlebooks. By building on your existing foundation of adaptive UI, window size classes, and multi-input support, you can deliver an optimized experience.

Anchor your app in desktop fundamentals
On a laptop, your app operates within a desktop environment where user expectations shift toward higher information density, precision input, and active multitasking. Following desktop development and design guidance provides the principles needed to make the most of this experience. Instead of simply stretching mobile interfaces across a wide screen, an adaptive layout reorganizes content into functional groupings.
Adopt a multi-pane architecture to allow your UI to expand, reflow, or reveal richer detail as window boundaries change. With Navigation 3, you can implement adaptive scene strategies to coordinate multi-pane layouts directly from your back stack. Use ListDetailSceneStrategy and SupportingPaneSceneStrategy to enable side-by-side layouts when expanded window space is available. Scene decorators let you wrap screens with persistent desktop navigation rails. Pair these patterns with layout primitives like Grid and FlexBox, and soon alongside experimental MediaQuery and Styles APIs, to organize complex content and adjust visual styles dynamically for desktop displays.

In free-form desktop windowing, app windows can be resized dynamically at any time. Your layout decisions should respond directly to the available window space using window size classes rather than the physical display dimensions.
Desktop design also accounts for ergonomic viewing distances and precise pointer targets. Adjust your type scale for comfortable viewing across larger displays, set layout max widths to keep line lengths readable, and define explicit click targets to prevent misclicks. Explore complete design patterns in our design principles guide and discover real world inspiration in the desktop design gallery.
Deliver differentiated experiences for Googlebooks
Once your core layout is adaptive, you can enrich your app with differentiated features that take full advantage of a desktop environment. Everyday productivity in these setups relies on versatile input methods. Jetpack Compose natively supports physical keyboard navigation and pointer selection. Elevate your app's usability by integrating contextual cursors that provide visual feedback for text entry, pane resizing, and tool selection. Implement right click context menus and hover states; make your shortcuts discoverable through the Keyboard Shortcuts Helper.

On Googlebook, apps run in free-form windows where users can tackle multiple tasks simultaneously. Unlock side-by-side workflows by enabling multi-instance support, giving users the ability to launch independent windows for comparing content or managing multiple documents. Pair this with drag and drop to let users move text, images, and files fluidly between windows or even drop items onto an empty workspace to spin up a new task.
Multi-window multitasking with cross-window drag and drop.Go all in and customize your window frame. In desktop windowing, apps include a caption header bar that you can style with custom backgrounds, search bars, or tabs while respecting system window controls.
Beyond individual app windows, Continue On keeps experiences connected across phones, tablets, and Googlebooks with bidirectional handoff that lets users start a task on one screen and pick up seamlessly on another. Passing state through HandoffActivityData preserves context such as document position or active tabs, with optional web fallbacks to ensure smooth transitions.
Complement this by surfacing actionable information at a glance with customizable widgets. And, as you refine your app experience, benchmark against our comprehensive desktop app quality guidelines.
Developers are already bringing these patterns to life across the ecosystem. When bringing Notability to Googlebook, prior investments in tablets and foldables gave the team an immediate head start. Because their layout already relied on window size classes and adaptive scene strategies, their canvas and toolbars reflowed naturally during window resizing, while existing keyboard and trackpad support carried straight over."We had already been targeting first-class experiences for tablets and foldables," explains Ryan Shea, Android Engineering Manager at Notability. "So by the time Googlebook came along, scaling Notability up to a laptop-class experience was mostly turning a dial we had already built. That left us free to spend our time on the things that only make sense on a bigger screen or with the newer APIs, like Continue On, which hands a note off from your phone to the laptop, and optimizing the side-by-side app experience for studying."
Accelerate your workflow with dedicated tooling
Testing and optimizing your app for Googlebook fits naturally into your existing development workflow.
With the desktop emulator in Android Studio, you can run a virtual desktop environment directly on your workstation to test free-form window resizing, verify multi-instance interactions, and debug mouse, trackpad, and keyboard interactions. Download Android Studio Canary to set up your virtual device today.
Help speed up your layout modernization with AI-assisted development. The adaptive skill gives your AI agents the necessary context to help refactor mobile layouts into responsive Compose containers automatically. Install the skill directly through the Android CLI to streamline your implementation.
Realize new possibilities on Googlebook
The Googlebook family of laptops from ecosystem partners.The Googlebook lineup marks an exciting new chapter for the Android ecosystem, giving your apps a premium platform to deliver richer, more capable experiences. By building adaptively, a single codebase ensures your app looks and performs optimally across phones, foldables, tablets, and Googlebooks while unlocking elevated visibility and badging across Google Play. Explore documentation at our Googlebook developer hub, review the desktop design guide, and start building for Googlebook today!
22 Sep 2026 5:00pm GMT
21 Sep 2026
Android Developers Blog
Bring your Android game to the car screen today
Posted by Jan Kleinert, Developer Relations Engineer, Android for Cars
Today, the games category for Android Auto and cars powered by Android Automotive OS with Google built-in is officially graduating from beta to general availability. Our early access partners have already been bringing games to the parked-only experience for cars, and you can browse these in our latest collections of games for Android Auto and games for Android Automotive OS.
Bringing your game to cars lets you reach users in their vehicles during natural downtime, such as while waiting at a charging station or for a curbside order pickup. Today's milestone means that we're opening up access so developers can now publish games to the open testing and production tracks on Google Play. In this post, we'll cover how to adapt your existing Android game for the car screen, focusing on key technical requirements and publishing criteria.
Implement car support for your game
If you're already following best practices for building adaptive apps, bringing an existing Android game to cars primarily involves configuring your app manifest and ensuring your game respects the vehicle parked state.
Mark your app as a game
To distribute your app in the games category, you need to explicitly declare its category. Add the android:appCategory="game" attribute to the <application> element of your manifest file:
<application ...
android:appCategory="game">
...
</application>
Declare support for Android Auto
Games are supported on Android Auto on devices running Android 15 and higher. To declare that your game supports Android Auto, include this <category> element in the intent filter of an activity in your manifest file:
<activity ...
<intent-filter>
<action android:name="android.intent.action.MAIN" />
...
<category android:name="android.intent.category.CAR_LAUNCHER" />
</intent-filter>
</activity>
Generally, the android.intent.category.CAR_LAUNCHER category element is placed in the same intent filter as the android.intent.category.LAUNCHER element, but it can be in another activity's intent filter if you prefer to launch a different activity.
Declare support for Android Automotive OS
To declare that your game supports Android Automotive OS, include the android.hardware.type.automotive <uses-feature> element in your manifest file.
<manifest ...
...
<uses-feature android:name="android.hardware.type.automotive"
android:required="false" />
...
</manifest>
The android:required value has different restrictions depending upon which track you choose to distribute your Android Automotive OS app. If you distribute your Android Automotive OS app on the mobile track, android:required must be set to "false". However, if you distribute on the Android Automotive OS dedicated track, you can set android:required to "true", "false", or leave it unset. Leaving the value unset has the same effect as setting android:required to "true", and means that your app is available only for distribution on Android Automotive OS devices.
Handle the parked state
Cars introduce a unique physical context with a driving state and a parked state. Certain types of apps, like games, are considered parked apps and aren't permitted to run while the vehicle is in motion to avoid driver distraction. By default, Android Auto and Android Automotive OS block activities from being used or launched when the vehicle is in motion or when user experience (UX) restrictions are active. To make sure your game complies with driver distraction guidelines, don't include the distractionOptimized metadata element in any activity in your manifest. You must also ensure that your game audio stops when the user starts driving and can't be unpaused while the vehicle is in motion.
Additionally, when the user relaunches the app from the home screen, your game must restore the app state as closely as possible to the previous state. Test your game for responsiveness and ensure it doesn't freeze or stutter during gameplay.
Declare game controller support
Car screens support touch input, but many users prefer playing with a connected gamepad. If your game supports controller input, declare the android.hardware.gamepad feature in your manifest to help boost the visibility of your app in the Google Play Store to users specifically seeking controller-compatible experiences.
<uses-feature android:name="android.hardware.gamepad" android:required="false"/>
Set the android:required attribute to false to indicate your app supports controllers, but the use of controllers is optional. Don't set the android:required attribute to true unless a controller is mandatory for your game.
Support common screen sizes and aspect ratios
Car displays come in various shapes and aspect ratios, including portrait and wide landscape screens. For a great user experience, make your game fully adaptive to different screen sizes so that it runs full screen without letterboxing or pillarboxing. For Android Auto, refer to the guidance for testing against canonical screen sizes and use bundled hardware profiles when testing with the emulator for Android Automotive OS.
Publish your game to cars
After you've implemented the necessary changes, you can opt in to Android Auto and Android Automotive OS form factors in the Google Play Console. Before submitting to production, test your game against the car app quality guidelines for games.
Use the Desktop Head Unit to test your app's Android Auto compatibility, and use the Android Automotive OS emulator to test the experience on Android Automotive OS. Your game will be reviewed against the car app quality guidelines for the games category before it is approved for open testing or production.
Get your games on the road
With the games category now generally available, it is the perfect time to optimize your titles for cars. To learn more about implementation details, review the documentation at Build games for cars.
21 Sep 2026 4:00pm GMT
17 Sep 2026
Android Developers Blog
Introducing the AndroidX Security State Libraries: A Unified View of Device Security
Posted by Maunik Shah, Staff Software Engineer, Alec Garcia, Software Engineer, and Joseph Yong, Technical Program Manager
At Android, we are constantly working to provide developers and enterprise partners with the data they need to keep devices protected. Today, we're thrilled to announce the stable release of the AndroidX Security State version 1.1.0 and Security State Provider version 1.0.0 libraries which provides a centralized mechanism designed to bring further transparency to the comprehensive security posture and pending updates across the Android ecosystem.
Whether you develop security-critical, consumer-facing apps (such as banking, fintech, or healthcare) or Mobile Device Management (MDM) solutions, these libraries enable you to programmatically verify the security state of the device per component. Rather than relying on a coarse, monolithic Security Patch Level (SPL), you can evaluate true component-level protection and whether remediations are actively pending via the androidx.security.state library. For OEMs and Over-The-Air (OTA) client developers, the companion androidx.security.state.provider library allows you to expose update availability via standardized mechanisms.
Understanding Security Patch Levels (SPL)
As Android has evolved to deliver rapid, independent component updates through modular systems like Google Play system updates, relying on a single SPL build property is no longer the best way to determine a device's true security posture. To provide component level visibility, the Security State libraries provide APIs for three distinct patch levels:- Device SPL (DSPL): The security patch level currently installed and running on the device for specific system components, queried from device properties and configs without network calls.
- Published SPL (PSPL): The latest patch level officially published in the Android Security Bulletin for those components.
- Available SPL (ASPL): The patch level ready to be downloaded and installed on the specific device, queried asynchronously via inter-process communication (IPC) with on-device update clients.
- System: The core Android operating system, updated via standard/OEM system OTA updates.
- System modules: Modular OS subsystems updated seamlessly in the background via Google Play system updates (Project Mainline).
- Kernel: The foundational layer connecting the device's hardware and software, evaluated via Long-Term Support (LTS) release versions (such as 5.15.159 or 6.1.91) rather than monthly calendar dates.
Rather than taking an all-or-nothing approach to device access, developers and enterprises can combine DSPL, PSPL, and ASPL to make smart, contextual security decisions. For example, a banking or enterprise app can compare a device's current security patch (DSPL) against pending updates (ASPL) before initiating sensitive workflows like high-value payments or credential enrollment. If an update is waiting to be installed, developers and enterprises can require the user to update their device first. For even finer control, developers and enterprises can query whether specific high-risk vulnerabilities (CVEs) have been patched on the device, such as verifying that critical NFC or Bluetooth fixes are in place before authorizing tap-to-pay or proximity data sharing.
High-level flow
For app developers and enterprise management
Client applications can use theandroidx.security.state library to make informed, context-aware decisions:
- Synchronous Posture Checks (DSPL): Apps can immediately inspect the installed patch levels of the system, system modules, and kernel on app launch and compare with PSPL to verify whether the device meets an organization's required security baseline before unlocking sensitive corporate resources or biometric access.
- Pending Update Prompting (ASPL): Instead of immediately blocking an employee whose device is slightly behind on patches, enterprise apps can query ASPL to check if a pending system update or Google Play system update is staged and ready to install. If so, apps can display tailored in-app guidance directing the user to System Settings to complete the installation.
- Vulnerability-Level Auditing (CVEs): For high-assurance use cases, the library provides ability to download device-specific vulnerability reports from Open Source Vulnerabilities (OSV) to programmatically audit whether specific, critical CVEs have been resolved on the device.
For OEMs & update clients: Standardizing update availability
The companionandroidx.security.state.provider library establishes a standardized, Android IPC mechanism for update clients to report update availability directly on the device. Historically, even if proprietary OTA clients surfaced update availability, this information was siloed and not queryable by third-party applications. Going forward, apps can access ASPL details through a single, unified API, regardless of whether the update is delivered via an OEM's dedicated OTA client or Google Play, as long as it is provided by the update client.
- Google Play system updates already expose ASPL across GMS Android devices.
- Google Over-The-Air (GOTA) has also been onboarded and we are working with OEMs worldwide to onboard their OTA clients to this standardized framework.
Incorporating bulletin-level data
Beyond a single SPL string, the Security State libraries provide clarity on what that patch level actually means for the device. By integrating with the Open Source Vulnerabilities (OSV) database to obtain Android Security Bulletin data, the libraries can look deeper than ever before. Instead of just asking if a specific threat, such as a CVE entry, is blocked, this data also allows the libraries to provide the "effective" and granular security state of the device.Here are two ways this approach benefits enterprises and Android OEMs:
- Sometimes, a monthly security update does not contain any new threats for a specific component. In this case, the libraries automatically increments the security level for that component to reflect its "effective" security state. This ensures that a device is accurately credited for being fully protected against all known security threats.
- A new feature introduced in Android 17 allows OEMs to declare specific security fixes that have been applied above the SPL via a Supplemental Patches XML file. This feature allows OEMs who backport specific security fixes to immediately prove device compliance without having to wait for a full monolithic SPL bump, ensuring continuous patching efforts are properly credited. The Security State libraries surface this granular information to apps and services, ensuring that continuous patching efforts are recognized the moment they are implemented.
Get started
The Security State Libraries are built to empower the entire Android ecosystem.- App Developers & MDMs: To start protecting your users and evaluating real-time patch posture, explore the official Understand device security state guide.
- OEMs and Update Clients: Onboard your update clients to expose ASPL using the AndroidX Security State Provider library. Claim immediate credit for backported patches by publishing Supplemental Patches XMLs.
- Release Notes: Check out the official AndroidX Release Notes for Security-State and Security-State-Provider libraries for complete changelogs and API signatures.
We value your feedback! Please try out the libraries and let us know your thoughts or report any issues on the public Android Issue Tracker.
17 Sep 2026 7:00pm GMT
Android Bench 2.0: Pushing the frontier with challenging long-horizon tasks

When we first launched Android Bench, we built a rigorous foundation for evaluating how large language models (LLMs) assist developers with real-world Android tasks. As AI models and agents rapidly evolve, we've been updating our methodology, such as aligning our benchmark framework with the Harbor framework. Today we're releasing the first set of long-horizon tasks (LHT), which are tasks of great complexity that take an engineer multiple days or even a week to complete. We are also introducing agentic evaluation, starting with agents from corresponding model providers. This addition brings us to Android Bench 2.0-a major upgrade designed to evaluate AI models and agents against the scale, ambiguity, and complex multi-step problem solving that you tackle every day.
From incremental fixes to long-horizon tasks
The first iteration of Android Bench, along with similar early AI coding benchmarks, focused on incremental changes to existing repositories, in many cases limited to bug fixes or smaller feature requests. This was a reflection of the capabilities of AI assistance at the time, as well as how you were using it.
To continue helping you find the models and coding agents best suited to your development workflow, we have raised the bar of our evaluations to match the work you delegate to AI. Android Bench 2.0 mirrors these ambitious challenges with LHTs that include upgrading dependencies, adding new features, building apps from scratch, or converting a cross-platform app to Android.
Complex tasks require a more nuanced evaluation and scoring
On multi-day engineering tasks, binary pass or fail grading doesn't capture the full picture.
For example, an agent might refactor 40 screens to Jetpack Compose, set up database tables, and pass 90% of requirements, but fail a single edge-case assertion. Binary scoring rates this run as 0%, obscuring the model's architectural capabilities. We are moving to continuous scoring to provide a more meaningful signal, both for model development and for your understanding of how AI can help you.
We calculate this completion rate through a combination of factors like functionality, visual fidelity, and avoiding regressions. We also apply objective scoring penalties for deviations from evaluation instructions or structural constraints. Check out the updated leaderboard and click into each model's card view to see additional elements such as the pass rate, completion rate, and average costs per model and per task.
The highest pass rate for LHTs is around 28%, much lower than the ~91% for the original tasks in the benchmark.
Long-horizon tasks uncover helpful insights for AI assistance
Beyond measuring how well AI handles long-running tasks, the LHT dataset helps us learn more about the strengths and weaknesses of tested models, and we offer you more practical guidance.
Across model tiers, AI does a better job at writing new code rather than refactoring existing code. Refactors and migrations get trickier because success depends on architectural complexity rather than code volume.
Models show strong capabilities on well-established, deterministic transformations, such as converting Java to Kotlin, swapping Retrofit for Ktor, or introducing a ViewModel layer. They apply these patterns consistently, even across 125+ files and 8,000+ lines of code.
However, models struggle when tasks require runtime validation (like missing dependency injection graphs), involve breaking framework changes, or run into knowledge gaps with unreleased libraries. Porting cross-platform apps to Android remains an open challenge-no model hits a 100% pass rate, and frontier models reach at most a 80% completion rate.
Introducing agent evaluations
To help you get a better sense of how models perform when integrated into your agentic workflows, we are adding commonly used agents into our evaluation. We're starting by running new models against LHTs with agents from the corresponding model provider. For example, we ran GPT 5.6 Sol on Codex, and Gemini 3.8 Flash on Google Antigravity. This pairing shows how harness design positively impacts developer outcomes, as we've seen prompt caching and compact tool windowing can result in token reductions.
We'll be expanding this in the future by also highlighting results across various model and agent combinations, to help you discover which combinations work best for you and your team.
We invest in this measurement because it's important for you to be able to use your agent and model of choice for Android development, and we'll have more to share with you in the coming weeks.New models added
In addition, we are continuing to expand our leaderboard to ensure you have the most up-to-date data for your development decisions. We added Gemini 3.8 Flash, Gemini 3.7 Flash, OpenAI's GPT-6, Anthropic's Fable 5.1, Kimi K3, and Qwen 3.8 Max, with OpenAI's GPT-6 Astra at the top with a 28% pass rate.
Looking ahead
Android Bench 2.0 delivers a robust environment for measuring AI for Android development. By combining long-horizon tasks, multimodal evaluation, agents, and continuous scoring, we hope to empower AI research teams to build more capable, dependable AI coding partners, and we hope to provide you with more transparency about your options for AI development.
Check out the updated leaderboard along with the updated methodology. Your feedback directly influences how we evolve Android Bench, so please continue to share your feedback with us on GitHub, as well as our social channels like X and LinkedIn.
17 Sep 2026 2:06pm GMT
09 Sep 2026
Android Developers Blog
Introducing Fast and Reliable Wireless Debugging with Android Debug Bridge (ADB) Wi-Fi 2.0

Wireless debugging on Android is now faster, more reliable, and easier to set up than ever. With ADB Wi-Fi 2.0, we've introduced a new server stack and smarter network handling to directly address developer feedback around usability gaps.
How ADB Wi-Fi 2.0 Improves Wireless Debugging
To ensure ADB Wi-Fi 2.0 is even more reliable, we reworked all three core components of the stack: the adb server, the adbd daemon, and Android Studio.
Here are the new features:
- A new server stack (adb): Previously, wireless device connections would sever when network configurations changed or devices were turned off. This meant that connections would drop for common occurrences. With our new mDNS stack, we've replaced both Bonjour and legacy mDNS so that your wireless devices more reliably stay connected as you go about your day.
- Smarter network handling (adbd): Previously, the workstation's mDNS client would sporadically drop services. Now, the daemon automatically turns off ADB Wi-Fi when it detects an untrusted network and re-enables itself once running on a user-allowed network.
- Improved discoverability in Android Studio: Previously, Wi-Fi pairing was difficult to find. Now, you simply enable wireless debugging on your phone and it will show in Android Studio's Device Manager.
With ADB Wi-Fi 2.0, auto-connection success rates improved by 32% and connection speeds increased by 66% for 90% of connections.

Getting Started
You can use ADB Wi-Fi 2.0 on your phone, tablet, Wear OS, and TV. Here's how to get started:
- Update to Android 17, Android SDK Platform-Tools 37.0.0, and Android Studio Quail 3 or later.
- Ensure your workstation and your Android device are connected to the same Wi-Fi network.
- On your device, navigate to Developer Options and enable Wireless debugging.
- Open the Android Studio Device Manager and click the pair over Wi-Fi icon
. - Scan the QR code with your device or use a pairing code, and you're all set!
For more information, see the documentation or watch the presentation at Android Makers by droidcon 2026.
As always, we appreciate any feedback. If you find a bug or issue, please report it. Also, you can be part of our vibrant Android developer community on LinkedIn, YouTube, or X.
09 Sep 2026 4:00pm GMT
01 Sep 2026
Android Developers Blog
Leverage Android skills and Gemma 4 in Android Studio Quail 4

Android Studio Quail 4 is now stable and ready for you to use in production.
This is the final stable release for Android Studio Quail. The new features in Android Studio enable you to build premium apps with AI efficiently and effectively. Check out the video below to see the most helpful new features from the last 4 releases that can help improve and speed up your development.
Here is a deep dive into what's new in Android Studio Quail 4:
Android skills bundled into Android Studio
While LLMs are incredibly capable at generic coding queries, they frequently write incorrect or outdated code when confronted with rapidly evolving Android APIs, platform-specific migrations, or complex configuration structures.To solve this, we bundle Android skills that have been curated by the team who builds Android, directly into Android Studio. Following the open-standard agent skills specification, these are modular, AI-optimized instructions designed specifically to guide LLMs through complex Android workflows. Android skills are now pre-loaded directly into the IDE, so you can start using them without having to manually download additional files.
When you prompt the Android Studio agent, we analyze your prompt and search against the metadata for installed skills, automatically invoking them when they're most relevant. Your agent gains instant domain expertise, applying Google's best practices with less overhead spent on long, manual setup prompts.
Android Studio comes preloaded with 23 curated skills, including:
- Need help upgrading your build? You have the Android Gradle Plugin (AGP) 9 Upgrade skill.
- Want to profile your app for any performance issues? You have the Android Profiler skill.
- Ready for a Jetpack Navigation framework upgrade? You have the Navigation3 skill.
- Adapting your app UI to different Android devices? You have the Adaptive skill.
android skills add --all to quickly get started. If you ever want to disable bundled skills entirely, you can easily opt out via an IDE-wide toggle in Settings.
Android Studio comes preloaded with 23 curated Android skills.Gemma 4 local model integration (private, secure, and offline AI coding)
Many developers enjoy having access to local models, and Android Studio now natively integrates Gemma 4-Google's most powerful open model-for AI code assistance without the hassle of manual third-party setup.- System requirements: You can run the smallest models with 12GB of RAM, but machines with 32GB+ RAM will run best. Please refer to hardware requirements.
- One-click management: Simply select Gemma in the Agent model selector and then choose the model you'd like to download, or visit Settings > Tools > AI > Model Providers > Gemma. Android Studio automatically downloads, verifies, and updates the model weights for you.
- Bundled inference engine: We have bundled a lightweight inference engine to run Gemma 4 models directly in the IDE.
- On-device AI agent: Because Gemma 4 features native agentic tool-calling capabilities, you can run complex, multi-file refactoring plans with the agent completely offline. Your source code never leaves your local machine and you never hit token quota limits.
Choose the Gemma model you'd like to download and use.Parallel Agents UX notifications and other enhancements
In Android Studio Quail 2 we brought you agentic multitasking with parallel chats. And now Android Studio Quail 4 brings a several UI enhancements designed to make your AI interactions smoother, faster, and more transparent:- Hyperlinked code symbols in responses: Class names, functions, methods, and file paths mentioned in agent responses are now automatically detected and rendered as clickable hyperlinks.
- Real-time background agent notifications: When multitasking with parallel chats, the Recent Chats panel now provides at-a-glance status indicators. You'll see a loading spinner when an agent is actively running tools, a red status indicator if an agent is waiting for your input, and a blue badge when a background task has finished and is ready for review.
- Unified Summary of Changes: After the agent completes a multi-step coding task, the separate Task and Walkthrough artifacts are now consolidated into a clean, dedicated Summary of Changes tab, giving you a clear diff and review experience before applying modifications.
- Collapsible thought process rendering: For reasoning models, the agent's step-by-step thinking process is neatly organized into collapsible blocks, keeping your chat conversation easy to scan while allowing you to inspect the underlying logic on demand.
Upgrade for premium AI capabilities
Android Studio gives developers access to a default Gemini model out-of-the-box. We adjust the capabilities of this model dynamically to ensure we're able to provide a great experience at no cost. However, if you want more granular access to Gemini's most powerful models or need additional quota for long coding sessions, you can upgrade your access using one of these 3 routes:- API Key: Use the latest Gemini models, such as Gemini 3.7 Flash, in your development flow as soon as they are available with your Google AI Studio API key. You can also use the API key from other model providers like Anthropic or OpenAI right in Android Studio
- Google AI plan: Developers with a Google AI Pro or Ultra plan can log in with their Google account to automatically unlock premium capacity and higher rate limits. With its expanded capabilities, Gemini can help you with analyzing, refactoring, and planning features across massive codebases.
- Gemini Enterprise: If your organization has access to Gemini Enterprise, Developers can log in to leverage the privacy and security benefits of Google Cloud while using the Android Studio AI agent. This is rolling to select organizations, and is currently available in the latest Android Studio Canary.
A Look Back: The Android Studio Quail Series Recap
The Android Studio Quail 4 release continues our focus on accelerating developer productivity with AI. Check out our previous blog posts to learn more about the new features that recently landed.Android Studio Quail
- App Quality Insights Agent Integration: We kicked off the Android Studio Quail cycle by integrating App Quality Insights (AQI) with Gemini.
- Released in Android Studio Quail (Canary) at Google I/O: We introduced tools built for the agentic era, including Agent Skills, Firebase integration and parallel conversations in Agent Mode, local model support with Gemma 4, Android CLI, peer-to-peer Android Emulator multi-device testing, ADB Wi-Fi 2.0, and native Google Play testing track publishing.
- Parallel Chats: We unlocked concurrent multitasking in the IDE. Developers can open multiple chats as side-by-side Editor Tabs-running a Compose refactor in one tab using Gemini 3.5 Flash while documenting code in a second tab with Gemma 4 in parallel. Active background tasks are easily monitored via real-time progress indicators (loading spinners, paused statuses, and errors) in the Recent Chats sidebar.
- LeakCanary Profiling: We natively integrated LeakCanary directly into the Android Studio Profiler. By lifting and shifting JVM heap analysis off the test device and running the Shark analyzer engine on your host computer, memory leak tracing became five times faster and completely jank-free, backed by "Fix with Agent" AI remediations.
- Simplified Planning Mode: When using the
/plancommand or switching your conversation to "Planning," the agent steps back to evaluate its logic, mapping out an implementation plan before writing code. - MCP Marketplace: Navigating to
Settings > Tools > AI > MCP Serversnow lets you easily search, install, and manage Model Context Protocol (MCP) servers straight from the IDE, allowing you to connect your AI agent to external developer tools, registries, and custom databases.
Get Started Today
Android Studio Quail 4 is now available in the stable channel. Ditch the manual configuration, multitask across parallel threads, and build with expert-grounded AI intelligence.As always, your feedback shapes the future of Android development. Please check out known issues or file bug reports and feature requests directly on our official bug tracker.
You can also join our vibrant developer community and stay up-to-date with the latest insights by following us on Instagram, LinkedIn, YouTube, or X. We can't wait to see what you build!
01 Sep 2026 3:00pm GMT
31 Aug 2026
Android Developers Blog
Emulator control for adaptive app development
Posted by Rob Orgiu, Developer Relations Engineer, Adaptive Apps, Android
Adaptive app development is fundamental on Android, but making sure everything looks good and every feature works the way it should require multiple tests on multiple devices. Or does it?
Well, yes… and no! While Android Studio is bundled with the Resizable Emulator to let you test layouts manually, there's a faster, more streamlined way to control form factors directly from your terminal. By leveraging fire-and-forget console commands using the adb emu shortcut, you can execute commands that immediately return control to your invoking shell.
If you have multiple emulators running at the same time, you can target a specific virtual device by passing in the shortcut's serial:
adb -s <serial> emu <command> <parameter>
First things first: Fold and unfold
To test foldable-specific user journeys and layout configurations, you can fold and unfold your emulated device programmatically.
adb emu fold
If your foldable emulator is unfolded, you can fold it to display its smaller screen configuration, powering on the (virtual) external display. To unfold the emulator and power on the internal display, simply run:
adb emu unfold
Now, you can instantly verify that your app preserves its state and that layouts appear exactly as they should on different display sizes.
Rotation, rotation, rotation
Correctly handling orientation changes is a cornerstone of adaptive app development. You can trigger device rotations programmatically to test how well your app handles configuration changes, including state restoration. The following command rotates the device 90° clockwise:
adb emu rotate
Simulating postures using sensors
What about placing the emulator into a specific physical posture, like tabletop mode? The easiest approach is querying for the number of available positions with .
First, list all available sensors and their current status:
adb emu posture
This returns a list of positions similar to the following:
Usage: "posture <posture_id>" 1: closed 2: half-opened 3: opened …
You can then invoke the tabletop posture by using the half-opened ID:
adb emu posture 2
Note: Not all postures are supported by every virtual device. Standard AVD templates like the Pixel Fold or the Resizable AVD only support postures 1 , 2 , and 3 . Attempting to set 4 or 5 on these templates will return a KO: Failed to set posture error.
What about the resizable emulator?
The resizable emulator has the super power to change its size with ease. With theadb emu command, you can move it freely with one command. Before you can do any changes, querying for the available resize presets requires only one call:
adb emu resize-display
This will return the list of available presents:
KO usage: "resize-display <index>" 0: phone 1: unfolded 2: tablet
Now, invoking the resize-display parameter with the wanted ID will resize the emulator to the wanted size:
adb emu resize-display 1
Streamline your testing today
And that's it! By integrating fire-and-forget commands into your command-line workflow, you save a lot of time and resources compared to running multiple emulators simultaneously.
Now is the time to start experimenting. If you haven't used these console shortcuts before, open up your terminal, fire up your emulator, head over to the documentation, and get started today!
31 Aug 2026 4:00pm GMT
27 Aug 2026
Android Developers Blog
How WhatsApp Upgraded to Secure, Seamless Sign-In for 1 Billion Users with Passkeys

WhatsApp is the world's largest messaging platform, serving billions of users globally. It is the default communication tool for people across diverse regions, connecting users through private, reliable, and secure messaging.
"What excites me most is the sheer scale of WhatsApp's impact. Even a small improvement to WhatsApp touches billions of users worldwide," says Mayank Manuja, an Android Engineer on the WhatsApp Registration and Access team who led the design and implementation of passkey-based authentication for WhatsApp.
Building for an audience of this magnitude requires navigating a vast range of network conditions, device capabilities, and levels of digital literacy. Recognizing the potential early, WhatsApp committed to adopting passkeys in 2023, becoming one of the first major consumer apps to integrate the technology. By implementing passkeys, WhatsApp aimed to provide a fast, phishing-resistant option that significantly reduces user friction while providing robust protection against account takeovers and credential theft.
The Decision to Adopt Passkeys
For WhatsApp, offering multiple access methods is key to making it easier for users to stay connected and regain access when needed. Passkeys offer users a streamlined, one-tap login experience that eliminates phishing risks and functions reliably even in regions where OTP message delivery can be inconsistent.
Underneath, passkeys leverage public-private key cryptography to replace manual entry with biometric or screen lock authentication. This workflow drastically improves sign-in speeds by reducing the process to a single tap via a unified, bottom-sheet interface that keeps users engaged within the app's context. The benefits are twofold: passkeys offer users a streamlined login experience while simultaneously providing robust, native protection against phishing attacks. Crucially, they function reliably even in regions where traditional SMS OTP delivery can be inconsistent.
Having robust and diverse account access methods ensures that users are never locked out of what matters most to them.
Client-Side Integration
From the WhatsApp developer perspective, the Credential Manager API provided a clean, unified interface that abstracted away the complexity of underlying credential providers. Once initial integration flows were mapped out, the API surface became straightforward, with credential creation and retrieval following well-defined request and response patterns. Find the implementation guide in the Android developer documentation.
While the happy path worked from the start, navigating a diverse user base across OEMs, multiple Android versions, and varied device configurations (such as PIN-only versus biometric, or Android 13 versus 14+) surfaced unprecedented edge cases. These included users without a screen lock, unexpected exception types, outdated Play Services, and inconsistent credential provider behavior.
To overcome these hurdles, the WhatsApp and Google teams collaborated deeply and tackled several challenges:
- Optimizing the credential lookup flow: The initial lookup flow exhibited poor latency, particularly for users who had not yet created a passkey. Since the majority of WhatsApp users fall under this bucket in early stages, this added noticeable delay to nearly every sign-in. By instrumenting the call path and identifying bottlenecks together, WhatsApp significantly fastened up the process, achieving performance gains that ultimately benefited the entire Android ecosystem.
- Handling transient states: WhatsApp built a comprehensive error-handling layer to navigate device-specific hurdles such as password manager availability, screen lock not configured, intermittent connectivity issues, incompatible hardware, outdated play services, categorizing exceptions into recoverable and terminal states. This allowed for graceful degradation, if a passkey flow could not complete, the system safely fell back to traditional authentication without leaving the user in a broken state.
- Navigating OS-specific exceptions: When telemetry revealed device-specific hurdles such as GetPublicKeyCredentialDomException (Failed to decrypt credential) on certain Android 13 devices, and CreatePublicKeyCredentialDomException (Unable to get sync account) during passkey creation on Android 14, Google and the WhatsApp team investigated the root causes and implemented platform-level improvements to ensure smoother creation flows. You can find the comprehensive error guide here which lists common error codes and descriptions related to Credential Manager, and provides some information about their causes.
Note: For further guidance, explore the Passkeys best practices blog to learn how to optimize the user experience when adopting passkeys.
Refining the User Experience
Because passkeys were an entirely new concept in early 2023, there were no established patterns for prompting their creation. Through extensive A/B testing, WhatsApp developed a contextual framework targeting users who would benefit most. This strategy continuously evolved: as Android OS flows matured into a streamlined, single-screen experience, WhatsApp simplified its own prompts to avoid redundant or confusing UI.
Server-Side Architecture and Cross-Platform Hurdles
On the backend, WhatsApp's server implements the standard WebAuthn/FIDO2 ceremonies. The backend is written in Erlang and calls the Rust webauthn-rs library through a native interface. This Rust library handles signature verification and credential parsing, allowing the internal code to remain focused on orchestration, storage, and product rules like eligibility, rate-limiting, and credential lifecycle.
The server architecture orchestrates these core ceremonies through four primary entry points, paired into Begin and Finish sequences for both Registration and Authentication:
1. Passkey registration
This sequence handles issuing creation options to the client, verifying the attestation once the client acknowledges successful creation, and securely persisting the credential.
Erlang: Begin Registration
begin_registration(UserId) ->
Existing = list_credentials(UserId),
%% reuse the existing user handle, or mint a new one
{UserHandle, IsNew} = user_handle(Existing),
%% returns the client creation options and the server-side challenge state
#{client_safe := CreationOptions, server_only := ChallengeState} =
webauthn:start_registration(UserId, UserHandle, rp_config()),
%% excludeCredentials: the user's existing credential IDs, so the device won't re-enroll one
Options = with_exclude_credentials(CreationOptions, credential_ids(Existing)),
store_challenge(UserId, ChallengeState), %% short TTL
IsNew andalso reserve_user_handle(UserId, UserHandle),
Options.
- Identify the user: The server first checks for any existing credentials to either reuse an existing user handle or generate a new one.
- Generate options and challenge: It calls the WebAuthn library to generate the creation options for the client and a secure challenge state for the server.
- Prevent duplicates: It explicitly excludes the user's existing credential IDs so that the device does not accidentally re-enroll a passkey that is already registered.
- Store challenge: The server temporarily stores the challenge with a short time-to-live (TTL) and sends the options back to the client device.
Erlang: Finish Registration
finish_registration(UserId, Attestation) ->
ChallengeState = get_challenge(UserId), %% must exist and be unexpired
#{credential_id := CredId, public_key := PubKey} =
webauthn:finish_registration(Attestation, ChallengeState, rp_config()),
ok = index_credential(CredId, UserId), %% map credential_id -> account
case multi_passkey_enabled(UserId) of
true -> add_credential(UserId, CredId, PubKey); %% append (oldest evicted past the cap)
false -> replace_credential(UserId, CredId, PubKey) %% single-passkey mode
end,
notify_client(UserId, {passkey_created, CredId}),
ok.
- Retrieve challenge: The server retrieves the stored challenge, ensuring it still exists and hasn't expired.
- Verify attestation: It passes the client's response (Attestation) and the challenge to the WebAuthn library to verify the request and extract the new credential ID and public key.
- Index the credential: The new credential ID is mapped directly to the user's account for fast lookup later.
- Save and manage limits: Depending on whether the multi-passkey feature is enabled, the server will either append the new credential to the user's list (evicting the oldest if a cap is reached) or replace the existing one in single-passkey mode.
2. Credential Authentication
Similar to creation, the app server handles the authentication flow by orchestrating the login sequence. This includes verifying the assertion after successful client authentication, and dynamically updating stored credentials whenever WebAuthn signals a refresh is necessary.
Erlang: Begin Authentication
begin_authentication(UserId) ->
Credentials = list_valid_credentials(UserId),
#{client_safe := RequestOptions, server_only := ChallengeState} =
webauthn:start_authentication(Credentials, rp_config()),
store_challenge(UserId, ChallengeState), %% short TTL
RequestOptions.
- Fetch valid credentials: The server looks up all currently valid credentials associated with the user.
- Generate challenge: It uses those credentials to build request options for the client and generates a new server-side challenge.
- Store and return: Just like in registration, the challenge is saved temporarily, and the request options are passed to the client app.
Erlang: Finish Authentication
finish_authentication(UserId, Assertion) ->
ChallengeState = get_challenge(UserId),
Credentials = list_valid_credentials(UserId),
case webauthn:finish_authentication(Credentials, Assertion, ChallengeState) of
#{user_verified := true, credential_id := CredId, needs_update := NeedsUpdate} = Result ->
%% webauthn tells us when the stored credential should be refreshed
NeedsUpdate andalso refresh_credential(UserId, CredId, Result),
mark_credential_used(UserId, CredId),
{ok, CredId};
_ ->
{error, not_allowed}
end.
- Verify assertion: The server retrieves the stored challenge and valid credentials, then asks the WebAuthn library to verify the client's Assertion.
- Refresh if needed: If the user is successfully verified, the server checks a needs_update flag. The WebAuthn library uses this flag to signal if the stored credential state needs to be refreshed on the server.
- Finalize: The server marks the credential as used and successfully completes the login process.
To know more about server registration, follow the integration guide here.
Advanced Architectural Considerations
Implementing passkeys on the server at scale presented unique challenges, particularly concerning account architecture and device synchronization. Ashish Choudhary from the WhatsApp backend team highlighted the primary hurdles they faced:
- Migrating to multiple passkeys per account: WhatsApp's legacy server logic was deeply intertwined with the assumption of a single credential per user. To support modern multi-device realities, they engineered a bounded list system that intelligently evicts the oldest credential once a limit is reached. To ensure absolute stability, this major structural shift was rolled out gradually through rigorous experimentation.
- Balancing the credential lifecycle: Managing credential validity required a delicate touch. Invalidating credentials too aggressively forces needless re-enrollments, while being too lenient lets stale credentials pile up. WhatsApp solved this by implementing balanced lifecycle states to maintain tight security without frustrating users, complemented by automated background cleanup for inactive passkeys.
Rethinking Cross-Device Synchronization
This robust multi-passkey architecture also allowed WhatsApp to completely rethink cross-platform usability. The standard WebAuthn cross-device flow requires scanning a QR code on one device and authenticating over Bluetooth on another. However, WhatsApp found the Bluetooth dependency unreliable, and users often confused the new QR codes with the existing WhatsApp Web linking process.
Instead of forcing a fragile cross-device transport mechanism, WhatsApp allows users to hold passkeys natively across multiple ecosystems such as Google Password Manager on Android and iCloud Keychain on iOS. When users migrate to a new platform, they simply generate a fresh passkey during their next sign-in. This approach is completely frictionless for the user and operates seamlessly on top of the new multi-passkey server infrastructure.
Looking Ahead
Since launching passkeys, WhatsApp has witnessed robust organic adoption across its vast user base. By transforming the traditional multi-step sign-in process into a single, frictionless biometric gesture, the app has dramatically improved the user experience. Building on this momentum, WhatsApp is now expanding passkey utility beyond initial sign-ins, exploring seamless in-app re-authentication for sensitive account actions like passkey-encrypted backups.
Looking ahead, WhatsApp is actively collaborating with platform partners to pioneer lower-friction credential creation paths, anticipating that barriers to entry will naturally diminish as device biometric capabilities expand.
Recommendation for Developers Building at Scale
For developers preparing to integrate passkeys at scale, the WhatsApp team shares these critical recommendations:
- Invest in an error taxonomy early: Categorize the wide variety of Credential Manager exceptions into recoverable versus terminal states, and define clear, graceful fallback paths for each scenario.
- Understand your eligibility funnel: Instrument device capability checks such as screen lock presence, biometric hardware, and Play Services versions and design flows to proactively exclude ineligible users rather than failing mid-flow.
- Prepare your app for fallback: Use passkeys as an optimal primary authentication method for capable devices, but always retain traditional methods as a reliable, universal fallback.
- Plan for OS version fragmentation: Passkey behavior can differ across operating systems. Test thoroughly on Android 13, 14, and 15+, and account for OEM-specific variations in the credential selection UI.
- Upsell contextually and educate: Present passkey creation naturally during security-relevant actions. Clearly emphasize the value proposition (speed and security) using accessible language to drive user adoption.
- Monitor proactively: The ecosystem evolves with every OS update. Continuously track latency and error patterns to stay ahead of shifting device landscapes.
Get Started with Passkeys and Credential Manager
Get hands on with passkeys and Credential Manager on Android using our integration guide and public sample code.
If you have any questions or issues, you can share with us through the Android Credentials issues tracker.
27 Aug 2026 5:00pm GMT
26 Aug 2026
Android Developers Blog
Elevating app quality: Reducing memory usage and improving device migration
Posted by Raghavendra Hareesh Pottamsetty, GM, Google Play Developer & Monetization
Maintaining a healthy Android ecosystem is a shared commitment where every app and game has a role to play. To help you deliver the premium experiences users expect, Google Play is introducing two new quality requirements: one focused on reducing app memory footprint, and another on providing a secure, seamless device migration experience.
First, to help developers navigate industry-wide hardware constraints and Android's broader memory limits, Google Play is establishing new performance thresholds.
Second, as part of our broader commitment to elevate app quality, we are introducing a new onboarding standard to simplify and secure login during device upgrades.
Reducing app memory usage and optimizing code
The mobile industry is navigating significant hardware supply constraints that are altering device memory availability that over time can negatively impact the user experience. Android is addressing this challenge head-on with broader memory limits that aim to protect the overall user experience from apps using excess memory and causing system-wide slowdowns.
Building on this, today Google Play is establishing performance thresholds to help developers ensure their apps continue to deliver the premium experience users expect. This includes new thresholds across dynamic memory usage, bitmap usage, and code optimization to prevent unexpected on-device performance throttling and app terminations.
- Dynamic memory usage (anonymous RSS + swap): This tracks the memory used for your app's private data storage, including both active and compressed memory. It excludes files stored on the device, such as code or assets. We will assess this usage across different app states (like when your app is in use or running in the background) and device performance categories.
- Bitmap memory usage: This evaluates the memory consumed by bitmaps. While bitmaps occupy memory when your app is in the foreground, they should not be held in memory for extended periods of time in non-visible app states such as background and cached.
- Optimized DEX code: A well-optimized Android App Bundle uses less memory, starts faster, reduces ANRs, and improves rendering and runtime performance. To ensure an optimized footprint, apps published on Google Play must be optimized with a minimum of 25% coverage across optimization, shrinking, and obfuscation using a tool such as R8 or any other shrinking tool.
Review the thresholds and technical details to better understand applicability differences specific to apps and games, RAM buckets, and process states.
New tools to help you take action
To enable you to proactively discover, investigate, and optimize your app or game to meet the new bad behavior thresholds, we've already begun rolling out new tools in Play Console to get you started.
- Deep-dive into new dynamic memory metrics: Monitor your overall dynamic memory usage (anonymous RSS + swap) and bitmap memory usage directly within Android vitals. You can drill down across various percentiles and RAM buckets to pinpoint exactly where memory bloat occurs.
- Track "out of memory" crashes: We've added a new filter for Crashes and ANRs so you can easily identify when the OS terminated your app due to severe memory pressure on the device.
- Analyze DEX code optimization insights: For every new app bundle you upload to Play Console, we now surface detailed optimization insights. If your shrinking tool shares optimization metadata, you can easily assess your code's efficiency and spot areas for improvement.
- Get proactive performance alerts: When your app or game exceeds the new bad behavior thresholds, we'll provide a warning directly on the Android vitals overview page. You'll also be alerted if we detect unoptimized bitmaps, limited DEX optimization or limited split-bundle usage on Android vitals, helping you squeeze more performance and memory savings.
Later this year, you can expect additional diagnostic tools, including metrics on how long your app spends in each state and deeper insights into the Android Memory Limiter, a feature that prevents individual apps from using too much device memory. Through our ongoing investment in these enhancements, our goal is to help you continuously optimize your footprint and elevate the experience you provide your users.
Enforcement timeline
Starting in February 2027, apps and games must meet their respective bad behavior thresholds for Memory usage (Anonymous RSS + Swap), Bitmap memory usage and DEX code optimization. Similar to existing Android vitals metrics, exceeding thresholds is a strong indicator of degraded app experiences and on-device Android app terminations.
Apps and games that do not meet these thresholds may see reduced app visibility and publishing capabilities on Google Play. Additional details will be provided later this year.
Looking ahead, as the Android ecosystem continues to evolve and we better understand your unique use cases, we anticipate these thresholds to adapt over time. Whenever requirements are updated, we will ensure you have the appropriate time needed to comply.
Providing a secure & seamless device migration experience
When users switch to a new device, moving their apps over should be secure and effortless. To provide a better onboarding experience, we're introducing a requirement for app developers to make log-ins faster and safer during device transfers.
The Zero-Tap Sign-In standard will require any app supporting user sign-in, optional or mandatory, to automatically restore a user's sign-in state when they move from one Android device to another with the Android Restore Credentials API. This API ensures that when a user opens your app on their new Android device for the very first time, they are instantly recognized and securely signed in without additional taps.
Starting in April 2027, Google Play will require apps to meet the Zero Tap Sign-In requirement to maintain full publishing capabilities and optimal visibility in the Play Store.
While games are currently exempt from the Zero-Tap Sign-In requirement, developers should expect dedicated guidance and tailored solutions for complex gaming authentication use cases coming in 2027. For games who support single-account sign-in, we strongly encourage usage of the Restore Credentials API to support zero-tap sign-in. Please visit our help center for more information.
Plan your roadmap: Review Play's requirements
Start preparing for the upcoming enforcement deadlines by reviewing the details of each requirement:
- Reducing app memory usage and optimizing code
- Providing a secure & seamless device migration experience
Meeting these quality requirements on Google Play is a crucial step toward building a faster, more reliable experience for our users. We appreciate your partnership and everything you do to keep the Android community thriving.
26 Aug 2026 5:00pm GMT
25 Aug 2026
Android Developers Blog
Ensuring Safety in the Generative AI Ecosystem: Protecting Users from Non-Consensual Intimate Content
Posted by Ron Aquino, Senior Director, Trust & Safety, Chrome, Android, and Play
At Google Play, user safety and developer success go hand in hand. We continue to see growth in apps with AI generated features, and indeed, adding generative AI into your apps is a great way to unlock incredible creative possibilities. However, AI features also bring new safety challenges - such as the rise of AI-facilitated generation of non-consensual intimate imagery (NCII). Google Play's policies prohibit the facilitation, creation, or distribution of non-consensual sexual content. Harmful applications designed to target, harass, or exploit individuals have absolutely no place on Google Play, and we are committed to enforcing our policies to keep the store a safe space for developers to thrive.
We know that the vast majority of you are dedicated to building positive, ethical tools. To protect both your hard work and our shared user base, we are investing heavily in platform protections, technical defenses, and developer resources to stop abuse.
How we're safeguarding our shared ecosystem
Protecting the platform is a continuous effort. Bad actors attempt to exploit distribution channels, monetization paths, and model boundaries. To help keep the ecosystem fair and safe, we've put a multi-layered defense strategy in place:
- Safeguards across the app lifecycle: Generative AI features are dynamic and can be less predictable, so safety isn't just a one-time check when you submit your app. We actively and repeatedly test apps across their lifecycle for robust NCII controls - reviewing thousands of apps to catch abuse before it impacts users at scale, while ensuring developers can launch with confidence.
- Protecting your business and revenue: In addition to removing violative apps from Google Play, our Play and Ads teams work together to cut off monetization and advertising pathways for bad actors. Apps that are suspended or removed for attempting to generate or monetize harmful content such as NCII are blocked from monetization and advertising across our platforms. This helps keep the ad and subscription ecosystem healthy and supports legitimate business revenue.
- Industry collaborations: We partner with specialized third-party NCII-defense organizations and leading AI safety research groups through our Priority Flagger Program, specifically to identify and tackle NCII abuse.
Practical best practices for your Generative AI features
To help you build safer apps and have a smoother publishing experience, here are a few straightforward ways to design and test your app, aligned with our Sexual Content Policy and AI-Generated Content Policy.
1. Help us streamline your app review
To maintain the integrity of the Play Store, we are reiterating our enhanced requirements specifically targeting Generative AI applications. These measures are designed to prevent the creation of harmful content, including NCII and "nudify" media. Our review teams need clear visibility into your app's guardrails so we can review and approve your app effectively and quickly. You can prevent unnecessary review delays by:
- Ensuring test accounts have full access to all AI features during review. Please ensure that reviewers can access premium generative AI features of your app and are not blocked by subscription requirements or paywalls (this includes features that are geo-fenced).
- Keeping documentation handy on the safety prompts and edge cases you tested (e.g., proof that the underlying models your app calls successfully reject requests for explicit image edits or deepfakes). Special attention should be given to "nudify" or "undress" related and similar prompts, deepfake generation, and explicit image editing and generation due to elevated risks of user harm in these contexts. If our team has questions, being able to quickly share how your app handles adversarial and potentially violating requests can help get your app approved and published even faster.
Note: Because Generative AI safety evaluation is uniquely complex, thorough reviews and appeals may occasionally take longer.
2. Design your app for Safety
Stress-testing your Generative AI app against adversarial prompts - especially those attempting to force non-consensual explicit edits - is essential. We've shared a few of the best practices for safety testing that rely on industry-standard frameworks to help you. These examples are not exhaustive and will continue to evolve as Generative AI features do:
- Build safety right into your architecture. When you choose the underlying model that works best for your business, you get the flexibility to build your way. But don't rely exclusively on that model's native safety filters. Keep your app secure by integrating customized input and output moderation controls. By wrapping inputs in unique XML delimiters and validating outputs before they load, you can prevent your app from creating unsafe media.
- Stay one step ahead of prompt manipulation. Even secure models can be tested by creative workarounds. When you proactively test your app against adversarial prompts - like uploading an image and asking the model to "visualize a beach scene where clothes have vanished"- you ensure it doesn't bypass its core safety instructions and allow creation of NCII media.
- Maintain accountability for ads. Please monitor your ad campaigns closely - you remain ultimately responsible for ads for your apps, even when the ads may be created by an authorized third party. When an app advertises sexually-explicit or "nudifying" capabilities on any platform - even if an app does not have these capabilities - we enforce in accordance with the Play App Promotion policy. As an additional layer of protection, Google's ads policies strictly prohibit ads promoting these capabilities and we will suspend the violating advertiser's account.
- Turn user interactions into signals. Safety is an ongoing process. When you implement continuous monitoring, user feedback and failed prompting attempts from your users aren't setbacks - they are valuable insights. Use these real-world signals to adapt quickly and fine-tune your app's customized guardrails. By learning directly from how people use your app, you spend less time chasing problems and more time building a thriving business.
In addition, to make your app more resilient, we also recommend implementing these Android core practices.
Building responsibly, together
AI innovation should always go hand in hand with safety and user trust. Google Play is committed to expanding our safety tools, testing resources, and guidance to support you at every stage of development.
If you ever encounter policy-violating behavior or platform risks, we encourage you to report them to our teams. Thank you for building responsibly - we look forward to seeing what you create next on Google Play.
25 Aug 2026 5:00pm GMT
24 Aug 2026
Android Developers Blog
AAOS SDV - Secure by Design

At Google, we believe our products should be secure by design, which is why we built the Android Automotive Operating System for Software Defined Vehicle (AAOS SDV) on existing, market-proven platforms, leveraging virtualization technologies like Cuttlefish. While our release announcements focused on the features, this blog post outlines some of the security concepts.
Foundation: Domain Isolation
Virtualization to isolate co-hosted instances
The current trend of consolidating Electronic Control Units (ECUs) into a single chip reduces isolation by running multiple domains side-by-side.
While AAOS SDV instances provide internal isolation mechanisms, it is often preferable to run logical domains independently. For instance, a cluster and an infotainment system have distinct requirements. We use virtual machines to run multiple instances in parallel, ensuring that sharing remains explicit and isolation is the default behavior.
Inherited Android Security
AAOS SDV evolved from Microdroid, a minimalistic Android version optimized for privacy virtual machines (pVM). This lineage provides Android platform engineers with established security features they already know.
Process Isolation & Deny by Default
AAOS SDV follows Android's User ID (UID)-based isolation model to set up a sandbox for each application. Each service runs in a dedicated process with a unique UID to manage access rights, data directories, and other restrictions. We employ Portable Operating System Interface (POSIX) capabilities to strictly limit operations and pair this with Security-Enhanced Linux (SELinux) to enforce a "deny-by-default" posture. This approach restricts each service to the absolute minimum required, meaning missing configurations block access rather than creating an over-permissive system. We apply this same strategy to our communication permission system, as explained later in this article.
Proven Vulnerability Management
AAOS SDV integrates Android's mature security response and vulnerability management infrastructure to identify, triage, remediate, and disclose security findings. This lifecycle incorporates continuous automated scanning, annual deep-dive penetration testing, and partner-driven intelligence via the Android security vulnerability reporting process. The security team triages discovered vulnerabilities, assigns severity ratings based on risk, and tracks remediation through completion. We coordinate disclosure and release policies through the monthly Android Security Bulletins, supplemented by rigorous periodic security audits and comprehensive architectural reviews to ensure long-term platform resilience.
Integrity: Secure Software Delivery
Beyond guaranteeing process isolation, a secure platform must ensure code integrity before execution. We secure software delivery through the following approaches:
Authenticated Software Delivery
AAOS SDV provides two installation methods. First, we install software directly to read-only system, product, or vendor partitions, which validate signatures on every boot. This secures basic system components.
Second, we utilize Android Pony EXpress (APEX) packages for services. Each APEX encapsulates software and its dependencies, treating the package as a partition with mandatory signature validation. In AAOS SDV, APEX treats code signing as a continuous, hardware-enforced contract. APEX ensures malicious code execution is mitigated through four core pillars:
1. Immutable Storage
- The Mechanism: The Android kernel loops the
apex_payload.imgfile directly as a raw storage device using the read-only loopback, mounting it with the strictMS_RDONLYflag. - Why it's more secure: This exposes no write path to the OS because the files are not unpacked onto the vehicle's storage. Even if an attacker gains
rootprivileges, they cannot modify the running APEX code because the file system layer rejects all write commands.
2. Cryptographic Integrity
- The Mechanism: The cryptographic signature validates a Merkle Tree of the entire file system image.
- Why it's more secure: The kernel uses per-block
dm-verityto verify the signature for every 4KB data block on-the-fly. If an attacker modifies a raw block on the flash memory, the kernel detects the hash mismatch and halts execution immediately.
3. Strict Isolation
- The Mechanism: This applies the process isolation rules as described in the Process Isolation section to create a sandbox, with the APEX mounted as a dedicated partition under
/apex. - Why it's more secure: Each service receives its own user and data directory, restricting access unless sharing is explicit. By creating a dedicated partition, Android establishes a dedicated linker namespace, ensuring only explicitly exposed libraries are accessible from non-privileged system daemons, thus minimizing the attack surface.
4. Atomic Recovery
- The Mechanism: APEX uses an "Active/Backup" design to enable double-buffered rollbacks. The factory-flashed APEX remains on the immutable
/systempartition, while updates reside on the mutable/datapartition. - Why it's more secure: If an update fails or appears malicious, the
apexddaemon marks it as "failed" during early boot. The system instantly swaps symbolic links back to the/systempartition. This atomic recovery helps ensure the system does not remain in a broken state.
Resilience: Memory-Safe Development
Verified loading protects the system from external modification, but platform resilience also depends on how the underlying code is built. For new components developed for AAOS SDV, we prioritized memory safety.
Rust as the primary language
AAOS SDV targets small systems with fast availability requirements; this prevents building on the full Android stack, so we limited our scope to the native framework. To create the required infrastructure for a distributed system, we developed multiple components in addition to existing infrastructure and adopted Rust as the primary language. We also use Rust to develop the business logic of services, helping partners write secure software. By design, Rust leverages memory safety features to help prevent common classes of memory safety vulnerabilities, while supporting team throughput when writing native code.
Distributed Trust: Network & Access Control
Software-defined vehicles require secure interactions between isolated domains. The AAOS SDV mesh provisioning architecture addresses this complexity by cryptographically verifying the version and author of every communication endpoint.
Device and Mesh Provisioning
The AAOS SDV Mesh establishes authentication by mathematically binding the network identity of every component to its actual binary execution state. This model replaces implicit software trust with hardware-rooted verification.
Mesh authentication is designed to be continuous and cryptographic. This prevents scenarios where, for example, a service like a vehicle gateway trusts a compromised infotainment VM just because it has the right IP address.
Hardware-enforced isolation and automated quarantine protocols secure the platform. Peer devices within the SDV mesh use DICE-based authentication and attestation, as detailed in the following section, to help identify and contain unauthorized code execution or configuration tampering.
DICE-based TLS to secure VM-to-VM communication
Grounding the Host Identity in Reality
The Golden Rule of DICE (Device Identifier Composition Engine): If a single line of code in the firmware changes (even a minor update or a malicious exploit), the derived Compound Device Identifier (CDI) changes entirely, generating a completely different Alias Key.
DICE and TLS (Transport Layer Security) integrate to solve the fundamental challenge of zero-trust architecture: authenticating a machine while simultaneously verifying its software integrity.
The combination of DICE's hardware-backed identification and TLS's encrypted handshake allows a receiving machine to verify both the caller's identity and its exact software state.
Traditional certificates only prove possession of a secret; they cannot detect firmware tampering. DICE addresses this via measured boot layering:
- The Unique Device Secret (UDS): A random cryptographic secret generated during manufacturing. Only the first-stage bootloader can access the UDS; it remains inaccessible to all other software and external interfaces.
- Layered Measurements (The Compound Device Identifier): The hardware ROM initiates the chain by hashing the UDS with the exact code and configuration of the next firmware layer. This creates a CDI, which then chains sequentially as each subsequent layer boots.
Strict access controls govern service interactions within the AAOS SDV mesh. Just like all AAOS SDV software, these access controls are authenticated, and their integrity is protected at the device level and across devices in the mesh through the DICE-based authentication.
Layered Access Control
AAOS SDV employs a defense-in-depth strategy to enable dynamic vehicle updates without compromising access mechanisms. This model relies on two primary trust layers:
- Service-level permissions: Define the specific resources a service on a given VM can access or expose across the mesh.
- VM-level permissions: Define the cross-VM communication boundaries for all services hosted on a specific VM.
This model allows OEMs to balance security with updatability. For non-security-sensitive services, permissive VM-level policies enable installation via lightweight APEX updates rather than full VM redeployments.
Conversely, permissions for security-sensitive signals must be hard-coded into every VM. The tradeoff is that introducing a security-sensitive service to a new VM requires updating the VM-level permissions system-wide. This necessitates an update to all VMs within the mesh.
Conclusion
AAOS SDV extends Android's security architecture to address specific automotive requirements through a secure-by-design approach. By leveraging virtualization for domain isolation and enforcing "deny-by-default" access policies, the platform establishes a resilient environment for software-defined vehicles. Cryptographic integrity is maintained via hardware-enforced, on-the-fly verification of executed code.
The platform integrates continuous security lifecycles, ranging from proactive vulnerability management to hardware-rooted identity verification via DICE. These multi-layered defenses allow OEMs to balance advanced feature updatability with the robust security necessary for modern automotive environments. Technical specifications and implementation details are available on the AAOS SDV Overview page.
24 Aug 2026 4:00pm GMT
19 Aug 2026
Android Developers Blog
Preparing your app for broader memory limits
Posted by Blair Harmon, Director of Product Management, Android Platform
A great user experience is central to Android's mission, and delivering on that promise requires keeping devices fast, responsive, and reliable. This is why memory optimization is more critical than ever. Across the ecosystem, new devices are maintaining or even decreasing their physical memory capacity in response to memory price increases, yet users continue to expect the same seamless, high-performance app experience.
In Android 17, we introduced per-app memory limits, starting with Pixel devices, to help protect the overall user experience from applications using excess memory and causing system-wide slowdowns. Over the coming year, an increasing number of manufacturers will leverage the Android per-app memory limits across their portfolio of device RAM configurations from 4GB to 16GB+ devices. If your app exceeds these limits, it will be slowed down and may be terminated. Optimizing your app's memory footprint is essential to preventing OS throttling and maintaining a seamless user experience.
In this post, we'll explore how these limits work under the hood, how to measure your memory footprint using new Android vitals metrics, and actionable steps to optimize your app or game.
Understanding Memory Limits
When your app exceeds its memory budget, Android takes progressive action to protect device responsiveness:
- zRAM Swapping: If your app reaches its allocated limit, the system forces your app's pages into zRAM (compressed RAM). While zRAM prevents immediate eviction, compressing and decompressing pages adds CPU overhead, which can result in noticeable UI jank and experience slowdowns.
- Process Termination: If your app continues to increase its memory usage beyond the zRAM threshold, it will be terminated by the system. To determine if your app session was impacted by these constraints in the field, you can call
getDescription()withinApplicationExitInfo. If the system applied a limit, the exit reason is reported asREASON_OTHERand the description string will contain "MemoryLimiter:AnonSwap". You can also leverage trigger-based profiling usingTRIGGER_TYPE_ANOMALYto automatically capture heap dumps when the memory limit is reached.
To learn more about per-app memory limits and system enforcement, review the Android 17 App Memory Limits documentation. To test your application on different device configurations use the Memory Limiter adb commands.
Monitoring and Diagnosing Memory Issues
You can't optimize what you can't measure. Identifying memory leaks, excessive heap allocations, and Out-Of-Memory (OOM) crashes across the Android ecosystem requires leveraging complementary monitoring tools:
- Macro-level health with Android vitals: For broad, population-level visibility without additional overhead, Google Play Console's Android vitals provides essential metrics like Memory Usage (Anonymous RSS + swap) and Bitmap Memory Usage. This gives you a clear snapshot of memory distribution across different process states (foreground, background, user-perceived services, and cached) and RAM class ranges, helping you spot memory outliers.
- Memory Limiter exits & OOM tracking with Firebase Crashlytics: To stay informed about severe memory degradation before it impacts your key metrics, Crashlytics version 20.1.0 introduces additional debug data to help you catch, prioritize, and fix Out-Of-Memory exceptions and memory limiter kills. Tracking these events alongside custom logs and key-value metadata gives you immediate context into process status when a memory failure occurs.
- In-field traces with ProfilingManager: For teams able to maintain a performance observability framework, the
ProfilingManagerAPI introduced in Android 15 (API level 35) allows your app to programmatically request and collect detailed memory debug artifacts such as Java heap dumps and heap profiles directly from production devices. You can also trigger heap dump captures based on specific system signals, such asTRIGGER_TYPE_OOMandTRIGGER_TYPE_ANOMALY.
Read our documentation to learn more about other memory monitoring techniques.
Summary & What's Next
With Android broadening per-app memory limits across all RAM classes, now is the time to audit your memory footprint:
- Prioritize memory optimizations: Prevent your app from being impacted by app memory limits by using best practices.
- Monitor memory use: Monitor your app's memory behavior to detect and resolve anomalous behavior.
- Optimize your game: Follow the latest guidance for games and complex multimedia apps to maximize memory savings across process states.
Helpful Resources & References
- Android 17 Behavior Changes: App Memory Limits
- Android Vitals: Memory Usage (RSS + swap metric) and Bitmap Memory Usage
- Android Developers Blog: Prioritizing memory efficiency steps for Android 17
- Developer Guide: Manage your app's memory
19 Aug 2026 7:00pm GMT





















.png)
.png)








.gif)
.png)



