Repository: flutter
Issue: [camera] [ios] Preview freezes when using torch with ultrawide or telephoto camera
Labels: e: device-specific,platform-ios,p: camera,package,P2,team-ios,triaged-ios

Hi.  My app requires access to the torch and a preview from the telephoto lens if using a 3-lens iPhone (e.g. iPhone 12).   However, for 2 of the four camera on this kind of phone the preview freezes if the torch is active.

I have repeated the behaviour with a few different torch plugins so I think this is a camera issue rather than a torch issue.

## Steps to Reproduce

- if I select cameras[0] or cameras[1] (front-facing) I can generate a live preview with torch active
- If I select cameras [2] (telephoto) or [3] (ultrawide), the preview freezes while the torch is active and unfreezes when I turn the torch off. There are no error messages reported, so there is nothing obvious to 'fix' from my end.  

1. Execute `flutter run` on the code sample <!-- (see "Code sample" section below) -->
2. Select a camera by changing the index value in onNewCameraSelected in initState method.
3. Toggle the torch using the text button

**Expected results:** Preview should not freeze for any cameras

**Actual results:** Preview freezes for cameras 2 and 3 but does not freeze for camera 0 and 1

## code snippet

````
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:torch_controller/torch_controller.dart';

List<CameraDescription> cameras = [];

void main() async {
  TorchController().initialize();
  WidgetsFlutterBinding.ensureInitialized();
  cameras = await availableCameras();

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        // enable Material 3
        useMaterial3: true,
        colorScheme: const ColorScheme.light(
          primary: Colors.indigo,
          outline: Colors.indigo,
        ),
      ),
      home: const CameraTest(),
    );
  }
}

class CameraTest extends StatefulWidget {
  const CameraTest({Key? key}) : super(key: key);

  @override
  _CameraTestState createState() => _CameraTestState();
}

class _CameraTestState extends State<CameraTest> with WidgetsBindingObserver {
  double? previewHt;
  CameraController? controller;
  bool _isCameraInitialized = false;
  TorchController? tc;



  void onNewCameraSelected(CameraDescription cameraDescription) async {
    final previousCameraController = controller;
    // Instantiating the camera controller
    final CameraController cameraController = CameraController(
      cameraDescription,
      ResolutionPreset.high,
      imageFormatGroup: ImageFormatGroup.bgra8888,
    );

    // Dispose the previous controller
    await previousCameraController?.dispose();

    // Replace with the new controller
    if (mounted) {
      setState(() {
        controller = cameraController;
      });
    }

    // Update UI if controller updated
    cameraController.addListener(() {
      if (mounted) setState(() {});
    });

    // Initialize controller
    try {
      await cameraController.initialize();
    } on CameraException catch (e) {
      print('Error initializing camera: $e');
    }
    // Update the Boolean
    if (mounted) {
      setState(() {
        _isCameraInitialized = controller!.value.isInitialized;
      });
    }
  }

  @override
  void initState() {
    onNewCameraSelected(cameras[2]); // < change to 0 or 1 and preview is fine
    tc = TorchController();
    super.initState();
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    final CameraController? cameraController = controller;

    // App state changed before we got the chance to initialize.
    if (cameraController == null || !cameraController.value.isInitialized) {
      return;
    }

    if (state == AppLifecycleState.inactive) {
      // Free up memory when camera not active
      cameraController.dispose();
    } else if (state == AppLifecycleState.resumed) {
      // Reinitialize the camera with same properties
      onNewCameraSelected(cameraController.description);
    }
  }

  @override
  Widget build(BuildContext context) {
    previewHt = MediaQuery.of(context).size.height*.7;

    return Scaffold(
        body: Column(
          children: [
            SizedBox(
              height: previewHt,
              child: _isCameraInitialized
                  ? AspectRatio(
                aspectRatio: 1 / controller!.value.aspectRatio,
                child: controller!.buildPreview(),
              )
                  : Container(),
            ),
            Center(
              child: TextButton(
                child: const Text('Toggle Torch',
                  style: TextStyle(fontSize: 20),),
              onPressed: ()=>tc!.toggle(),),
            )
          ],
        )
    );
  }
}

````

<!-- Finally, paste the output of running `flutter doctor -v` here. -->

```
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 3.1.0-0.0.pre.1507, on macOS 12.2.1 21D62 darwin-arm, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.1)
[✓] VS Code (version 1.71.2)
[✓] Connected device (3 available)
[✓] HTTP Host Availability

• No issues found!

```

</details>


<!--
      Consider also attaching screenshots and/or videos to better
      illustrate the issue.

      You can upload them directly on GitHub.
      Beware that video file size is limited to 10MB.
-->