Stable Channel Update for Desktop

The Stable channel has been updated to 151.0.7922.137/.138 for Windows and Mac and 151.0.7922.137 for Linux, which will roll out over the coming days/weeks. A full list of changes in this build is available in the Log 

Security Fixes and Rewards
Note: Access to bug details and links may be kept restricted until a majority of users are updated with a fix. We will also retain restrictions if the bug exists in a third party library that other projects similarly depend on, but haven’t yet fixed.

This update includes 5 security fixes. Please see the Chrome Security Page for more information.

[$500][535000102] High CVE-2026-19556: Use after free in V8. Reported by Jihyeon Jeong (Compsec Lab, Seoul National University / Research Intern) on 2026-07-15
[N/A][534867485] High CVE-2026-19557: Use after free in TabStrip. Reported by Google on 2026-07-14
[N/A][536676756] High CVE-2026-19558: Use after free in Extensions. Reported by @bean5oup on 2026-07-20
[N/A][540100588] High CVE-2026-19559: Use after free in HTML. Reported by Google on 2026-07-28
[N/A][540482895] High CVE-2026-19560: Use after free in Blink. Reported by WinD39 - Huynh Dinh Vu on 2026-07-30

We would also like to thank all security researchers that worked with us during the development cycle to prevent security bugs from ever reaching the stable channel.

Many of our security bugs are detected using AddressSanitizer, MemorySanitizer, UndefinedBehaviorSanitizer, Control Flow Integrity, libFuzzer, or AFL.

Interested in switching release channels? Find out how here. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.


Daniel Yip

Google Chrome

Extended Stable Update for Desktop

The Extended Stable channel has been updated to 150.0.7871.230 for Windows and Mac which will roll out over the coming days/weeks.

A full list of changes in this build is available in the log. Interested in switching release channels? Find out how here. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Srinivas Sista
Google Chrome

Chrome for Android Update

   Hi, everyone! We've just released Chrome 151 (151.0.7922.137) for Android. It'll become available on Google Play over the next few days. 

This release includes stability and performance improvements. You can see a full list of the changes in the Git log. If you find a new issue, please let us know by filing a bug.


Android releases contain the same security fixes as their corresponding Desktop releases (Windows & Mac: 151.0.7922.137/138, Linux: 151.0.7922.137) unless otherwise noted.

Harry Souders

Chrome Beta for iOS Update

Hi everyone! We've just released Chrome Beta 152 (152.0.7977.41) for iOS; it'll become available on App Store in the next few days.

You can see a partial list of the changes in the Git log. If you find a new issue, please let us know by filing a bug.

Chrome Release Team
Google Chrome

Chrome Beta for Android Update

Hi everyone! We've just released Chrome Beta 152 (152.0.7977.42) for Android. It's now available on Google Play.

You can see a partial list of the changes in the Git log. For details on new features, check out the Chromium blog, and for details on web platform updates, check here.

If you find a new issue, please let us know by filing a bug.

Chrome Release Team
Google Chrome

Chrome Stable for iOS Update

Hi everyone! We've just released Chrome Stable 152 (152.0.7977.40) for iOS; it'll become available on App Store in the next few hours.

This release includes stability and performance improvements. You can see a full list of the changes in the Git log. If you find a new issue, please let us know by filing a bug.

Chrome Release Team
Google Chrome

Chrome Beta for Desktop Update

The Beta channel has been updated to 152.0.7977.42 for Windows, Mac and Linux.

A partial list of changes is available in the Git log. Interested in switching release channels? Find out how. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Chrome Release Team
Google Chrome

New usability features in Connected Sheets

Google Workspace is introducing two usability enhancements to Connected Sheets to improve data presentation and give more flexibility when analyzing BigQuery data. 

List parameters: When writing a query, users can reference multiple values in a single list parameter by selecting a grid range in a sheet. Each cell will function as a unique value in the list. This enables more flexible or robust querying based on values already in the sheet. For example, this feature allows data admins and power users to configure input sheets that allow collaborators or end users to easily select options via drop-down or in the sheet for advanced filtering without needing to modify the underlying query. As a result, more users can independently self-serve insights and interact with Connected Sheets. 

Column aliasing: Users can create aliases for BigQuery column names directly within the Connected Sheet. Database column names can sometimes be unwieldy or lack contextual information for broader audience readability. Aliasing provides a way to substitute presentation-ready labels in the Connected Sheets interface without altering the underlying database reference. Users can continue to refer to columns by either the new alias or the original name in formulas and inputs. 





Getting started 


Rollout pace 


Availability 

  • Available to all Google Workspace customers and users with personal Google accounts 

Resources 

What's new in the Jetpack Compose August '26 release

Posted by Nick Butcher, Product Manager, Jetpack Compose


Today, the Jetpack Compose August ‘26 release is stable! This release brings version 1.12 across core Compose modules (see the full BOM mapping), introducing rich visual APIs like Mesh Gradients and Wide Color Gamut (WCG) support, structural layout features like named areas in Grid, seamless integration with Android’s Credential Manager, and significant testing and performance improvements.

To update your project to today’s release, upgrade your Compose BOM version to 2026.08.00:

implementation(platform("androidx.compose:compose-bom:2026.08.00"))

Breaking Changes

AGP & Compile SDK: Compose 1.12 updates compileSdk to API 37, requiring a minimum AGP 9.2.0. As a reminder, Compose will always target the latest compileSdk. Learn more about this change here.

Modifier.onFirstVisible() is deprecated: Migrate to Modifier.onVisibilityChanged(), which provides more precise visibility threshold tracking.

Graphics

Mesh Gradients

Compose 1.12 introduces MeshGradientPainter to help you create multi-point, organic color gradients.



val rows = 1
val columns = 1

val gradientPainter = remember {
    MeshGradientPainter(rows, columns) {
        // Parameters: row, column, position, color
        setVertex(0, 0, Offset(0f, 0f), Color.Red)     // Top-Left
        setVertex(0, 1, Offset(1f, 0f), Color.Blue)    // Top-Right
        setVertex(1, 0, Offset(0f, 1f), Color.Green)   // Bottom-Left
        setVertex(1, 1, Offset(1f, 1f), Color.Yellow)  // Bottom-Right
    }
}

Box(
    modifier = modifier
        .aspectRatio(16/9f)
        .fillMaxWidth()
        .paint(gradientPainter)
)

For more information and examples, see the documentation.

Wide Color Gamut & HDR Support

Modern displays offer extended color fidelity and higher dynamic range. In Compose 1.12, full pipeline support for Wide Color Gamut (P3) and HDR rendering has been enabled across Compose graphics, paint, and shaders. Colors defined in non-sRGB color spaces (such as Display P3) are preserved through to platform rendering without color clamping. Colors will safely fall back to sRGB if they use an unsupported color space (e.g. CieXyz, CieLab, or Oklab), rely on a color space on an unsupported Android version (e.g Bt2020Hlg on Android 13 and below), or if the app is running on Android 9 (API 28) and below.

Other notable changes:

  • LayerOutsets was added to GraphicsLayer & Modifier.graphicsLayer, which you can use to increase the visual bounds of the layer beyond its measured size. Apply LayerOutsets to avoid the implicit clipToBounds behavior when the layer is promoted to an offscreen buffer.

Styles

At Google I/O, we shared our early vision for the Compose Styles API—a unified, performant way to style components. Since then, we have continued building the underlying architecture to guarantee strict type safety and predictable correctness, and to support building custom design systems.

To ensure we get this foundational layer correct, the API will remain experimental, and you can expect breaking changes.

Runtime Optimizations

Keyed SideEffect Overload

SideEffect now supports key arguments, which lets you fire one-shot side effects whenever specific keys change. This can lead to better performance compared to using a LaunchedEffect or DisposableEffect when you don’t need the coroutine or dispose block. SideEffect is up to 90% faster than LaunchedEffect and around 20% faster than DisposableEffect. Note that SideEffect runs its effect before DisposableEffect and LaunchedEffect, so use caution if migrating existing effects to this API, especially for LaunchedEffects that rely on being dispatched to start after the current frame is completed.

@Composable
fun AnalyticsTracker(userId: String, screenName: String) {
    SideEffect(key1 = userId, key2 = screenName) {
        analytics.logScreenView(userId, screenName)
    }
}

Animation

DeferredTargetAnimation has graduated out of experimental status.

Interactive Two-Stage Transitions

New composables: DeferredAnimatedContent and DeferredAnimatedVisibility allow creating delightful two-stage transitions, e.g. for predictive back gesture tracking.

Manual animation control: During a transition's deferred phase, animated properties (like scale or offset) can now be manually manipulated in real-time (e.g., tracking a swipe gesture).

Seamless handoff: Once the deferred phase ends, the transition engine takes over and performs a seamless handoff, including velocity transfer, to the automatic transition.

Shared element support: A new permitTransformDuringDeferredTransition flag in SharedContentConfig controls whether shared elements visually transform along with their parent containers during the deferred transition phase.

val state = remember { DeferredTransitionState(initialScreen) }
val transition = rememberDeferredTransition(state)

if (predictiveBackInProgress) {
    state.defer(targetScreen)
} else {
    state.animateTo(targetScreen)
}

transition.DeferredAnimatedContent(
    targetState = targetScreen,
    mutableTransformSpec = {
       MutableContentTransform {
           // Manually manipulate properties during the deferred phase
           initialContentTransform { scale = swipeProgress }
       }
    }
) { screen ->
    ScreenContent(screen)
}

Below are two demos of use cases where a gesture-driven animation is handed off to a triggered animation:



Text, Input & Platform Integrations

Editable Text Formatting

New APIs offer rich-text formatting for editable text in BasicTextField. You can now programmatically apply and manipulate inline character and paragraph formatting using SpanStyle and ParagraphStyle via the new addStyle() method inside a TextFieldBuffer scope (such as inside textFieldState.edit { ... } or an InputTransformation). Additionally, TextFieldBuffer provides getSpanStyles() and getParagraphStyles() APIs that return TrackedRange objects, allowing you to read, update, or remove applied styles. To complement formatting creation, TextFieldState now exposes a read-only textStyles property for querying active styles across ranges, while TextFieldBuffer provides originalTextStyles to inspect formatting state prior to an edit. Text formatting and custom annotations are persisted across configuration changes.

val state = rememberTextFieldState("Formatted text in Compose 1.12")

// Apply bold and color styles to a range of text
state.edit {
    addStyle(
        SpanStyle(fontWeight = FontWeight.Bold, color = Color.Blue),
        start = 0,
        end = 9
    )
}

// Query active styles from TextFieldState
val currentStyles = state.textStyles

Text Selection

A new SelectionState API provides programmatic control and observability over text selection within a SelectionContainer. Hoisting a SelectionState object via rememberSelectionState() and passing into SelectionContainer exposes selectedTexts as a reactive list of AnnotatedStrings and provides methods like selectAll(), clear(), select(TextRange), and extendSelectionByWord().

Additionally, use getSelectableTexts() to retrieve all selectable text items in layout order and select text across composables in the SelectionContainer using a global range.

@Composable
fun ProgrammaticSelectionExample() {
    val selectionState = rememberSelectionState()

    Column {
        Button(
            onClick = { selectionState.selectAll() },
            modifier = Modifier.disableSelectionClearOnTap()
        ) {
            Text("Select All")
        }

        SelectionContainer(state = selectionState) {
            Text("Text content to be selected programmatically.")
        }
    }
}

Credential Manager Integration

Compose text fields now natively integrate with Android’s Credential Manager (API 34+) via the Autofill framework (below API 34 is handled by androidx.credentialslibrary). By attaching the new credentialRequest semantics property with CredentialRequestData, text inputs can prompt passkeys, saved credentials, or sign-in requests directly within the user input flow.

@Composable
fun LoginField(textFieldState: TextFieldState) {
    val credentialData = remember {
        CredentialRequestData(
            // Specify Credential Manager request options
        )
    }

    BasicTextField(
        state = textFieldState,
        modifier = Modifier.semantics {
            credentialRequest = credentialData
        }
    )
}

Other notable changes:

  • Support for font variation settings in downloadable fonts.
  • Enabled auto-scrolling when dragging text selection beyond the viewport in SelectionContainer.
  • Added support for automatic interaction sounds (clicks and focus navigation) to Compose components, with a new SoundEffectOnInteraction composable to allow opt-out. Note that as a consequence of this change, semantics click listeners must now be called from the main thread, which may affect a small number of test cases.
  • KeyboardType now includes Date, Time, DateTime, and SignedDecimal.
  • BasicSecureTextField now uses TextObfuscationMode.System by default, while RevealLastTyped serves as an absolute override.

Layout Enhancements

Named Areas in Grid Layout

Building complex 2D layouts is now easier with named areas in the @Experimental Grid component. Rather than managing numeric column and row indices across items, you can define semantic regions in your GridConfigurationScope and position composables by area name.

@OptIn(ExperimentalGridApi::class)
@Composable
fun DashboardLayout() {
    Grid(
        config = {
            area("header", row = 0, column = 0, rowSpan = 1, columnSpan = 2)
            area("sidebar", row = 1, column = 0)
            area("content", row = 1, column = 1)
            gap(16.dp)
        }
    ) {
        HeaderSection(modifier = Modifier.gridItem(areaId = "header"))
        NavigationSidebar(modifier = Modifier.gridItem(areaId = "sidebar"))
        MainContentView(modifier = Modifier.gridItem(areaId = "content"))
    }
}

Performance

As with every release, we continue to invest in Compose's performance to ensure that the framework helps you to build beautiful, performant apps. In this release we've focused on improving startup performance and are now seeing Time to Initial Display (the time it takes for an app to produce its first frame) that is comparable to Views in our benchmarks.

Testing & Tooling Upgrades

Test Synchronization

Compose 1.12 introduces new test APIs designed to reduce test execution times and eliminate flakiness during state sampling:

  • hasPendingWork: Passively checks if the UI has pending work without advancing the clock, which is ideal for manual animation loops.

  • runWithoutImplicitWait: Temporarily disables implicit synchronization when stepping through manual clock frames (e.g. animation tests).

  • @Test
    fun testAnimationStateFast() {
    
    composeTestRule.mainClock.autoAdvance = false
        
        while (composeTestRule.hasPendingWork()) {
            composeTestRule.mainClock.advanceTimeByFrame()
            composeTestRule.waitForIdle()
            
            composeTestRule.runOnUiThread {
                composeTestRule.runWithoutImplicitWait {
                    // This is most effective when querying multiple nodes in a single frame. 
                    // It prevents the redundant synchronization overhead that would 
                    // otherwise occur on every individual query.
                    val box1 = composeTestRule.onNodeWithTag("Box1").fetchSemanticsNode()
                    val box2 = composeTestRule.onNodeWithTag("Box2").fetchSemanticsNode()
                    
                    assertThat(box1.boundsInRoot.right).isAtMost(box2.boundsInRoot.left)
                }
            }
        }
    }

    Other notable changes:

    • The captureToImage API now allows you to capture a popup or dialog together with its anchor in a single bitmap.
    • Added onRootWithViewInteraction to scope Compose semantic searches to specific Android Views. This simplifies testing hybrid UIs, such as RecyclerViews, without requiring unique test tags in production code.
    • @PreviewWrapper annotations can now be applied to custom @MultiPreview classes, enabling reusable preview setups (such as custom themes) across multiple components.

    Happy Composing!

    Compose 1.12 makes app development easier and more expressive than ever, with mesh gradients, wide color gamut support, downloadable variable fonts, Credential Manager integration, and faster testing tools. As always, we value your input, so please share your feedback on these changes or what you'd like to see next on our issue tracker. Happy composing!

    Bring one-handed gestures to your Wear OS app

    Posted by Chiara Chiappini, Developer Relation Engineer, Android Developer Relations


    One-handed gestures offer a convenient and touch-free way for users to interact with their watches, enabling them to perform key actions using only the hand on which the device is worn. 

    First introduced on Pixel Watch with Wear OS 6.1, one-handed gestures made quick interactions effortless, such as starting and stopping a timer, accepting calls, and controlling media. 

    Now, with Wear OS 7, we're expanding this functionality with a new Gestures framework that allows OEMs to map gestures to primary actions and dismissals, and an API to bring gesture control to the developer community.

    Starting with the 1.7 beta release of Compose for Wear OS, you can seamlessly integrate gesture control into your Wear Compose apps. To use this release, upgrade your Wear Compose dependency to:

    androidx.wear.compose:compose-material3:1.7.0-beta01

    Designing for one-handed interaction

    The one-handed gestures framework is designed around two primary interaction patterns that allow users to take action without touching the screen:

    • Primary action, which on Pixel Watch is mapped to a double-pinch gesture: this action should be mapped to the most important task in a given context. For example, users can perform this gesture to take a photo in a camera app, start/stop a timer, or accept an incoming call. 
    • Dismiss action, which on Pixel Watch is mapped to a wrist turn gesture: this action is mapped to system back by default and provides an intuitive way to close interruptive screens or get back to the watch face. It may be overridden for specific use cases, such as silencing an incoming phone call.

    These gestures are currently available on Pixel Watch 3 and newer, and the Wear OS gesture framework is available to all Wear OS device manufactures to adopt.

    Check out our new design guidance for integrating one-handed gestures into your Wear app.

    Integrating gestures with Compose on Wear OS

    To provide seamless gesture support in Wear OS 7, we are introducing a new Modifier.oneHandedGesture that you can apply to any existing interactive composable to make it gesture-aware. 

    Implementing gestures with Compose on Wear OS requires these steps:

    1. Define the gesture configuration. Start by using rememberOneHandedGestureConfiguration to define the nature of the interaction. This configuration dictates the basic behavior by providing the GestureAction (e.g. tracking a primary pinch or a dismiss wrist flick).
    2. Initialize the indicator state. Depending on your UI component, initialize a specific state object, such as OneHandedGestureClickIndicatorState for buttons or OneHandedGestureScrollIndicatorState for scrollable lists. This state is used to coordinate visual feedback between the gesture detection modifier and the visual UI indicators, seamlessly managing visibility, timing, and animations.
    3. Apply Modifier.oneHandedGesture to your interactive component. You'll pass in your configuration and state, and you’ll provide standard callbacks: onGestureAvailable to activate the visual hint when the system prepares the gesture, and onGesture to execute your action when the gesture happens.

    The following sample shows how those three steps translate into code when configuring an IconButton:


    val gestureConfig = rememberOneHandedGestureConfiguration(action = OneHandedGestureAction.Primary)
    val indicatorState = remember { OneHandedGestureClickIndicatorState() }
    val coroutineScope = rememberCoroutineScope()
    
    OutlinedIconButton(
        onClick = onPlayPauseButtonClicked,
        modifier = Modifier.touchTargetAwareSize(IconButtonDefaults.LargeButtonSize)
            .oneHandedGesture(
                gestureConfiguration = gestureConfig,
                interactionSource = interactionSource,
                onGestureLabel = "play or pause",
                onGestureAvailable = { 
                    coroutineScope.launch { indicatorState.showIndicator() } 
                },
                onGesture = onPlayPauseButtonClicked,
            ),
    ) {
        // button content goes here
        // See "Guided discovery with gesture indicators" section of this post for recommendations on adding a gesture indicator.
    }

     

    The GestureAction.Primary can also be used to scroll when the content is the end goal of the user journey, or there is a gesture actionable button off screen that the user can scroll to. Some examples include:

    • Scrolling through a notification to view the content and/or initiate a reply (available in TransformingLazyColumn and ScalingLazyColumn).
    • Paging through workout metrics or other content that doesn’t require the user to tap to continue the user journey (available in  HorizontalPager and VerticalPager).  

    val scrollGestureConfig = rememberOneHandedGestureConfiguration(action = GestureAction.Primary)
    val scrollIndicatorState = remember { OneHandedGestureScrollIndicatorState() }
    val coroutineScope = rememberCoroutineScope()
    
    TransformingLazyColumn(
        state = scrollState,
        contentPadding = contentPadding,
        modifier = Modifier
            .fillMaxSize()
            .oneHandedGesture(
                gestureConfiguration = scrollGestureConfig,
                onGestureLabel = "scroll",
                onGestureAvailable = { 
                    coroutineScope.launch { scrollIndicatorState.showIndicator() } 
                },
                onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) }
            )
    ) {
        // list content goes here
        // See "Guided discovery with gesture indicators" section of this post for recommendations on adding a gesture indicator.
    }

    Guided discovery with gesture indicators

    To help users learn which gestures are available, gesture indicators work as hints to help discovery about which gestures are available on a screen.

    These hints provide animated cues that inform users where they can perform a gesture. The framework manages the cadence and appearance of these hints, ensuring that they are helpful without being intrusive. System settings let users change the cadence to something less frequent if desired.

    To integrate with hints, the API provides the following gesture indicator components:

    The following example shows how to use the OneHandedGestureClickIndicator for a Button. See another example for using the OneHandedGestureScrollIndicator in our guidance.


    val gestureConfig = rememberOneHandedGestureConfiguration(action = GestureAction.Primary)
    val indicatorState = remember { OneHandedGestureClickIndicatorState() }
    val coroutineScope = rememberCoroutineScope()
    
    OutlinedIconButton(
        onClick = onPlayPauseButtonClicked,
        modifier = Modifier.touchTargetAwareSize(IconButtonDefaults.LargeButtonSize)
            .oneHandedGesture(
                gestureConfiguration = gestureConfig,
                interactionSource = interactionSource,
                onGestureLabel = "play or pause",
                onGestureAvailable = { 
                    coroutineScope.launch { indicatorState.showIndicator() } 
                },
                onGesture = onPlayPauseButtonClicked,
            ),
    ) {
        OneHandedGestureClickIndicator(
            gestureConfiguration = gestureConfig,
            indicatorState = indicatorState,
        ) {
            val icon = if (playerUiModel.playbackState.isPlaying) Icons.Filled.Pause else Icons.Filled.PlayArrow
            Icon(icon, contentDescription = "Play or Pause")
        }
    }

    Sample app showing gesture hint for media controls

    We are already seeing early adoption of these APIs from partners like Spotify, who are using one-handed gestures to make music control more seamless on the go. By adopting the Modifier.oneHandedGesture into their Wear OS app, Spotify allows users to play or pause their music with the primary gesture action, which on Pixel Watch devices is the double-pinch gesture. This action triggers the same behavior as the physical play/pause button, and the user doesn’t  need to touch the screen.

    Spotify app with gesture integration

    Bring one-handed gestures to your app

    You can begin experimenting with one-handed gestures today in the 1.7 beta release of Compose for Wear OS.

    Ensure your app is running on Wear OS 7, which provides the underlying platform support for gesture detection. Check out our new one-handed gestures developer guide  to see how you can start building more convenient experiences for your users.

    Bringing Chrome to ARM64 Linux Devices

    We’re excited to announce that Google will launch Chrome for ARM64 Linux devices in Q2 2026, following the successful expansion of Chrome to Arm-powered macOS devices in 2020 and Arm-powered Windows devices in 2024.

    Launching Chrome for ARM64 Linux devices allows more users to enjoy the seamless integration of Google’s most helpful services into their browser. This move addresses the growing demand for a browsing experience that combines the benefits of the open-source Chromium project with the Google ecosystem of apps and features.

    This release represents a significant undertaking to ensure that ARM64 Linux users receive the same secure, stable, and rich Chrome experience found on other platforms.

    Get the best of the Google ecosystem

    With Chrome, you are able to leverage the full power of the Google ecosystem, providing a more cohesive and feature-rich environment designed for convenience and cross-device continuity. By signing into a Google Account, your bookmarks, browsing history, and open tabs follow you across devices. You can easily access the best extensions the Chrome Web Store has to offer, without needing to use specialized tools or alter developer settings. And you can effortlessly translate webpages with a single click.

    Use the browser that is secure by design

    Chrome also offers the added benefit of Google’s strongest security protections. Enabling Enhanced Protection in Safe Browsing offers real-time protection against phishing and malware by leveraging AI alongside Google’s list of known threats. With the Google Pay integration you can easily and securely manage your payments, using Chrome autofill for an added level of convenience. And the Google Password Manager lets you securely store, generate, and sync complex passwords across all your devices, eliminating the need to memorize multiple logins. It goes beyond simple storage by actively monitoring your credentials for data breaches and providing "Password Checkup" alerts if any of your accounts are compromised.

    Partnering with the industry

    Last year, NVIDIA introduced the DGX Spark, an AI supercomputing device that packs its Grace Blackwell architecture into a compact, 1-liter form factor. Google is partnering with NVIDIA to make it easier for DGX Spark users to install Chrome. Users with other Linux distributions can also install the ARM64 version of Chrome by visiting chrome.com/download.

    This launch marks a major milestone in our commitment to the Linux community and the Arm ecosystem. We look forward to seeing how developers and power-users leverage Chrome on this next generation of high-performance devices.

    Android Sets New Record for Mobile Web Performance

    A core part of the Android experience is the web. Whether you are browsing in Chrome or using one of the >90% of Android apps that utilize WebView, the speed of the web defines the speed of your phone. Today, we are proud to celebrate a major milestone: Android is now the fastest mobile platform for web browsing.

    Through deep vertical integration across hardware, the Android OS, and the Chrome engine, the latest flagship Android devices are setting new performance records, outperforming all other mobile competitors in the key web performance benchmarks Speedometer and LoadLine and providing a level of responsiveness previously unseen on mobile.

    Android flagship phones reach new high-scores in
    web performance benchmarks (Chrome 146, March 2026)

    Why web performance matters

    Web performance isn't just about high scores—it’s about how your device feels every day. On Android, web content and its performance is central to the user experience.

    Whether searching for information, catching up on the latest news, or online-shopping, Android users spend a significant portion of their daily screen time interacting with web content. Chrome is one of the most popular Android apps in the US and worldwide. Furthermore, this usage increases sharply on tablets and foldables, where productivity use cases are key.

    While the web is clearly important, a great web experience necessitates a fast browser and device: Modern websites are highly complex, with more than 200 million active sites serving everything from blog posts with dynamic ad auctions to desktop-class productivity tools. This complexity makes for a demanding workload that can stress even powerful devices.

    To ensure a high-quality user experience, we focus on two critical pillars when evaluating web performance: responsiveness and page load speed.

    Speedometer: Measuring web responsiveness

    Speedometer is the collaborative industry standard used by all major browser engine developers to measure web app responsiveness. It simulates real-world user actions—like adding items to a to-do list—to measure interaction latency.

    While synthetic, Speedometer's workloads offer high consistency and are built using relevant, state-of-the-art web frameworks, such as React, Angular or jQuery, and include to-do apps, text editors, chart rendering, and a mock news portal.

    Speedometer scores have a strong correlation (-0.8) with 99th-percentile interaction latency (INP) in the field. Thus, a higher Speedometer score directly translates to a more fluid, snappy feeling when you tap, scroll, or type on a website.

    LoadLine: Measuring the complete page load

    While interaction responsiveness is vital, it’s only half of the story. Users also care about how fast a page appears after they click a link. To measure this, Chrome and Android teams worked with Android SoC and OEM partners to develop LoadLine, an emerging end-to-end benchmark that simulates the complete process of loading a website.

    Where traditional benchmarks often focus on synthetic tasks, LoadLine uses recorded, stable versions of select real-world websites. This includes simpler and more complex sites with varied characteristics, reflecting the most important types of mobile web content, such as shopping, search, and news portals.

    LoadLine has proven that Android's page load performance is world-class: Top tier Android phones score up to 47% higher than non-Android competitors. And this matters: LoadLine scores also correlate well (-0.8) with median and high-percentile page load latency in the field.

    Speedometer (left) and examples of LoadLine workloads (right)

    Success through vertical optimization

    Android’s current lead is the result of a concerted effort to tune the entire "stack"—from silicon to software.

    We encouraged our Android partners to evaluate and tune their devices against Speedometer and LoadLine. While advances in SoCs' core performance build the foundation for fast web experiences, tuning of the OS and browser software stack are critical to utilize the hardware effectively. Collaborating with select SoC and OEM partners, we utilized Speedometer and LoadLine to optimize Chrome and kernel scheduler policies.

    As a result of these improvements, some Android flagship phones improved their Speedometer and LoadLine scores by 20-60% year-over-year, compared to their respective predecessor models. And these improvements translate to faster real-world web performance: Today, page loads are 4-6% faster and high-percentile interactions 6-9% faster on these newer models, for real users in the field.

    We invite all developers and hardware partners to join us in using these benchmarks to push the boundaries of what’s possible on the mobile web.

    JetStream 3: A modern benchmark for high-performance, compute-intensive Web applications

    We’re incredibly excited to announce the release of JetStream 3, built in close collaboration with Apple, Mozilla, and other partners in the web ecosystem!

    While we’ve covered the high-level details of this release in our shared announcement blog post, we wanted to take a moment here to dive a little deeper. In this post, we’ll pull back the curtain on the benchmark itself, explore the methodology behind our choices, and share the motivations driving these major updates.


    Why Do We Benchmark, Anyway?

    Before we get into the "what," it helps to talk about the "why." Why do browser engineers care so much about benchmarks?

    At its core, benchmarking serves as a critical safety net for catching performance regressions before they ever reach users. But beyond that, benchmarks act as a powerful motivation function—a sort of "gamification" for browser engineers. Having a clear target helps us prioritize our efforts and decide exactly which optimizations deserve our focus. It also drives healthy competitiveness between different browser engines, which ultimately lifts the entire web ecosystem.

    Of course, the ultimate goal isn't just to make a number on a chart go up; it's to meaningfully improve user experience and real-world performance.

    Driven by Open Governance

    Just like Speedometer 3, JetStream 3 is the result of a massive collaborative effort across all major browser engines, including Apple, Mozilla, and Google.

    We adopted a strict consensus model for this release. This means we only added new workloads when everyone agreed they were valuable and representative. This open governance model has led to an incredibly productive collaboration with buy-in from multiple parties, ensuring the benchmark serves the best interests of the overall Web ecosystem.

    Ripe for an Update

    The last major release, JetStream 2, came out in 2019. In the technology space—and especially on the Web—six years is an eternity.

    There's a well-known concept in economics called Goodhart's Law, which states that when a measure becomes a target, it ceases to be a good measure. Over time, engines naturally optimize for the specific patterns of a benchmark, and the metrics slowly lose their correlation with real-world performance. Speedometer recently received a massive update to account for this, and it only makes sense that JetStream is next in line.

    JetStream vs. Other Benchmarks

    You might be wondering: with the recent release of Speedometer 3, why do we need another benchmark?

    While Speedometer is fantastic for measuring UI rendering and DOM manipulation, JetStream has a different focus: the computationally intensive parts of Web applications. We're talking about use cases like browser-based games, physics simulations, framework cores, cryptography, and complex algorithms.

    There are also practical engineering considerations. JetStream is designed so that it can run in engine shells—like d8, the standalone shell for V8. For engine developers, this is a massive advantage. Building a shell is significantly quicker than compiling a full browser like Chrome, allowing engineers to iterate faster. Because d8 is single-process, it also produces far less background noise, leading to more stable testing. This shell-compatibility also makes JetStream highly valuable for hardware and device vendors running simulators. It is a trade-off—a shell is slightly further removed from a full, real-world browser environment—but the engineering velocity it unlocks is well worth it.

    How We Select Workloads

    Building a benchmark requires a delicate balance between microbenchmarks and real applications.

    Microbenchmarks are great engineering tools; they have a high signal-to-noise ratio and make it easy to see the effects of one specific optimization. While they make sense for early improvements of new features, they also often encourage overfitting in the long run. Engines might optimize heavily for a tiny loop that looks great on the benchmark but does absolutely nothing to help real users.

    Because of this, a primary criterion for inclusion in JetStream 3 is that a workload should represent a real, end-to-end use case (or at least a highly abstracted form of one).

    We also heavily prioritized diversity. We don’t want workloads that all exercise the exact same hot loop. We want coverage across different frameworks, varied libraries, diverse source languages, and distinct toolchains.

    Finally, we had to lay down some practical ground rules:

    • Time: The full benchmark suite needs to complete in a few minutes.
    • Memory: It shouldn't consume so much RAM that it crashes low-end devices.
    • Network: It shouldn't require massive payload transfers.
    • Consistency: Results should be deterministic and repeatable from one run to the next.

    Rethinking WebAssembly

    One of the most significant shifts in JetStream 3 is an increased focus and major update with regards to WebAssembly (Wasm).

    When JetStream 2 was created, Wasm was still in its infancy. Fast forward to today, and Wasm is significantly more widespread.

    Because the language has evolved so rapidly, JetStream 2 became outdated quickly. It only tested the Wasm MVP (Minimum Viable Product). Today, the Wasm spec includes powerful features like SIMD (single instruction, multiple data), WasmGC, and Exception Handling—none of which were being properly benchmarked.

    The ecosystem of tools has also completely transformed. The old workloads relied almost entirely on ancient versions of Emscripten compiling C/C++, often utilizing the deprecated asm.js backend via asm2wasm. Furthermore, some of the old microbenchmarks mis-incentivized the wrong optimizations. For example, the old HashSet-wasm workload rewarded aggressive inlining that actually hurt performance in real-world user scenarios.

    The New WebAssembly Workloads

    To fix this, we sought out entirely new Wasm workloads, introducing 12 in total.

    We expanded our toolchain coverage from just C++ to include five new toolchains: J2CL, Dart2wasm, Kotlin/Wasm, Rust, and .NET. This means we are now actively benchmarking Wasm generated from Java, Dart, Kotlin, Rust, and C#!

    These workloads represent actual end-to-end tasks, including:

    • argon2: A cryptographic password hashing function.
    • Transformers.js: Client-side machine learning heavily utilizing SIMD.
    • Cross-platform UI: Dart and Kotlin workloads utilizing WasmGC.
    • SQLite3: The ubiquitous database, replacing old WebSQL patterns.
    • .NET: As an example of full interpreters and language runtimes built on top of Wasm.

    These aren't tiny, kilobyte-sized modules anymore. These are multi-megabyte applications that produce diverse, complex flamegraphs, pushing engines to their limits. Reflecting its heightened importance on the modern web, Wasm now makes up 15-20% of the overall benchmark suite, up from just 7% in JetStream 2. Beyond new workloads, JetStream 3 also overhauls scoring to ensure that runtime performance—not just instantiation—is accurately reflected in the total score.

    The New and Updated JavaScript Workloads

    We have many new larger JavaScript workloads that better represent how JS is used in the wild. Additionally to just measuring the pure execution speed we have "startup" workloads that include parsing and frameworks setup code – more closely matching what happens on initial page load.

    • babylonjs: Startup and execution of the JavaScript core of the Babylon.js 3D engine.
    • bigint-noble-ed25519: BigInt stress-test that calculates an elliptic curve.
    • doxbee: Async code patterns using promises and async functions.
    • js-tokens js-tokenizer performance over JavaScript and JSX sources.
    • jsdom-d3-startup: D3 running in a JavaScript-only DOM implementation frequently used in unittests.
    • lazy-collections: JavaScript generators stress-test.
    • mobx-startup: Startup performance of the MobX state management library.
    • prismjs: Startup performance of a syntax highlighting library on various source files.
    • proxies: Two new workloads that stress tests proxy functionality using different libraries.
    • raytrace classes: Stress testing private and public fields with ES6 classes.
    • sync-fs: A mock file system, testing DataView, Promises, and synchronous generators / iterators.
    • threejs: A 3D particle system implemented with Three.js.
    • typescript-lib: Typescript v5.9 compilation speed.
    • validatorjs: String validation and sanitization with validator.js.
    • web-ssr: Server-side rendering (SSR) using React.

    Updated JavaScript Workloads

    • WTB: Updated version of the web-tooling benchmark measuring performance of various developer tools.
    • Sunspider: All separate workloads have been combined into a single item to reduce its weight.
    • Various older workloads were fixed to fix benchmark bugs and counter-act non real-world improvements.

    Conclusion

    With JetStream 3, the browser benchmarking space has made another big step forward and brought a new tool for browsers to improve performance for their valued users. Alongside Speedometer and MotionMark, these benchmarks give a clear view not only to browser vendors but also to users about various engine’s performance.

    If you’d like to contribute to the benchmark with your own workloads or have suggestions for how we can make it better, feel free to join the repository on GitHub. We’re continually iterating on these benchmarks and will have more updates on each in the future as well.

    Gemini 1.5 Pro Now Available in 180+ Countries; With Native Audio Understanding, System Instructions, JSON Mode and More

    Posted by Jaclyn Konzelmann and Megan Li - Google Labs

    Achieving privacy compliance with your CI/CD: A guide for compliance teams

    Posted by Fergus Hurley – Co-Founder & GM, Checks, and Evan Otero – Product Manager, Checks

    Introducing new AI tools on Google for Developers

    Posted by Chris Demeke – Senior Product Manager

    Celebrating 5 years of Jetpack Compose

    Posted by Rebecca Franks, Developer Relations Engineer, Nick Butcher, Product Manager, Loryn Hairston, Product Marketing Manager, Android


    Today, we officially celebrate five years since the release of Jetpack Compose 1.0. From version 1.0, announced on July 28th, 2021, to our latest 1.11 release, we’ve seen the APIs evolve significantly over the years, and we’re taking a moment to celebrate.

    When we officially announced the 1.0 release, we promised a simpler, faster, and more intuitive way to build native interfaces on Android. Looking back, it's safe to say that Compose didn’t just deliver on that promise, but also completely changed the Android ecosystem, with more than 68% of the top 1,000 apps using it in production today.

    History

    Over the last five years, Compose has grown steadily. In the early days, we explored showing you how to build layouts with the basic Box, Row, and Column. Today, we’ve expanded Compose to work not just on mobile devices, but to other form factors such as Compose for TV, WearOS, Glance for Widgets, and even display glasses with Jetpack Compose Glimmer.



    We recorded an Android Developers Backstage episode with Clara Bayarri, Engineering Lead for Jetpack, and two former leads of the team, Romain Guy and Chet Haase, along with Tor Norbye, Senior Engineering Director. In this episode, they discuss the history of Compose and the early days of development.




    Compose highlights over the years

    Looking back

    The beginnings of Compose were very different from what you know today. Two projects were happening in parallel inside the Android team.

    At the time, the Views toolkit team was thinking of unbundling the UI Toolkit into a library to help with development speed, and make it easier for developers to adopt and control updates. Meanwhile, a team was working on a novel idea to build declarative layouts by embedding XML inside Kotlin, which looked something like this:



    Those two efforts merged to produce what you know today - a fully declarative UI Toolkit that utilizes the power of a compiler plugin, runtime, and Kotlin:

    @Composable
    fun Newsfeed(stories: List<Story>) {
        LazyColumn {
            items(stories) { story ->
                Card {
                    val author = story.author
                    Image(painterResource(author.profilePhoto),
                        contentDescription = author.name)
                    Text(author.name)
                    Text(story.content)
                    if (story.hasCommentsEnabled()) {
                        for(comment in story.comments) {
                            Text(comment.mainContent)
                        }
                    }
                }
            }
        }
    }

    And you, the community, helped us very early on! Before 2021, Compose had a pre-alpha phase, which helped ensure Compose was fit to solve the problems of our developers.

    One of our favorite memories is the Android Dev Challenge. We challenged the community to build four different tasks with Compose, filling our feeds with Puppy apps, clocks, and weather apps, and giving us a ton of direct feedback that helped shape the 1.0 release.

    Compose has continued to evolve, from launching with a set of Material 2 components to now supporting Material 3 Expressive.

    Material 2 in Compose

    Material 3 Expressive in Compose

    Looking ahead

    As of today, Compose 1.11 is the latest version with 1.12 coming soon, offering so much more than 1.0, 5 years ago. This year, we introduced more adaptive APIs, such as FlexBox, Grid, MediaQuery, and Styles. These APIs let you advance to the next level of premium, adaptive UI development with Compose.

    At Google I/O 2026, we announced that we are now Compose-first, meaning that all future UI development will happen only in Compose, while the Views toolkit enters maintenance mode. Material Design is also shifting focus entirely to Compose, signaling an end to the findViewById era.

    Community is at the heart of Compose 

    Over the years, you’ve inspired us with creative examples of how you’ve used Compose, and we’d love to highlight a few more examples of where we’ve seen exciting work. JetBrains has been a great partner for Google with Compose, expanding Compose to work across platforms with Compose Multiplatform and enabling desktop, iOS, and web developers to also enjoy the benefits of Compose.

    We’ve really enjoyed following our most beloved newsletters from JetpackCompose.app’s Dispatch, AndroidWeekly, to jetc - helping Android Developers stay up-to-date with the latest in the world of Compose and Android.

    Another standout contributor is sinasamaki. They’ve created many delightful experiences using Compose, such as this fun ribbon modifier and the glitchy effect:


    Saket Narayan has also always been an inspiration when it comes to creating useful tools for Compose, such as telephoto, a library featuring support for pan and zoom gestures and automatic sub-sampling of large images, or the latest library, Touch Robot, which allows you to easily test interaction animations:

    paparazzi.gif(end = 3_000) {
      DebitCard(
        Modifier.testTag("card")
      )
    
      val touchRobot = rememberTouchRobot()
      LaunchedEffect(Unit) {
        touchRobot.onNode(hasTestTag("card")).performGesture {
          draw(
            path = createAndroidHeadPath(),
            duration = 3.seconds,
          )
        }
      }
    }
    
    /** A path drawing the Android head. */
    fun createAndroidHeadPath(bounds: Rect): Path = TODO()

    Jake Wharton, who has used Compose in innovative ways (like molecule, and even building UI with Compose for the terminal with mosaic). Chris Banes, who has built many Compose libraries over the years, with our most recent favourite - Haze for background blurring, and many of the Android Google Developer Experts like Akshay Chordiya, Huyen Tue Dao, and Katie Barnett, who’ve contributed to the success of Compose. But this is not about selecting individuals - there have been so many great contributors to the Compose codebase, and many of you continue to inspire us with your fun examples, libraries, and in-depth talks. Without the community, Jetpack Compose wouldn’t be as successful as it is today.

    Cheers to the next 5 years, and more! 

    Jetpack Compose has grown from an experimental idea into the standard for Android UI Development. Thank you to the entire Toolkit team at Google, and to the incredible global developer community that wrote libraries, filed bugs, and pushed the boundaries of what declarative UI can do.

    This week, we’ll be celebrating with some in-person birthday parties across the globe, and a live “Birthday party” on the Android Developers YouTube channel on July 30th at 13:00 UTC. During this time, we’ll hang out and discuss Compose and answer your questions!

    Cheers to the next 5 years, and happy composing!