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