惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
Jina AI
Jina AI
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
C
Cybersecurity and Infrastructure Security Agency CISA
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
S
Securelist
S
Security Affairs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
L
LINUX DO - 热门话题
博客园 - 三生石上(FineUI控件)
T
Threatpost
T
The Blog of Author Tim Ferriss
C
CERT Recently Published Vulnerability Notes
IT之家
IT之家
P
Palo Alto Networks Blog
Microsoft Azure Blog
Microsoft Azure Blog
Spread Privacy
Spread Privacy
Cyberwarzone
Cyberwarzone
腾讯CDC
L
LangChain Blog
Know Your Adversary
Know Your Adversary
C
CXSECURITY Database RSS Feed - CXSecurity.com
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
T
Tor Project blog
AWS News Blog
AWS News Blog
T
Tenable Blog
NISL@THU
NISL@THU
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
H
Hackread – Cybersecurity News, Data Breaches, AI and More
人人都是产品经理
人人都是产品经理
MongoDB | Blog
MongoDB | Blog
MyScale Blog
MyScale Blog
D
DataBreaches.Net
Microsoft Security Blog
Microsoft Security Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
量子位
美团技术团队
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
The GitHub Blog
The GitHub Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
The Honour System Running Your Phone's Speaker
Maxi · 2026-06-19 · via DEV Community

Maxi

Part one of a short series on who actually controls the audio coming out of your Android phone, and why almost none of it is the app you think.

A few days ago I was listening to music on my phone when I opened an unrelated app, one built around an endless feed. The very first screen autoplayed a short video. My music stopped. Not paused and then resumed, not lowered for a moment under the clip. It simply stopped, and I had to go back and press play again.

This is the kind of thing that is easy to never think about. It happens constantly. But this time it nagged at me, because the app that silenced my music was not a media app. It had no obvious business being in charge of my audio. And yet a five-second clip I never asked to watch reached across the system and shut down a dedicated music player. I wanted to understand how a random app gets that power, and whether it is even power at all.

One speaker and a dozen claimants

At any given moment, there is usually exactly one stream of sound that I actually care about, but there are dozens of apps installed, any number of which might want to make noise at the same time. Two apps deciding to play audio at once is not some rare edge case. It is the ordinary condition of a phone. A navigation prompt needs to talk over a podcast. A video call wants the channel a song is currently using. A game wants to play effects while a streaming app sits paused in the background.

So someone, somewhere, has to arbitrate. The question that would not leave me alone was where that arbitration lives and what shape it takes. Is there a single authority that hands out the speaker like a token? Does the loudest or newest app simply win? My instinct said this had to be a system-level concern, because no single app can see what every other app is doing. But the thing I had actually watched happen, a non-media app casually overruling a media app, hinted that the rules were stranger than a tidy priority list.

The system asks, it does not take

The piece I had been missing has a name: audio focus. Once I started thinking in those terms, the behaviour stopped looking like a hostile takeover and started looking like something far more polite, almost to a fault.

My understanding is that an app does not seize the speaker. It asks for it. When an app wants to play sound, the well-behaved thing to do is request audio focus from the system through AudioManager, the per-app gateway into Android's audio service. The system tracks who currently holds focus, conceptually a stack of requests, and when a new app asks, the previous holder is told it has lost focus. Here is the part that reframed everything for me: nobody forces the previous app to go quiet. The system taps it on the shoulder and informs it that someone else has asked to play. What happens next is left entirely to the app that was interrupted.

So my music was never shut down by force. The player that was running received a message saying it had lost focus, and its own code decided to pause. The autoplay video did not reach into the music player and stop it. It asked the system for the floor, and the music player chose to yield.

The vocabulary of an interruption

What convinced me this was deliberate design rather than a lucky accident is the vocabulary the system uses for losing focus. It is not a single off switch. When an app loses focus, it is told roughly how it lost it, and the names of those signals read like a small grammar of courtesy.

private val focusListener = AudioManager.OnAudioFocusChangeListener { change ->
    when (change) {
        AudioManager.AUDIOFOCUS_LOSS ->
            player.pause()        // someone took the floor indefinitely

        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT ->
            player.pause()        // a brief interruption, focus should return

        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK ->
            player.lowerVolume()  // keep playing, just step aside quietly

        AudioManager.AUDIOFOCUS_GAIN ->
            player.resume()       // the floor is yours again
    }
}

Reading that list told me more about the intent than any specification could. AUDIOFOCUS_LOSS is a permanent goodbye: another app has taken the floor and does not expect to hand it back soon, so the correct response is to stop and let go. AUDIOFOCUS_LOSS_TRANSIENT is a short interruption, the kind an incoming call or a navigation prompt creates, with the expectation that focus returns shortly. And then there is the one I find most telling, AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK, which does not ask the music to stop at all. It asks it to drop its volume and keep playing underneath, the way Maps quiets your music to a murmur while it tells you to turn left, then lets it rise again afterward.

This is why my music stopped outright instead of ducking or pausing and resuming. My guess is that the autoplay video requested a full, indefinite gain, which handed my music player an AUDIOFOCUS_LOSS, the permanent kind. The player did the right thing for a permanent loss. It stopped, and it did not attempt to resume on its own. Compare that to a phone call, which requests transient focus, hands the music a transient loss, and lets it resume the instant the call ends. The same machinery, a different degree of politeness, and you feel the difference as a user without ever needing the words for it.

What makes this almost funny is that I doubt anyone at the company behind that feed app consciously decided to interrupt my music. If their video player is built on one of the common media libraries, requesting audio focus is often the default. Somewhere deep in the stack, a sensible library made a reasonable assumption about how media should behave, and that assumption was enough to stop my music.

An honour system, with everything that implies

The detail I keep turning over is that this whole arrangement runs on trust. Audio focus is advisory. The system can tell an app it has lost focus, but through this mechanism alone it cannot force the app to actually fall silent. A lazily written app can simply ignore the loss and keep playing, and you are left with two streams wrestling over your ears. Most of us have met that app.

So why would the designers choose a cooperative model over a strict one, where the system rips audio away from whoever was holding it? My guess is that the strict version is quietly worse. A forced handover would mean the system decides, for every app, what losing audio ought to mean. Should the sound stop, or pause, or duck? Only the app that was playing knows whether it is a podcast that must pause precisely so you do not miss a sentence, or an ambient track that should simply fade. By making the loss a message rather than a command, the system hands that decision to the one party with enough context to get it right. The cost is plain: it only works when apps cooperate. The reward is that, when they do, the result is far more humane than any central rule could manage.

The floor underneath the floor

What I find quietly strange is that the speaker on a device I own runs almost entirely on an honour system. The app playing my music was never truly in control of whether it kept playing. It was just the most recent voice in a polite, system-wide conversation about who gets the floor, and it stepped back the moment it was asked.

But this only explains why one sound stops when another starts. It says nothing about the moments when sounds do not stop at all: a notification chiming cleanly over the top of a song, an alarm and music sounding in the very same instant. If audio focus were the entire story, those moments should not be possible. Which means the floor I have been describing is not really one floor, and something beneath it is doing work I have not yet accounted for. That is where I want to look next.