Skip to content

[camera_android_camerax] Restore torch state between camera switches#11541

Draft
camsim99 wants to merge 12 commits intoflutter:mainfrom
camsim99:camx-i160956-torchstate
Draft

[camera_android_camerax] Restore torch state between camera switches#11541
camsim99 wants to merge 12 commits intoflutter:mainfrom
camsim99:camx-i160956-torchstate

Conversation

@camsim99
Copy link
Copy Markdown
Contributor

@camsim99 camsim99 commented Apr 20, 2026

WIP towards fixing flutter/flutter#160956.


Normal pull request information above the line.

This pull request is an attempt to "oneshot" fixing flutter/flutter#160956. Using antigravity to execute a plan that is collaboratively worked on. The "rules" are to not allow human authored code to camera_android_camerax and to not rely on human code review feedback for code iteration.

We can add documentation, skills, mcp servers, presubmit test etc. Basically any "support infrastructure" for development is allowed but the package changes must be generated as a single pass.
When we discover that the plan is not good enough we will blow the package changes away and either modify the plan or add more support infrastructure and try again.

For more information see the working doc in go/flutter-project-one-shot-torch

@camsim99 camsim99 force-pushed the camx-i160956-torchstate branch from 631b962 to b33f6ae Compare April 20, 2026 17:48
Comment on lines +17 to +18
> - **Option B (Ideal)**: Expose `hasFlashUnit()` via Pigeon and check it before attempting to restore torch.
>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camsim99 what option do you prefer here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is an indication that we have not given the agent sufficient context to understand the design principles for where we put what layer of logic. That said, our goal is to one-shot package changes not one shot plans. Let's see if there is also evidence that it does not understand where to put logic when it implements code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think A is the right approach for fixing the issue. B wouldn't fix it on its own but I do think it identified a good improvement for the plugin which is checking hasFlashUnit before trying to turn on the torch and giving back a helpful error if so.


---

#### [MODIFY] [android_camera_camerax.dart](file:///Users/camillesimon/packages/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agents can wander across the files they have access to. I think running this under the camera_android_camerax package is probably sufficient to keep the changes scoped there. My one worry is that it tries to modify the root federated api surface.

Maybe we say "Changes must be backwards compatible and should stay in camera_android_camerax"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also if this was a relative path I think in code review we could click it and read the file it was suggesting modifications to.


#### [MODIFY] [android_camera_camerax.dart](file:///Users/camillesimon/packages/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart)

- Add `_currentCameraDescription` instance variable to track active camera.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand why this needs a new variable. Why cant one of camera, cameraInfo or liveCameraState track which camera is "current"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the key to the map should be Camera2CameraInfo.from(cameraInfo).cameraId in java. Not sure what the dart equivalent is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need it to track the last torch state per camera. The suggested _currentCameraDescription.name is the equivalent of Camera2CameraInfo.from(cameraInfo).cameraId

- Update `_currentCameraDescription` in `createCameraWithSettings` and `setDescriptionWhileRecording`.
- Replace `torchEnabled` boolean with `Map<String, bool> _torchEnabledPerCamera = {};`.
- Update `setFlashMode` to use `_torchEnabledPerCamera` keyed by `_currentCameraDescription.name`.
- Modify `_enableTorchMode` to accept an optional `isRestore` boolean parameter (defaulting to `false`). If `isRestore` is true and the operation fails, the error should not be added to `cameraErrorStreamController`. `isRestore` is true when called during automatic restoration.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading the implementation of _enableTorchMode I dont think the input should be isRestore because in the context of that method the only thing it would decide is if an error should be thrown. The variable in _enableTorchMode should be "shouldThrowOnFailure" or something similar.

Then in the places where we call _enableTorchMode(<bool>. shouldThrowOnFailure=isRestore)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SGTM


Run tests using:
```bash
dart test test/android_camera_camerax_test.dart
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be dart run ../../../script/tool/bin/flutter_plugin_tools.dart dart-test --package=camera_android_camerax and we should remove it from below.


### Automated Tests

I will add unit tests in `android_camera_camerax_test.dart` to verify:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a test for restoring a torch mode to off in addition to restoring to on.

```

Additionally, run the following commands to ensure codebase health:
```bash
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camsim99 do you think we should ask/tell the agent to make the tool call an alias to make the below commands easier to read.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good idea!


Additionally, run the following commands to ensure codebase health:
```bash
# Format and Analyze
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we give some guidance to the prompt on when to run each of these tools.

Here is my suggestion.

  • Run format and analyze after every code edit.
  • Run fix if errors are found in analyze before attempting any other mitigations.
  • Run tests after each test case added and after finishing a unit of code work.
  • Run gradle check after touching build.gradle.kts files
  • Run license check after getting new files to their final state.
  • When you think you are completely done run readme, version, pubspec checks.
  • finally run publish check.

dart run ../../../script/tool/bin/flutter_plugin_tools.dart pubspec-check --packages=camera_android_camerax
dart run ../../../script/tool/bin/flutter_plugin_tools.dart readme-check --packages=camera_android_camerax
dart run ../../../script/tool/bin/flutter_plugin_tools.dart version-check --packages=camera_android_camerax
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The automated test need to include building the example app.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure when you want to add this in but we can also point it to the integration tests, making sure those all pass (and thus, the example app builds). Of course, it ideally also adds an integration test.

dart run ../../../script/tool/bin/flutter_plugin_tools.dart version-check --packages=camera_android_camerax
```

### Manual Verification
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to expanded to let the agent build the example app against an emulator.

Give the agent a command to start an emulator you have installed locally, We can worry about portability later. I also recommend we install the skill android-adb it is mit licensed.

adb shell dumpsys media.camera | grep -i "torch" can find the state of the torch.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 considerations we might consider including in the manual verification section since I hope to run the plan from more than just your host machine.

Hardware Emulation: In the AVD Manager, ensure your emulator's camera setting is set to something other than None. If it is set to Emulated or Webcam, the system image may or may not support torch operations depending on the API level and emulator build.

Unsupported State: If the emulator simply does not support the torch, CameraCharacteristics.FLASH_INFO_AVAILABLE will return false. You can verify this by checking the dumpsys output for "flash" availability. If it is unavailable, the plugin's attempts to toggle the torch will be ignored by the system, which is a common reason for the "silent failure" you might be seeing in the issue you linked.

Copy link
Copy Markdown
Contributor Author

@camsim99 camsim99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High level thoughts on the plan % the manual verification section (which will require an entirely new draft from me looks like)

Comment on lines +17 to +18
> - **Option B (Ideal)**: Expose `hasFlashUnit()` via Pigeon and check it before attempting to restore torch.
>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think A is the right approach for fixing the issue. B wouldn't fix it on its own but I do think it identified a good improvement for the plugin which is checking hasFlashUnit before trying to turn on the torch and giving back a helpful error if so.

- Update `_currentCameraDescription` in `createCameraWithSettings` and `setDescriptionWhileRecording`.
- Replace `torchEnabled` boolean with `Map<String, bool> _torchEnabledPerCamera = {};`.
- Update `setFlashMode` to use `_torchEnabledPerCamera` keyed by `_currentCameraDescription.name`.
- Modify `_enableTorchMode` to accept an optional `isRestore` boolean parameter (defaulting to `false`). If `isRestore` is true and the operation fails, the error should not be added to `cameraErrorStreamController`. `isRestore` is true when called during automatic restoration.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SGTM


#### [MODIFY] [android_camera_camerax.dart](file:///Users/camillesimon/packages/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart)

- Add `_currentCameraDescription` instance variable to track active camera.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need it to track the last torch state per camera. The suggested _currentCameraDescription.name is the equivalent of Camera2CameraInfo.from(cameraInfo).cameraId

```

Additionally, run the following commands to ensure codebase health:
```bash
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good idea!

dart run ../../../script/tool/bin/flutter_plugin_tools.dart pubspec-check --packages=camera_android_camerax
dart run ../../../script/tool/bin/flutter_plugin_tools.dart readme-check --packages=camera_android_camerax
dart run ../../../script/tool/bin/flutter_plugin_tools.dart version-check --packages=camera_android_camerax
```
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure when you want to add this in but we can also point it to the integration tests, making sure those all pass (and thus, the example app builds). Of course, it ideally also adds an integration test.

@reidbaker
Copy link
Copy Markdown
Contributor

Despite me being at next I am available to review this so we can make forward progress this week. Just ping me when it is ready for another review.

@camsim99 camsim99 requested a review from reidbaker April 24, 2026 16:37
#### [MODIFY] [pigeons/camerax_library.dart](file:///Users/camillesimon/packages/packages/camera/camera_android_camerax/pigeons/camerax_library.dart)

- Add `bool hasFlashUnit();` to `abstract class CameraInfo`.
- Run the Pigeon generator to update generated files.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we have to modify the plan here but I am wondering if the agents know how to use this library. I do think we should probably make sure that one of the automated verification steps will ensure that the generated files have been updated correctly and not by the agent.

- Add `bool hasFlashUnit();` to `abstract class CameraInfo`.
- Run the Pigeon generator to update generated files.

#### [MODIFY] [android/src/main/java/io/flutter/plugins/camerax/CameraInfoProxyApi.java](file:///Users/camillesimon/packages/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraInfoProxyApi.java)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove all global paths and replace them with relative paths? Or is this the result of having strong file selectors in your ide?

@reidbaker
Copy link
Copy Markdown
Contributor

reidbaker commented Apr 26, 2026

I think this plan is good enough for a first attempt.

@kevmoo has a concept he called when the agent is "tired" I am curious if this plan will max out the context window and need to be picked upbon another session mid way through.

Check out his "rules" here. https://github.com/kevmoo/sdk/blob/socket2/conductor%2Fcheat_sheet_for_the_agent.md

Depending on how the first prompt goes we may want to incorporate some of those.

@kevmoo
Copy link
Copy Markdown
Contributor

kevmoo commented Apr 26, 2026

I think this plan is good enough for a first attempt.

@kevmoo has a concept he called when the agent is "tired" I am curious if this plan will max out the context window and need to be picked upbon another session mid way through.

Check out his "rules" here. https://github.com/kevmoo/sdk/blob/socket2/conductor%2Fcheat_sheet_for_the_agent.md

Depending on how the first prompt goes we may want to incorporate some of those.

It's basically just "context window is full" – but it is fun to talk to the agent about it.

I EXPLICITLY say "DO NOT be passive aggressive about 'are we ready to call it a day on this project?' – just tell me your context window is getting full"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants