Когда объект TextureView "Потребительская сторона" закрыт?

Один из официальных образцов Google для Camera2 API имеет та же самая проблема BufferQueue has been abandoned, как показано в:

В частности, пример приложения вызывает метод closeCamera() из onPause() фрагмента, где closeCamera() вызывает close() на CameraCaptureSession, затем close() на CameraDevice, затем close() на ImageReader (используется для фактической съемки). После close() on CameraDevice, когда в LogCat появляется несколько вхождений вышеупомянутого сообщения BufferQueue has been abandoned, хотя я получаю сообщение только на некоторых устройствах Android 5.1 (Nexus 4 и Nexus 7 2013), а не на других (Nexus 5 и Nexus 6).

Комментарий fadden:

Если пользовательская сторона закрыта перед вводом onPause(), сообщения ожидаются.

Когда TextureView "сторона потребителя" будет закрыта, и почему тогда?

Код примера Google не проактивно ничего не делает, чтобы закрыть TextureView, который я вижу. И, поскольку TextureView все еще может быть видимым при паузе, я ожидал, что "потребительская сторона" не будет затронута во время onPause(), но, возможно, позже в onStop().

Хотя я понимаю, что это сообщение (несмотря на ошибку) является доброкачественным, я пытаюсь понять, как избавиться от него, если не по какой-либо другой причине, чем для того, чтобы не дать мне снова и снова спрашивать, почему мой код регистрирует эту ошибку. Я надеюсь, что, понимая больше об этой "стороне потребителя", я могу понять, как лучше убирать вещи, когда пользователь выходит из действия или фрагмента, использующего Camera2, и избегает этой ошибки.

Ответ 1

Ожидаете ли вы вызывать метод обратного вызова камеры с закрытым состоянием, прежде чем выйти из режима onPause?

Пока этот обратный вызов не срабатывает, камера все еще может выполнять незавершенную работу, а определение close() - завершить все ожидающие запросы захвата до выключения устройства. Это можно ускорить, вызвав abortCapture() перед вызовом функции close().

Некоторые устройства (например, N5 и N6) в настоящее время блокируют вызов close(), чтобы при возврате все ожидающие работы выполнялись, но это детализация реализации, которые, как я думаю, наша выборка неосторожно полагается на сегодняшний день.

Однако мы обычно хотим, чтобы приложения вызывали close() и сразу же оставили onPause(), чтобы избежать зависания потока пользовательского интерфейса при ожидании закрытия аппаратного обеспечения камеры. Но сегодня это еще не реальность.

Другими словами, close() предполагается асинхронным и не на всех устройствах. Но мы хотели бы, чтобы вы могли запускать и забывать об этом, поэтому эти сообщения об ошибках должны быть адресованы на стороне устройства камеры (не спам журнала, когда цель повторного запроса уходит в середине операции).

Другая причина, почему вызов close() и exit onPause() не рекомендуется сегодня, заключается в том, что это предотвратит открытие другими приложениями камера в своих вызовах onResume(), что вызовет ложные ошибки при переключении между приложениями камеры.

Итак, суммируем:

Пока: Подождите CameraDevice.StateCallback # onClosed для вызова перед выходом onPause() после вызова CameraDevice # close().

В какой-то будущий момент: будет безопасно просто вызвать close() и выйти onPause; структура будет правильно разрешать подключению следующего приложения, а не спаму вашего журнала. Извините, что сегодня это не состояние!

Ответ 2

Что касается фактического вопроса - "когда" TextureView "потребительская сторона" закрыта ", я не знаю точное время, но это, безусловно, после возвращения onPause.

Грубо, TextureView содержит поверхность GL, и как только пользовательский интерфейс для активности больше не виден, эти ресурсы срываются. Как только это произойдет, SurfaceTexture, выданный TextureView, уже недействителен, и все существующие пользователи этой SurfaceTexture (или Surfaces, сделанные из него) начнут получать эти ошибки. Метод TextureView.SurfaceTextureListener.onSurfaceTextureDestroyed должен быть вызван TextureView прямо перед этим.

Итак, в качестве альтернативы вы можете вернуть false из onSurfaceTextureDestroyed, чтобы избежать его освобождения во время разрыва интерфейса, а вместо этого ждать, когда onClosed будет запущен, а затем в onClosed выпустить TextureView SurfaceTexture самостоятельно. Тем не менее, я недостаточно хорошо знаком с интерфейсом UI/View, чтобы точно знать, что это сработает, и поскольку некоторые из лежащих в основе нативных поверхностей выпущены в любом случае, вы все равно можете увидеть заброшенные ошибки с этим подходом.

Если вам интересно, верхние уровни соответствующего кода находятся в TextureView, особенно destroySurface, хотя вам нужно будет понять всю систему Android UI, чтобы разобраться, когда именно вызывается метод destroySurface и каковы его эффекты.