Short answer: a phone left running as a camera normally has more than one thing asking for frames — a file being written the whole time, and a browser somewhere on the same network that turns up for ninety seconds and goes away again. Camera2 fixes the list of outputs when the capture session is configured, so changing the list has meant building a new session. Android 17 adds
updateOutputConfigurations()toCameraCaptureSession, which the Android team describes as letting an app "dynamically attach and detach output surfaces without the need to reconfigure the entire camera capture session." It does not let a phone run a stream it could not run before. It changes what it costs to change the set — and on an unattended camera the set changes at exactly the moment you would least like a stutter. Background Camera RemoteStream is what I build; everything below is Android's description of Android's behaviour, quoted and linked.
Why the output list is the interesting part
A capture session is a contract. You hand Camera2 a set of surfaces — a recorder surface, an ImageReader, a preview — the framework works out whether the device can drive all of them together, and from then on the session delivers frames into that set.
For a camera on a shelf, almost every term of that contract really is constant. The sensor is the same sensor tomorrow. The orientation is settled the moment somebody props the phone up. The encoder settings are chosen once and left alone. There is one term that is not constant, and it changes several times a day: how many things want frames.
At three in the morning, one — the file. At six-fifteen, when the dog starts barking, two. A minute later, one again. Nothing about the scene changed; somebody just decided to look.
That is an odd shape for an API that was designed around configure-once. It is also, I think, why this particular Android 17 addition is easy to skim past: it reads like a photo-app convenience, and the camera it actually helps most is the one nobody is holding.
What apps did before, and what each option cost
There were two honest ways to handle an output that comes and goes, and both of them cost something.
Option one: configure everything at start-up and hold it. Build the session with the recorder surface and the streaming surface, whether or not anybody is watching, and simply stop reading from the second one when nobody is. Nothing has to change later, because nothing changes. You pay for it in memory and in bookkeeping, permanently, for a viewer that on most days never arrives. The Android 17 announcement names that cost directly — the new API is described as removing "the memory cost and code complexity of configuring and holding onto all camera output surfaces that your app might need during camera start up."
Option two: rebuild the session when the set changes. Configure the recorder alone, and when somebody opens the page, close the session and configure a new one with both surfaces. You pay nothing while nobody is watching. You pay at the transition, and the transition lands on top of a recording that is supposed to be continuous. Google's phrasing for what that produces is worth keeping: the change "helps to eliminate user-visible glitches or freezes during operation."
Neither option is a bug. They are two ends of the same trade, and every app that serves a live view off a recording device has picked one, usually without writing down that it was a choice.
What Android 17 actually added
From the Android 17 Beta 1 announcement, under Media and Camera:
We have introduced
updateOutputConfigurations()toCameraCaptureSession. This allows you to dynamically attach and detach output surfaces without the need to reconfigure the entire camera capture session. This change enables seamless transitions between camera use cases and modes (such as shooting still images vs shooting videos) without the memory cost and code complexity of configuring and holding onto all camera output surfaces that your app might need during camera start up. This helps to eliminate user-visible glitches or freezes during operation.
The published snippet is four lines of substance:
fun updateCameraSession(session: CameraCaptureSession, newOutputConfigs: List<OutputConfiguration>)) {
// Dynamically update the session without closing and reopening
try {
// Update the output configurations
session.updateOutputConfigurations(newOutputConfigs)
} catch (e: CameraAccessException) {
// Handle error
}
}
Two things worth noticing before anybody copies it. The signature as published carries a stray extra closing parenthesis after List<OutputConfiguration> — it will not compile as printed, which is a typo in the announcement rather than anything about the API, and is mentioned here only so you do not spend ten minutes doubting your own brackets. And the failure mode is CameraAccessException, which is the same exception family the rest of Camera2 throws: this is an operation on a live session, so it can be refused the way any other camera operation can be refused.
The shape matters more than the signature. It is a method on an existing session, taking the new list. The session identity survives. Whatever was already streaming keeps streaming while the set around it changes.
Why this lands differently on an unattended camera
The use case the announcement leads with is a photo app switching between stills and video. That is a mode change the user asked for and is watching happen, with a finger still on the screen. A quarter-second of black there is mildly annoying and instantly forgiven.
A phone doing camera duty has the inverse property. The moment its output set changes is, by definition, the moment somebody has decided to look — and the recording that must not skip is running underneath the whole time. The disturbance and the reason for the disturbance arrive together, which is the worst possible pairing for working out afterwards what happened.
That gives you a diagnostic, and it is the practical thing to take away from all of this. If the live view takes a visible beat to appear, and the recorded file has a discontinuity at that same timestamp, the network is probably not your culprit. A slow network makes the view late; it does not put a break in a file that is being written locally. A session reconfiguration does both at once, because both outputs hang off the same session.
Four things this does not do
It does not change what your phone can drive at once. How many outputs a device guarantees, and at what sizes, is set by its Camera2 hardware level, and that table has not moved. I wrote that part up separately in One Camera, Two Consumers. updateOutputConfigurations() changes how you get from one legal combination to another; it does not make an illegal one legal.
It does not make the second stream cheap. Encoding for a viewer still costs what it costs while the viewer is there. What goes away is the standing cost of being ready for a viewer who is not.
It does not touch the reason a background camera is hard in the first place. Holding a camera open with the display off is a foreground-service problem, and that has its own rules and its own failure modes — the FGS type walkthrough is here. Nothing in Android 17's session API relaxes any of it.
And it is an Android 17 API. I have not measured it, on any device, and this piece deliberately does not tell you what it saves in milliseconds, because I do not know. What I can tell you is that the platform has now written down, in its own words, that both costs were real — and that is useful today even on a phone that will never see the API, because it tells you which of the two you have been paying.
The test, if you want to know which one you are paying
It takes about five minutes and needs no beta build.
- Start the recording and leave it alone for two or three minutes with nothing watching.
- Open the live view. Note, roughly, whether the picture appears more or less at once or after a distinct pause.
- Close it. Wait a minute. Open it again.
- Stop the recording and scrub the file to the timestamps where you opened and closed.
A clean file across all four transitions means the app is holding its outputs configured — option one, and you are paying for it in memory the entire time the camera runs. A break, a dropped second, or a jump in the timeline at exactly those moments means you are on option two, and the cost is landing on the recording rather than on the process size. Neither result is a defect, so there is nothing here to file a bug about. What the five minutes buy you is the end of guessing: if the file shows the transitions, plan your viewing around them; if it does not, stop worrying about them and go spend the attention on something that is actually costing you frames.
Sources. The API, the quoted description and the snippet are from Google's Android 17 Beta 1 announcement (13 February 2026), section Media and Camera → Dynamic Camera Session Updates. The class it lands on is CameraCaptureSession. Disclosure: I work on Background Camera RemoteStream, an app in this category, so treat the platform behaviour as the useful part and the framing as coming from somebody with an interest.











