30 Sep 2026

feedTalkAndroid

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

feedAndroid Developers Blog

Driving growth on Google Play: The next era of subscriptions

Posted by Sheenam Mittal, Senior Product Manager, Google Play

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:

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

28 Sep 2026

feedAndroid 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.

The booking assistant shows all booking progress, organized by event type.

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.
The Android app sends the current trip itinerary data to the server. The coordinator agent chooses which subagents to trigger. Each subagent provides its results to a shared session queue that streams the results back to the Android app.

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:


A basic interface that lets a user chat with an assistant.

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

By hosting agent workflows in the cloud and using the AG-UI and A2UI protocols together, we can build dynamic, native Android interfaces driven directly by AI models. AG-UI establishes the real-time bidirectional streaming channel for messages and lifecycle events, while A2UI enables the cloud agent to dynamically describe interactive UI components, keeping the client application perfectly decoupled from the step-by-step backend orchestration logic.

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.0

28 Sep 2026 4:00pm GMT

24 Sep 2026

feedAndroid 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.

Claude Agent in Android Studio

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

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.

Log in to the Antigravity Agent using a Google account, Gemini Enterprise license,
Enterprise Agent platform or Gemini API key

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:

  1. Update Android Studio: Ensure you are running the latest from the canary release channel.
  2. 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
  3. 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

29 Aug 2026

feedPlanet Maemo

An In-Depth Look at the LiberNovo Omni SE

Two months, one chair, and a cushion that had to be replaced - twice. This isn't a review in the strict sense. The only other chair I've used long-term is an IKEA Nominell, so I can't offer broad comparisons. What I can offer is an honest account of living with the Omni SE - plus a few observations most reviews skip.

Where I'm coming from

My background shapes what I look for in a chair, so it's worth stating up front.

I never had back problems with my old IKEA chair, but I credit that to regular exercise rather than to the chair. In my experience, exercise is by far the most effective way to prevent back pain - closely followed by changing posture throughout the day: standing up now and then and putting your leg muscles to work.

The upshot: for me, the specific chair matters less than people assume. What I value instead are quality-of-life features - freedom to move and the ability to recline deeply for a quick moment of relaxation. That's the lens I judged the Omni SE through.

The Omni chairs hardly need an introduction; they're among the most aggressively marketed chairs on social media. So rather than rehash the spec sheet (Dan Ahn's YouTube channel covers that well), I'll stick to my own experience.

Ordering

I paid the 10€ deposit, ordered on 16 June for 589€, and received the chair on 23 June - so about two months of use at the time of writing.

The 10€ "deposit" turned out to be a one-year warranty extension rather than a deposit. Fine by me.

The seat cushion problem

The downside of ordering early and cheap: at least the first batch shipped with foam that was too soft in the seat cushion.

The Omni cushion combines three foam densities, with the firmest section only near the backrest. Even that section wasn't firm enough - once the foam warmed up, you'd sink through to the plastic pan. Steve, the Anthros CEO, summarises the issue neatly - keep in mind though, that this is coming from a rival.

If you're reading this in a seemingly fine Omni and wonder what this feels like, sit on the front edge for a few minutes: the softer foam lets you bottom out. Sit with your lumbar against the backrest and you're on the firm section, where it should feel comfortable.

Customer support assured me that batches produced after early May went through improved firmness testing - which means my chair was made before that. At the time of writing, it's still unclear whether all new deliveries ship with the updated cushion. So if you'd rather not go through the hassle of getting a replacement, wait until that's confirmed.

How support handled it

Sitting with my lumbar against the backrest was exactly where the problem showed up for me, so after a few uncomfortable weeks I contacted support via email. They replied within 24 hours, and their first suggestion was that I should sit closer to the backrest. Once I confirmed I already was, they promised a revised cushion - and noted that my return window would restart on the day the replacement arrived.

A week later a new cushion arrived - the Pro version, sent by mistake. Since the correct replacement was another month out, I used the Pro cushion in the meantime; its firmer foam didn't bottom out. I also received a small compensation package for the inconvenience, including the StepSync Mat, which turned out to be surprisingly handy - more on that below.

The correct SE cushion arrived at the end of August, so at the time of writing I've used the Pro cushion for about a month and the revised SE cushion for three days.

On the two replacement cushions

The revised SE cushion is noticeably stiffer than the one my chair originally shipped with, across all three foam zones.

The Pro uses Gabriel Atlantic fabric, which the active ventilation requires because it allows more airflow. It's also more durable. The trade-off is the coarser weave: less soft and slightly scratchy compared to the standard fabric.

In terms of firmness, the two replacement cushions feel about the same to me - the fabric is the main difference. Upgrading to the Pro just for the fabric isn't worth it in my view.

Backrest and recline

The backrest is what LiberNovo builds its marketing around, and deservedly so. Sitting down for the first time, it was the most noticeable difference to my IKEA chair: it hugs you around the lumbar region and you immediately feel supported, without limiting your range of motion.

The second standout is the recline. If you've ever wanted to lie back for a moment of relaxation and quick back relief, that's what the 160° position gives you. Even at maximum recline the chair feels stable - but to be genuinely comfortable, you'll want to raise your legs. Whether that calls for the official footrest is up to you; I put the StepSync Mat on the subwoofer under my desk and called it a day.

Day to day, though, I keep the chair locked at 135° with the tension tightened up - that lets me move freely back and forth while still getting the back support.

Armrests

These get called out as a weak point, so I'll say plainly that I like them. Yes, they slide forward and backward very easily - but for me that's an advantage: I can pull up to the desk and the armrests simply move out of the way. If you prefer them to stay put, I can see it being annoying.

The one real drawback: at the two narrowest width settings they collide with the backrest unless fully extended forward.

Material-wise, the firmness and smooth surface are pleasant. Keep in mind, though, that my old chair had no armrests at all.

The standout: parts availability

The cushion swap points to what I consider LiberNovo's real strength - not the chair itself, but what you can do with it after you buy it.

Competing brands may advertise a 12-year warranty instead of six, but their spare-parts selection is very limited. With LiberNovo you can order every individual component - and, unusually, at fair prices: building an Omni SE from parts comes to €681, against €679 for the finished chair (current price). Most brands price their spares steeply enough to make that comparison absurd.

What that enables is customization: want a headrest in a different colour? Order that spare part. Worried about the motorized lumbar? Swap in the manual one from the SE.

Verdict

After two months, I'm happy with the upgrade. The Omni SE is far more comfortable than my IKEA chair, and I use the recline often - reading a book, or just taking the load off my back.

The biggest drawback is probably the fixed seat depth. You can change it later by buying the 45 cm / 48 cm cushion replacement, but that still doesn't let different people share the same chair.

LiberNovo recently extended the warranty to six years for everyone, which makes seven with my deposit. Since the SE has no electronic components, that covers the whole chair in my case.

My cushion wasn't right out of the box, and it still took two months and two shipments to sort out. But the parts availability and the support response mean you're not stuck with a problem you can't fix - and that, more than any spec, is what won me over.

I'll update this post if anything changes.

0 Add to favourites0 Bury

29 Aug 2026 11:27am GMT

04 Jul 2026

feedPlanet Maemo

Reticulum is interesting

It all started innocently enough: sometime last summer, I ran into the blog post Start your own Internet Resiliency Club on Hacker News.

…communicate with each other across a few kilometers without any centralized infrastructure using cheap, low-power, unlicensed LoRa radios and open source Meshtastic text messaging software.

The idea of a local, infrastructure-free communications mesh sounded useful, especially as we were about to sail into the Pacific.

Meshtastic

While conflicts and natural disasters are hopefully far away, on the smaller atolls there is no cellular network. With Meshtastic we could communicate over LoRa.

Using Meshtastic on a boat

Over the hurricane season, the Meshtastic setup became quite extensive. Our boat has a Meshtastic node, plus a mast-mounted solar repeater. We both have Meshtastic cards that we carry with us. With these we can communicate with text messages over quite a long distance. And we get telemetry and alerts from the boat.

In Cartagena, Colombia we could hear the boat pretty much across the city. And since some of our buddy boats also run Meshtastic, we've even had conversations while offshore.

While the existing Meshtastic setup is serving us well, there is always room for improvement and new ideas.

Reticulum

Reticulum is a project that seeks to take this to a whole new level. It is a whole decentralized networking stack that allows anything from instant messaging and voice calls to full-on SSH sessions to be carried over a multitude of different interfaces. You can transport Reticulum over LoRa, Bluetooth, and also over regular TCP/IP networks. And if authorities didn't take a dim view on encryption in ham radio, it would also work over our HF radio. With store-and-forward mechanisms it can deal with intermittent connectivity.

Because your identity is portable, your connectivity can be fluid. You can be sitting at a desk connected to a fiber backbone one moment, and walking through a field connected only to a long-range LoRa mesh the next. To the rest of the network, nothing has changed. Your friends do not need to update your contact info. The messages they send do not bounce back. The network senses the shift in the medium and reroutes the flow of data automatically.
You are no longer a stationary node in a fixed grid. You are a wanderer in a fluid medium.
- The Zen of Reticulum

As it stands now, Reticulum is still quite an early system with rudimentary and tech-heavy user interfaces. But that seems to be about to change: the Columba app for Android seems about as user-friendly as Meshtastic or something like Signal. There's a lot of potential in that once it reaches a stable version.

Distributed development over Reticulum

In the meanwhile, there is one aspect of Reticulum we developers can benefit from immediately: Distributed development. With it, any rngit node running on Reticulum can be your "GitHub". Git history, issue tracking, release distribution is already there.

I recently switched my various programming projects over. We have rngit running on the boat NAS, and VPS running a mirror behind more consistent connectivity. And for now I also mirror the work periodically to GitHub for backwards compatibility.

Reticulum for software

What I think is worthwhile to explore is having machines interface with Reticulum. Just like we can tell our boat to switch lights on via a Meshtastic message, we should be able to do the same with Reticulum. And maybe there should be a NomadNet "site" for the boat showing status of the various systems.

Going further, maybe boats could share chart data, depth soundings, weather information with each other over this. The promise of VDES, but built from the grassroots perspective.

And maybe things like NoFlo should be able to communicate over Reticulum? Reticulum implementations exist for multiple programming languages, but for this we'd need a JavaScript port.

There's still a lot to study and to think about. Watch this space. Last time I noted that something is interesting, it took me to a ten year rabbit hole.

0 Add to favourites0 Bury

04 Jul 2026 12:00am GMT

26 Jan 2026

feedPlanet Maemo

Igalia Multimedia contributions in 2025

Now that 2025 is over, it's time to look back and feel proud of the path we've walked. Last year has been really exciting in terms of contributions to GStreamer and WebKit for the Igalia Multimedia team.

With more than 459 contributions along the year, we've been one of the top contributors to the GStreamer project, in areas like Vulkan Video, GstValidate, VA, GStreamer Editing Services, WebRTC or H.266 support.

Pie chart of Igalia's contributions to different areas of the GStreamer project: other (30%) vulkan (24%) validate (7%) va (6%) ges (4%) webrtc (3%) h266parse (3%) python (3%) dots-viewer (3%) tests (2%) docs (2%) devtools (2%) webrtcbin (1%) tracers (1%) qtdemux (1%) gst (1%) ci (1%) y4menc (1%) videorate (1%) gl (1%) alsa (1%)
Igalia's contributions to the GStreamer project

In Vulkan Video we've worked on the VP9 video decoder, and cooperated with other contributors to push the AV1 decoder as well. There's now an H.264 base class for video encoding that is designed to support general hardware-accelerated processing.

GStreaming Editing Services, the framework to build video editing applications, has gained time remapping support, which now allows to include fast/slow motion effects in the videos. Video transformations (scaling, cropping, rounded corners, etc) are now hardware-accelerated thanks to the addition of new Skia-based GStreamer elements and integration with OpenGL. Buffer pool tuning and pipeline improvements have helped to optimize memory usage and performance, enabling the edition of 4K video at 60 frames per second. Much of this work to improve and ensure quality in GStreamer Editing Services has also brought improvements in the GstValidate testing framework, which will be useful for other parts of GStreamer.

Regarding H.266 (VVC), full playback support (with decoders such as vvdec and avdec_h266, demuxers and muxers for Matroska, MP4 and TS, and parsers for the vvc1 and vvi1 formats) is now available in GStreamer 1.26 thanks to Igalia's work. This allows user applications such as the WebKitGTK web browser to leverage the hardware accelerated decoding provided by VAAPI to play H.266 video using GStreamer.

Igalia has also been one of the top contributors to GStreamer Rust, with 43 contributions. Most of the commits there have been related to Vulkan Video.

Pie chart of Igalia's contributions to different areas of the GStreamer Rust project: vulkan (28%) other (26%) gstreamer (12%) ci (12%) tracer (7%) validate (5%) ges (7%) examples (5%)
Igalia's contributions to the GStreamer Rust project

In addition to GStreamer, the team also has a strong presence in WebKit, where we leverage our GStreamer knowledge to implement many features of the web engine related to multimedia. From the 1739 contributions to the WebKit project done last year by Igalia, the Multimedia team has made 323 of them. Nearly one third of those have been related to generic multimedia playback, and the rest have been on areas such as WebRTC, MediaStream, MSE, WebAudio, a new Quirks system to provide adaptations for specific hardware multimedia platforms at runtime, WebCodecs or MediaRecorder.

Pie chart of Igalia's contributions to different areas of the WebKit project: Generic Gstreamer work (33%) WebRTC (20%) Regression bugfixing (9%) Other (7%) MSE (6%) BuildStream SDK (4%) MediaStream (3%) WPE platform (3%) WebAudio (3%) WebKitGTK platform (2%) Quirks (2%) MediaRecorder (2%) EME (2%) Glib (1%) WTF (1%) WebCodecs (1%) GPUProcess (1%) Streams (1%)
Igalia Multimedia Team's contributions to different areas of the WebKit project

We're happy about what we've achieved along the year and look forward to maintaining this success and bringing even more exciting features and contributions in 2026.

0 Add to favourites0 Bury

26 Jan 2026 9:34am GMT

18 Sep 2022

feedPlanet Openmoko

Harald "LaF0rge" Welte: Deployment of future community TDMoIP hub

I've mentioned some of my various retronetworking projects in some past blog posts. One of those projects is Osmocom Community TDM over IP (OCTOI). During the past 5 or so months, we have been using a number of GPS-synchronized open source icE1usb interconnected by a new, efficient but strill transparent TDMoIP protocol in order to run a distributed TDM/PDH network. This network is currently only used to provide ISDN services to retronetworking enthusiasts, but other uses like frame relay have also been validated.

So far, the central hub of this OCTOI network has been operating in the basement of my home, behind a consumer-grade DOCSIS cable modem connection. Given that TDMoIP is relatively sensitive to packet loss, this has been sub-optimal.

Luckily some of my old friends at noris.net have agreed to host a new OCTOI hub free of charge in one of their ultra-reliable co-location data centres. I'm already hosting some other machines there for 20+ years, and noris.net is a good fit given that they were - in their early days as an ISP - the driving force in the early 90s behind one of the Linux kernel ISDN stracks called u-isdn. So after many decades, ISDN returns to them in a very different way.

Side note: In case you're curious, a reconstructed partial release history of the u-isdn code can be found on gitea.osmocom.org

But I digress. So today, there was the installation of this new OCTOI hub setup. It has been prepared for several weeks in advance, and the hub contains two circuit boards designed entirely only for this use case. The most difficult challenge was the fact that this data centre has no existing GPS RF distribution, and the roof is ~ 100m of CAT5 cable (no fiber!) away from the roof. So we faced the challenge of passing the 1PPS (1 pulse per second) signal reliably through several steps of lightning/over-voltage protection into the icE1usb whose internal GPS-DO serves as a grandmaster clock for the TDM network.

The equipment deployed in this installation currently contains:

For more details, see this wiki page and this ticket

Now that the physical deployment has been made, the next steps will be to migrate all the TDMoIP links from the existing user base over to the new hub. We hope the reliability and performance will be much better than behind DOCSIS.

In any case, this new setup for sure has a lot of capacity to connect many more more users to this network. At this point we can still only offer E1 PRI interfaces. I expect that at some point during the coming winter the project for remote TDMoIP BRI (S/T, S0-Bus) connectivity will become available.

Acknowledgements

I'd like to thank anyone helping this effort, specifically * Sylvain "tnt" Munaut for his work on the RS422 interface board (+ gateware/firmware) * noris.net for sponsoring the co-location * sysmocom for sponsoring the EPYC server hardware

18 Sep 2022 10:00pm GMT

08 Sep 2022

feedPlanet Openmoko

Harald "LaF0rge" Welte: Progress on the ITU-T V5 access network front

Almost one year after my post regarding first steps towards a V5 implementation, some friends and I were finally able to visit Wobcom, a small German city carrier and pick up a lot of decommissioned POTS/ISDN/PDH/SDH equipment, primarily V5 access networks.

This means that a number of retronetworking enthusiasts now have a chance to play with Siemens Fastlink, Nokia EKSOS and DeTeWe ALIAN access networks/multiplexers.

My primary interest is in Nokia EKSOS, which looks like an rather easy, low-complexity target. As one of the first steps, I took PCB photographs of the various modules/cards in the shelf, take note of the main chip designations and started to search for the related data sheets.

The results can be found in the Osmocom retronetworking wiki, with https://osmocom.org/projects/retronetworking/wiki/Nokia_EKSOS being the main entry page, and sub-pages about

In short: Unsurprisingly, a lot of Infineon analog and digital ICs for the POTS and ISDN ports, as well as a number of Motorola M68k based QUICC32 microprocessors and several unknown ASICs.

So with V5 hardware at my disposal, I've slowly re-started my efforts to implement the LE (local exchange) side of the V5 protocol stack, with the goal of eventually being able to interface those V5 AN with the Osmocom Community TDM over IP network. Once that is in place, we should also be able to offer real ISDN Uk0 (BRI) and POTS lines at retrocomputing events or hacker camps in the coming years.

08 Sep 2022 10:00pm GMT

Harald "LaF0rge" Welte: Clock sync trouble with Digium cards and timing cables

If you have ever worked with Digium (now part of Sangoma) digital telephony interface cards such as the TE110/410/420/820 (single to octal E1/T1/J1 PRI cards), you will probably have seen that they always have a timing connector, where the timing information can be passed from one card to another.

In PDH/ISDN (or even SDH) networks, it is very important to have a synchronized clock across the network. If the clocks are drifting, there will be underruns or overruns, with associated phase jumps that are particularly dangerous when analog modem calls are transported.

In traditional ISDN use cases, the clock is always provided by the network operator, and any customer/user side equipment is expected to synchronize to that clock.

So this Digium timing cable is needed in applications where you have more PRI lines than possible with one card, but only a subset of your lines (spans) are connected to the public operator. The timing cable should make sure that the clock received on one port from the public operator should be used as transmit bit-clock on all of the other ports, no matter on which card.

Unfortunately this decades-old Digium timing cable approach seems to suffer from some problems.

bursty bit clock changes until link is up

The first problem is that downstream port transmit bit clock was jumping around in bursts every two or so seconds. You can see an oscillogram of the E1 master signal (yellow) received by one TE820 card and the transmit of the slave ports on the other card at https://people.osmocom.org/laforge/photos/te820_timingcable_problem.mp4

As you can see, for some seconds the two clocks seem to be in perfect lock/sync, but in between there are periods of immense clock drift.

What I'd have expected is the behavior that can be seen at https://people.osmocom.org/laforge/photos/te820_notimingcable_loopback.mp4 - which shows a similar setup but without the use of a timing cable: Both the master clock input and the clock output were connected on the same TE820 card.

As I found out much later, this problem only occurs until any of the downstream/slave ports is fully OK/GREEN.

This is surprising, as any other E1 equipment I've seen always transmits at a constant bit clock irrespective whether there's any signal in the opposite direction, and irrespective of whether any other ports are up/aligned or not.

But ok, once you adjust your expectations to this Digium peculiarity, you can actually proceed.

clock drift between master and slave cards

Once any of the spans of a slave card on the timing bus are fully aligned, the transmit bit clocks of all of its ports appear to be in sync/lock - yay - but unfortunately only at the very first glance.

When looking at it for more than a few seconds, one can see a slow, continuous drift of the slave bit clocks compared to the master :(

Some initial measurements show that the clock of the slave card of the timing cable is drifting at about 12.5 ppb (parts per billion) when compared against the master clock reference.

This is rather disappointing, given that the whole point of a timing cable is to ensure you have one reference clock with all signals locked to it.

The work-around

If you are willing to sacrifice one port (span) of each card, you can work around that slow-clock-drift issue by connecting an external loopback cable. So the master card is configured to use the clock provided by the upstream provider. Its other ports (spans) will transmit at the exact recovered clock rate with no drift. You can use any of those ports to provide the clock reference to a port on the slave card using an external loopback cable.

In this setup, your slave card[s] will have perfect bit clock sync/lock.

Its just rather sad that you need to sacrifice ports just for achieving proper clock sync - something that the timing connectors and cables claim to do, but in reality don't achieve, at least not in my setup with the most modern and high-end octal-port PCIe cards (TE820).

08 Sep 2022 10:00pm GMT