1418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin/* 2418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * Copyright (C) 2013 The Android Open Source Project 3418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * 4418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 5418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * you may not use this file except in compliance with the License. 6418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * You may obtain a copy of the License at 7418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * 8418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 9418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * 10418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * Unless required by applicable law or agreed to in writing, software 11418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 12418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * See the License for the specific language governing permissions and 14418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin * limitations under the License. 15418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin */ 16418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 177b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala#define LOG_TAG "Camera2-FrameProcessorBase" 18418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin#define ATRACE_TAG ATRACE_TAG_CAMERA 19418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin//#define LOG_NDEBUG 0 20418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 21418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin#include <utils/Log.h> 22418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin#include <utils/Trace.h> 23418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 247b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala#include "common/FrameProcessorBase.h" 257b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala#include "common/CameraDeviceBase.h" 26418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 27418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkinnamespace android { 28418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkinnamespace camera2 { 29418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 307b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville TalvalaFrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) : 3171381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin Thread(/*canCallJava*/false), 32204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He mDevice(device), 33204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He mNumPartialResults(1) { 34204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He sp<CameraDeviceBase> cameraDevice = device.promote(); 35204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He if (cameraDevice != 0 && 36204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He cameraDevice->getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) { 37204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He CameraMetadata staticInfo = cameraDevice->info(); 38204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT); 39204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He if (entry.count > 0) { 40204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He mNumPartialResults = entry.data.i32[0]; 41204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He } 42204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He } 43418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin} 44418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 457b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville TalvalaFrameProcessorBase::~FrameProcessorBase() { 46418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin ALOGV("%s: Exit", __FUNCTION__); 47418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin} 48418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 497b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvalastatus_t FrameProcessorBase::registerListener(int32_t minId, 5025a0aef19e170d2695f64b4c48296e7914155a88Zhijun He int32_t maxId, wp<FilteredListener> listener, bool sendPartials) { 51418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin Mutex::Autolock l(mInputMutex); 52954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra List<RangeListener>::iterator item = mRangeListeners.begin(); 53954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra while (item != mRangeListeners.end()) { 54954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra if (item->minId == minId && 55954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra item->maxId == maxId && 56954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra item->listener == listener) { 57954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra // already registered, just return 58954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra ALOGV("%s: Attempt to register the same client twice, ignoring", 59954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra __FUNCTION__); 60954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra return OK; 61954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra } 62954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra item++; 63954d248e02e19f8ecd165804b7d063d346154f4cGaurav Batra } 64418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin ALOGV("%s: Registering listener for frame id range %d - %d", 65418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin __FUNCTION__, minId, maxId); 6625a0aef19e170d2695f64b4c48296e7914155a88Zhijun He RangeListener rListener = { minId, maxId, listener, sendPartials }; 67418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin mRangeListeners.push_back(rListener); 68418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin return OK; 69418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin} 70418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 717b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvalastatus_t FrameProcessorBase::removeListener(int32_t minId, 7271381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin int32_t maxId, 7371381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin wp<FilteredListener> listener) { 74418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin Mutex::Autolock l(mInputMutex); 75418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin List<RangeListener>::iterator item = mRangeListeners.begin(); 76418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin while (item != mRangeListeners.end()) { 77418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin if (item->minId == minId && 78418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin item->maxId == maxId && 79418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin item->listener == listener) { 80418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin item = mRangeListeners.erase(item); 81418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } else { 82418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin item++; 83418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 84418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 85418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin return OK; 86418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin} 87418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 887b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvalavoid FrameProcessorBase::dump(int fd, const Vector<String16>& /*args*/) { 89418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin String8 result(" Latest received frame:\n"); 90418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin write(fd, result.string(), result.size()); 91215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin 92215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin CameraMetadata lastFrame; 93215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin { 94215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin // Don't race while dumping metadata 95215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin Mutex::Autolock al(mLastFrameMutex); 96215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin lastFrame = CameraMetadata(mLastFrame); 97215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin } 98215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin lastFrame.dump(fd, 2, 6); 99418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin} 100418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 1017b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvalabool FrameProcessorBase::threadLoop() { 102418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin status_t res; 103418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 104a2e203bdb911bd5595723651d06ad91c330a7873Igor Murashkin sp<CameraDeviceBase> device; 105418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin { 10671381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin device = mDevice.promote(); 107418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin if (device == 0) return false; 108418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 109418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 110418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin res = device->waitForNextFrame(kWaitDuration); 111418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin if (res == OK) { 11271381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin processNewFrames(device); 113418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } else if (res != TIMED_OUT) { 1147b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala ALOGE("FrameProcessorBase: Error waiting for new " 115418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin "frames: %s (%d)", strerror(-res), res); 116418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 117418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 118418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin return true; 119418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin} 120418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 1217b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvalavoid FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) { 122418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin status_t res; 123418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin ATRACE_CALL(); 124cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei CaptureResult result; 1254345d5b57a93ec6d003df84f5cce2db7cccfbd86Igor Murashkin 1264345d5b57a93ec6d003df84f5cce2db7cccfbd86Igor Murashkin ALOGV("%s: Camera %d: Process new frames", __FUNCTION__, device->getId()); 1274345d5b57a93ec6d003df84f5cce2db7cccfbd86Igor Murashkin 128cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei while ( (res = device->getNextResult(&result)) == OK) { 12971381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin 130cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei // TODO: instead of getting frame number from metadata, we should read 131cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei // this from result.mResultExtras when CameraDeviceBase interface is fixed. 132418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin camera_metadata_entry_t entry; 133418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 134cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT); 135418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin if (entry.count == 0) { 136418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin ALOGE("%s: Camera %d: Error reading frame number", 13771381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin __FUNCTION__, device->getId()); 138418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin break; 139418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 140418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin ATRACE_INT("cam2_frame", entry.data.i32[0]); 141418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 142cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei if (!processSingleFrame(result, device)) { 14371381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin break; 14471381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin } 145418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 146cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei if (!result.mMetadata.isEmpty()) { 147215bb3499c7eeea6303e55fac66452f2574c022aIgor Murashkin Mutex::Autolock al(mLastFrameMutex); 148cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei mLastFrame.acquire(result.mMetadata); 149418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 150418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 151418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin if (res != NOT_ENOUGH_DATA) { 152418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin ALOGE("%s: Camera %d: Error getting next frame: %s (%d)", 15371381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin __FUNCTION__, device->getId(), strerror(-res), res); 154418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin return; 155418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 156418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 157418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin return; 158418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin} 159418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 160cb0652e5a850b2fcd919e977247e87239efaf70eJianing Weibool FrameProcessorBase::processSingleFrame(CaptureResult &result, 161cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei const sp<CameraDeviceBase> &device) { 1624345d5b57a93ec6d003df84f5cce2db7cccfbd86Igor Murashkin ALOGV("%s: Camera %d: Process single frame (is empty? %d)", 163cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei __FUNCTION__, device->getId(), result.mMetadata.isEmpty()); 164cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei return processListeners(result, device) == OK; 16571381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin} 16671381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin 167cb0652e5a850b2fcd919e977247e87239efaf70eJianing Weistatus_t FrameProcessorBase::processListeners(const CaptureResult &result, 16871381051e2d048b2705c447b3d59db6e972493eeIgor Murashkin const sp<CameraDeviceBase> &device) { 169418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin ATRACE_CALL(); 170cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei 171418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin camera_metadata_ro_entry_t entry; 172418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 173204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He // Check if this result is partial. 174204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He bool isPartialResult = false; 175204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He if (device->getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) { 176204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He isPartialResult = result.mResultExtras.partialResultCount < mNumPartialResults; 177204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He } else { 178204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He entry = result.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT); 179204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He if (entry.count != 0 && 180204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { 181204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He ALOGV("%s: Camera %d: This is a partial result", 182204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He __FUNCTION__, device->getId()); 183204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He isPartialResult = true; 184204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He } 185fd6ecdd39bd83ea020f78b425e96310380d66c35Eino-Ville Talvala } 186fd6ecdd39bd83ea020f78b425e96310380d66c35Eino-Ville Talvala 187cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei // TODO: instead of getting requestID from CameraMetadata, we should get it 188cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei // from CaptureResultExtras. This will require changing Camera2Device. 189cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei // Currently Camera2Device uses MetadataQueue to store results, which does not 190cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei // include CaptureResultExtras. 191cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei entry = result.mMetadata.find(ANDROID_REQUEST_ID); 192418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin if (entry.count == 0) { 193cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei ALOGE("%s: Camera %d: Error reading frame id", __FUNCTION__, device->getId()); 194418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin return BAD_VALUE; 195418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 19611d0d44d583f679638cc927bfffe920e495e90ccZhijun He int32_t requestId = entry.data.i32[0]; 197418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 198418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin List<sp<FilteredListener> > listeners; 199418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin { 200418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin Mutex::Autolock l(mInputMutex); 201418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 202418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin List<RangeListener>::iterator item = mRangeListeners.begin(); 203204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He // Don't deliver partial results to listeners that don't want them 204418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin while (item != mRangeListeners.end()) { 205cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei if (requestId >= item->minId && requestId < item->maxId && 206204e3295e2814052aef7e45ee9edd60128efbbd0Zhijun He (!isPartialResult || item->sendPartials)) { 207418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin sp<FilteredListener> listener = item->listener.promote(); 208418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin if (listener == 0) { 209418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin item = mRangeListeners.erase(item); 210418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin continue; 211418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } else { 212418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin listeners.push_back(listener); 213418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 214418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 215418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin item++; 216418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 217418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 218cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei ALOGV("%s: Camera %d: Got %zu range listeners out of %zu", __FUNCTION__, 219cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei device->getId(), listeners.size(), mRangeListeners.size()); 220cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei 221418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin List<sp<FilteredListener> >::iterator item = listeners.begin(); 222418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin for (; item != listeners.end(); item++) { 223cb0652e5a850b2fcd919e977247e87239efaf70eJianing Wei (*item)->onResultAvailable(result); 224418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin } 225418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin return OK; 226418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin} 227418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin 228418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin}; // namespace camera2 229418e493e8d67924cfda652cb64965647ce6381cbIgor Murashkin}; // namespace android 230