170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin/*
270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * Copyright (C) 2013 The Android Open Source Project
370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *
470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * you may not use this file except in compliance with the License.
670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * You may obtain a copy of the License at
770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *
870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *
1070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * Unless required by applicable law or agreed to in writing, software
1170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
1270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * See the License for the specific language governing permissions and
1470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * limitations under the License.
1570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin */
1670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
172f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalapackage android.hardware.camera2.impl;
1870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
1957ea59b376c6b72206b5b339733ee5874b181762Igor Murashkinimport static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
2057ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin
212f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaimport android.hardware.camera2.CameraAccessException;
222f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaimport android.hardware.camera2.CaptureRequest;
2357ea59b376c6b72206b5b339733ee5874b181762Igor Murashkinimport android.hardware.camera2.CaptureResult;
2457ea59b376c6b72206b5b339733ee5874b181762Igor Murashkinimport android.hardware.camera2.ICameraDeviceCallbacks;
2557ea59b376c6b72206b5b339733ee5874b181762Igor Murashkinimport android.hardware.camera2.ICameraDeviceUser;
265afd3e91b8e785b1b3a42e40b0a3ca11eba2d7ccEino-Ville Talvalaimport android.hardware.camera2.utils.CameraBinderDecorator;
2757ea59b376c6b72206b5b339733ee5874b181762Igor Murashkinimport android.hardware.camera2.utils.CameraRuntimeException;
284af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvalaimport android.os.Handler;
29decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunkimport android.os.IBinder;
304af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvalaimport android.os.Looper;
31decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunkimport android.os.RemoteException;
3270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinimport android.util.Log;
3357ea59b376c6b72206b5b339733ee5874b181762Igor Murashkinimport android.util.SparseArray;
3470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinimport android.view.Surface;
3570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
3657ea59b376c6b72206b5b339733ee5874b181762Igor Murashkinimport java.util.ArrayList;
3757ea59b376c6b72206b5b339733ee5874b181762Igor Murashkinimport java.util.HashSet;
38decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunkimport java.util.Iterator;
3970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinimport java.util.List;
4070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
4170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin/**
4270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate
4370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin */
442f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalapublic class CameraDevice implements android.hardware.camera2.CameraDevice {
4570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
4670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    private final String TAG;
47ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He    private final boolean DEBUG;
4870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
49decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk    private static final int REQUEST_ID_NONE = -1;
50decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk
5170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // TODO: guard every function with if (!mRemoteDevice) check (if it was closed)
5270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    private ICameraDeviceUser mRemoteDevice;
5370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
5470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    private final Object mLock = new Object();
5570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
5670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
57868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final StateListener mDeviceListener;
58868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final Handler mDeviceHandler;
59868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
60868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private boolean mIdle = true;
614af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala
624af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala    private final SparseArray<CaptureListenerHolder> mCaptureListenerMap =
634af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            new SparseArray<CaptureListenerHolder>();
6470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
65decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk    private int mRepeatingRequestId = REQUEST_ID_NONE;
66decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk    private final ArrayList<Integer> mRepeatingRequestIdDeletedList = new ArrayList<Integer>();
6757ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin    // Map stream IDs to Surfaces
6857ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin    private final SparseArray<Surface> mConfiguredOutputs = new SparseArray<Surface>();
6970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
7070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    private final String mCameraId;
7170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
72868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    // Runnables for all state transitions, except error, which needs the
73868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    // error code argument
74868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
75868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final Runnable mCallOnOpened = new Runnable() {
76868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        public void run() {
77868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (!CameraDevice.this.isClosed()) {
78868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceListener.onOpened(CameraDevice.this);
79868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
80868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
81868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    };
82868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
83868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final Runnable mCallOnUnconfigured = new Runnable() {
84868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        public void run() {
85868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (!CameraDevice.this.isClosed()) {
86868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceListener.onUnconfigured(CameraDevice.this);
87868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
88868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
89868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    };
90868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
91868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final Runnable mCallOnActive = new Runnable() {
92868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        public void run() {
93868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (!CameraDevice.this.isClosed()) {
94868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceListener.onActive(CameraDevice.this);
95868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
96868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
97868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    };
98868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
99868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final Runnable mCallOnBusy = new Runnable() {
100868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        public void run() {
101868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (!CameraDevice.this.isClosed()) {
102868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceListener.onBusy(CameraDevice.this);
103868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
104868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
105868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    };
106868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
107868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final Runnable mCallOnClosed = new Runnable() {
108868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        public void run() {
109868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (!CameraDevice.this.isClosed()) {
110868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceListener.onClosed(CameraDevice.this);
111868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
112868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
113868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    };
114868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
115868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final Runnable mCallOnIdle = new Runnable() {
116868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        public void run() {
117868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (!CameraDevice.this.isClosed()) {
118868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceListener.onIdle(CameraDevice.this);
119868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
120868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
121868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    };
122868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
123868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private final Runnable mCallOnDisconnected = new Runnable() {
124868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        public void run() {
125868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (!CameraDevice.this.isClosed()) {
126868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceListener.onDisconnected(CameraDevice.this);
127868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
128868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
129868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    };
130868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
131868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    public CameraDevice(String cameraId, StateListener listener, Handler handler) {
132868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        if (cameraId == null || listener == null || handler == null) {
133868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            throw new IllegalArgumentException("Null argument given");
134868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
13570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        mCameraId = cameraId;
136868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        mDeviceListener = listener;
137868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        mDeviceHandler = handler;
13870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        TAG = String.format("CameraDevice-%s-JV", mCameraId);
139ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He        DEBUG = Log.isLoggable(TAG, Log.DEBUG);
14070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
14170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
14270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    public CameraDeviceCallbacks getCallbacks() {
14370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return mCallbacks;
14470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
14570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
14670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    public void setRemoteDevice(ICameraDeviceUser remoteDevice) {
1475afd3e91b8e785b1b3a42e40b0a3ca11eba2d7ccEino-Ville Talvala        // TODO: Move from decorator to direct binder-mediated exceptions
148868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        synchronized(mLock) {
149868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice);
150868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
151868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            mDeviceHandler.post(mCallOnOpened);
152868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            mDeviceHandler.post(mCallOnUnconfigured);
153868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
15470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
15570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
15670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
1574af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala    public String getId() {
1584af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala        return mCameraId;
1594af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala    }
1604af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala
1614af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala    @Override
16270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    public void configureOutputs(List<Surface> outputs) throws CameraAccessException {
163868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        // Treat a null input the same an empty list
164868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        if (outputs == null) {
165868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            outputs = new ArrayList<Surface>();
166868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
16770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        synchronized (mLock) {
168868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            checkIfCameraClosed();
169868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
17057ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin            HashSet<Surface> addSet = new HashSet<Surface>(outputs);    // Streams to create
17157ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin            List<Integer> deleteList = new ArrayList<Integer>();        // Streams to delete
17257ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin
17357ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin            // Determine which streams need to be created, which to be deleted
17457ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin            for (int i = 0; i < mConfiguredOutputs.size(); ++i) {
17557ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                int streamId = mConfiguredOutputs.keyAt(i);
17657ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                Surface s = mConfiguredOutputs.valueAt(i);
17757ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin
17857ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                if (!outputs.contains(s)) {
17957ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                    deleteList.add(streamId);
18057ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                } else {
18157ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                    addSet.remove(s);  // Don't create a stream previously created
18257ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                }
18357ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin            }
18457ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin
185868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            mDeviceHandler.post(mCallOnBusy);
186868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            stopRepeating();
187868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
18857ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin            try {
189decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                waitUntilIdle();
19057ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin
191868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                // TODO: mRemoteDevice.beginConfigure
19257ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                // Delete all streams first (to free up HW resources)
19357ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                for (Integer streamId : deleteList) {
19457ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                    mRemoteDevice.deleteStream(streamId);
19557ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                    mConfiguredOutputs.delete(streamId);
19657ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                }
19757ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin
19857ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                // Add all new streams
19957ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                for (Surface s : addSet) {
20070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                    // TODO: remove width,height,format since we are ignoring
20170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                    // it.
20257ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                    int streamId = mRemoteDevice.createStream(0, 0, 0, s);
20357ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                    mConfiguredOutputs.put(streamId, s);
20470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                }
20557ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin
20657ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                // TODO: mRemoteDevice.endConfigure
20757ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin            } catch (CameraRuntimeException e) {
20857ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                if (e.getReason() == CAMERA_IN_USE) {
20957ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                    throw new IllegalStateException("The camera is currently busy." +
210868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                            " You must wait until the previous operation completes.");
21157ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                }
21257ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin
21357ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                throw e.asChecked();
21457ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin            } catch (RemoteException e) {
21557ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                // impossible
21657ea59b376c6b72206b5b339733ee5874b181762Igor Murashkin                return;
21770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            }
218868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
219868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (outputs.size() > 0) {
220868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceHandler.post(mCallOnIdle);
221868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            } else {
222868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceHandler.post(mCallOnUnconfigured);
223868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
22470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
22570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
22670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
22870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public CaptureRequest.Builder createCaptureRequest(int templateType)
22970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            throws CameraAccessException {
23070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        synchronized (mLock) {
231868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            checkIfCameraClosed();
23270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadataNative templatedRequest = new CameraMetadataNative();
23470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            try {
23670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                mRemoteDevice.createDefaultRequest(templateType, /* out */templatedRequest);
23770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            } catch (CameraRuntimeException e) {
23870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                throw e.asChecked();
23970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            } catch (RemoteException e) {
24070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                // impossible
24170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                return null;
24270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            }
24370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
24470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CaptureRequest.Builder builder =
24570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala                    new CaptureRequest.Builder(templatedRequest);
24670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
24770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            return builder;
24870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
24970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
25070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
2526bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin    public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
25370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            throws CameraAccessException {
2546bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin        return submitCaptureRequest(request, listener, handler, /*streaming*/false);
25570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
25670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
2586bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin    public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
2594af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            Handler handler) throws CameraAccessException {
260fc19e2cfe5bd0bc5f5be8a216ef5ee398a86b048Zhijun He        if (requests.isEmpty()) {
261fc19e2cfe5bd0bc5f5be8a216ef5ee398a86b048Zhijun He            Log.w(TAG, "Capture burst request list is empty, do nothing!");
2626bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin            return -1;
263fc19e2cfe5bd0bc5f5be8a216ef5ee398a86b048Zhijun He        }
26470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        // TODO
26570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        throw new UnsupportedOperationException("Burst capture implemented yet");
26670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
26770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
26870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
2696bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin    private int submitCaptureRequest(CaptureRequest request, CaptureListener listener,
2704af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            Handler handler, boolean repeating) throws CameraAccessException {
2714af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala
2724af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala        // Need a valid handler, or current thread needs to have a looper, if
2734af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala        // listener is valid
274e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        if (listener != null) {
275e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            handler = checkHandler(handler);
2764af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala        }
27770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
27870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        synchronized (mLock) {
279868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            checkIfCameraClosed();
28070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            int requestId;
28170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
282e73b41b27f16b160cfe49bdcac3091dce94229aeRuben Brunk            if (repeating) {
283e73b41b27f16b160cfe49bdcac3091dce94229aeRuben Brunk                stopRepeating();
284e73b41b27f16b160cfe49bdcac3091dce94229aeRuben Brunk            }
285e73b41b27f16b160cfe49bdcac3091dce94229aeRuben Brunk
28670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            try {
28770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                requestId = mRemoteDevice.submitRequest(request, repeating);
28870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            } catch (CameraRuntimeException e) {
28970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                throw e.asChecked();
29070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            } catch (RemoteException e) {
29170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                // impossible
2926bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin                return -1;
29370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            }
2944af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            if (listener != null) {
2954af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala                mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, request,
2964af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala                        handler, repeating));
2974af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            }
29870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
29970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            if (repeating) {
300decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                mRepeatingRequestId = requestId;
30170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            }
30270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
303868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (mIdle) {
304868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceHandler.post(mCallOnActive);
305868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
306868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            mIdle = false;
307868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
3086bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin            return requestId;
30970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
31070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
31170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
31270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
3136bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin    public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
3144af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            Handler handler) throws CameraAccessException {
3156bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin        return submitCaptureRequest(request, listener, handler, /*streaming*/true);
31670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
31770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
31870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
3196bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin    public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
3204af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            Handler handler) throws CameraAccessException {
321fc19e2cfe5bd0bc5f5be8a216ef5ee398a86b048Zhijun He        if (requests.isEmpty()) {
322fc19e2cfe5bd0bc5f5be8a216ef5ee398a86b048Zhijun He            Log.w(TAG, "Set Repeating burst request list is empty, do nothing!");
3236bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin            return -1;
324fc19e2cfe5bd0bc5f5be8a216ef5ee398a86b048Zhijun He        }
32570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        // TODO
32670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        throw new UnsupportedOperationException("Burst capture implemented yet");
32770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
32870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
32970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
33070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    public void stopRepeating() throws CameraAccessException {
33170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
33270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        synchronized (mLock) {
333868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            checkIfCameraClosed();
334decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk            if (mRepeatingRequestId != REQUEST_ID_NONE) {
335decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk
336decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                int requestId = mRepeatingRequestId;
337decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                mRepeatingRequestId = REQUEST_ID_NONE;
338decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk
339decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                // Queue for deletion after in-flight requests finish
340decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                mRepeatingRequestIdDeletedList.add(requestId);
34170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
34270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                try {
34370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                    mRemoteDevice.cancelRequest(requestId);
34470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                } catch (CameraRuntimeException e) {
34570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                    throw e.asChecked();
34670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                } catch (RemoteException e) {
34770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                    // impossible
34870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                    return;
34970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                }
35070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            }
35170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
35270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
35370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
35470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
35570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    public void waitUntilIdle() throws CameraAccessException {
3567f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He
3577f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He        synchronized (mLock) {
3587f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He            checkIfCameraClosed();
359decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk            if (mRepeatingRequestId != REQUEST_ID_NONE) {
3607f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He                throw new IllegalStateException("Active repeating request ongoing");
3617f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He            }
3627f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He
3637f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He            try {
3647f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He                mRemoteDevice.waitUntilIdle();
3657f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He            } catch (CameraRuntimeException e) {
3667f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He                throw e.asChecked();
3677f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He            } catch (RemoteException e) {
3687f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He                // impossible
3697f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He                return;
3707f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He            }
371decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk
372decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk            mRepeatingRequestId = REQUEST_ID_NONE;
373decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk            mRepeatingRequestIdDeletedList.clear();
374decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk            mCaptureListenerMap.clear();
375e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        }
37670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
37770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
37870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
3798ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala    public void flush() throws CameraAccessException {
3808ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala        synchronized (mLock) {
381868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            checkIfCameraClosed();
382868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
383868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            mDeviceHandler.post(mCallOnBusy);
3848ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala            try {
3858ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala                mRemoteDevice.flush();
3868ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala            } catch (CameraRuntimeException e) {
3878ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala                throw e.asChecked();
3888ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala            } catch (RemoteException e) {
3898ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala                // impossible
3908ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala                return;
3918ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala            }
3928ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala        }
3938ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala    }
3948ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala
3958ebd52bf4166a5ef8b7e91c9e3ecce2ce27cff12Eino-Ville Talvala    @Override
3965c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin    public void close() {
39770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        synchronized (mLock) {
39870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
39970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            try {
4002a3eced15eddc322b946462b9018285997396a99Igor Murashkin                if (mRemoteDevice != null) {
4012a3eced15eddc322b946462b9018285997396a99Igor Murashkin                    mRemoteDevice.disconnect();
4022a3eced15eddc322b946462b9018285997396a99Igor Murashkin                }
40370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            } catch (CameraRuntimeException e) {
4045c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin                Log.e(TAG, "Exception while closing: ", e.asChecked());
40570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            } catch (RemoteException e) {
40670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                // impossible
40770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            }
40870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
409868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (mRemoteDevice != null) {
410868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                mDeviceHandler.post(mCallOnClosed);
411868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            }
41270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
413868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            mRemoteDevice = null;
41470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
41570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
41670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
41770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
41870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    protected void finalize() throws Throwable {
41970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        try {
42070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            close();
42170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
42270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        finally {
42370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            super.finalize();
42470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
42570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
42670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
42770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    static class CaptureListenerHolder {
42870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
42970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        private final boolean mRepeating;
43070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        private final CaptureListener mListener;
43170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        private final CaptureRequest mRequest;
4324af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala        private final Handler mHandler;
43370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
4344af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala        CaptureListenerHolder(CaptureListener listener, CaptureRequest request, Handler handler,
4354af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala                boolean repeating) {
4364af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            if (listener == null || handler == null) {
4374af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala                throw new UnsupportedOperationException(
4384af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala                    "Must have a valid handler and a valid listener");
4394af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            }
44070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            mRepeating = repeating;
4414af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            mHandler = handler;
44270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            mRequest = request;
44370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            mListener = listener;
44470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
44570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
44670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        public boolean isRepeating() {
44770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return mRepeating;
44870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
44970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
45070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        public CaptureListener getListener() {
45170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return mListener;
45270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
45370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
45470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        public CaptureRequest getRequest() {
45570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return mRequest;
45670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
4574af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala
4584af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala        public Handler getHandler() {
4594af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            return mHandler;
4604af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala        }
4614af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala
46270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
46370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
464ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He    public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
46570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
466e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        //
467e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        // Constants below need to be kept up-to-date with
468e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        // frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
469e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        //
470e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
471e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        //
472e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        // Error codes for onCameraError
473e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        //
474e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
475e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        /**
476e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala         * Camera has been disconnected
477e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala         */
478e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        static final int ERROR_CAMERA_DISCONNECTED = 0;
479e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
480e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        /**
481e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala         * Camera has encountered a device-level error
482e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala         * Matches CameraDevice.StateListener#ERROR_CAMERA_DEVICE
483e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala         */
484e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        static final int ERROR_CAMERA_DEVICE = 1;
485e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
486e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        /**
487e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala         * Camera has encountered a service-level error
488e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala         * Matches CameraDevice.StateListener#ERROR_CAMERA_SERVICE
489e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala         */
490e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        static final int ERROR_CAMERA_SERVICE = 2;
491e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
49270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        @Override
49370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        public IBinder asBinder() {
49470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return this;
49570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
49670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
49770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        @Override
498e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        public void onCameraError(final int errorCode) {
499868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            Runnable r = null;
500868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (isClosed()) return;
501868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
502868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            synchronized(mLock) {
503e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                switch (errorCode) {
504e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                    case ERROR_CAMERA_DISCONNECTED:
505868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                        r = mCallOnDisconnected;
506e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                        break;
507868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                    default:
508868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                        Log.e(TAG, "Unknown error from camera device: " + errorCode);
509868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                        // no break
510e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                    case ERROR_CAMERA_DEVICE:
511e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                    case ERROR_CAMERA_SERVICE:
512e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                        r = new Runnable() {
513e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                            public void run() {
514868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                if (!CameraDevice.this.isClosed()) {
515868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                    mDeviceListener.onError(CameraDevice.this, errorCode);
516868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                }
517e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                            }
518e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                        };
519e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                        break;
520e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                }
521868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                CameraDevice.this.mDeviceHandler.post(r);
522e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            }
523e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        }
524e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
525e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        @Override
526e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        public void onCameraIdle() {
527868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (isClosed()) return;
528868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
529e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            if (DEBUG) {
530e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                Log.d(TAG, "Camera now idle");
531e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            }
532e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            synchronized (mLock) {
533868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                if (!CameraDevice.this.mIdle) {
534868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                    CameraDevice.this.mDeviceHandler.post(mCallOnIdle);
535868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                }
536868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                CameraDevice.this.mIdle = true;
537e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            }
538e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        }
539e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
540e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        @Override
541e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        public void onCaptureStarted(int requestId, final long timestamp) {
542ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He            if (DEBUG) {
543e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                Log.d(TAG, "Capture started for id " + requestId);
544e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            }
545e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            final CaptureListenerHolder holder;
546e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
547e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            // Get the listener for this frame ID, if there is one
548e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            synchronized (mLock) {
549e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
550ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He            }
551e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
552e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            if (holder == null) {
553e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                return;
554e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            }
555e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
556868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (isClosed()) return;
557868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
558e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            // Dispatch capture start notice
559e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            holder.getHandler().post(
560e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                new Runnable() {
561e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                    public void run() {
562868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                        if (!CameraDevice.this.isClosed()) {
563868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                            holder.getListener().onCaptureStarted(
564868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                CameraDevice.this,
565868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                holder.getRequest(),
566868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                timestamp);
567868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                        }
568e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                    }
569e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                });
57070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
57170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
57270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        @Override
57370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        public void onResultReceived(int requestId, CameraMetadataNative result)
57470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala                throws RemoteException {
575ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He            if (DEBUG) {
576ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He                Log.d(TAG, "Received result for id " + requestId);
577ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He            }
5784af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            final CaptureListenerHolder holder;
57970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
5807a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala            Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT);
5817a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala            boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial);
5827a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala
58370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            synchronized (mLock) {
58470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                // TODO: move this whole map into this class to make it more testable,
58570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                //        exposing the methods necessary like subscribeToRequest, unsubscribe..
58670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                // TODO: make class static class
58770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
588ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He                holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
58970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
59070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                // Clean up listener once we no longer expect to see it.
5917a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                if (holder != null && !holder.isRepeating() && !quirkIsPartialResult) {
592ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He                    CameraDevice.this.mCaptureListenerMap.remove(requestId);
59370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                }
594decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk
595decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                // TODO: add 'capture sequence completed' callback to the
596decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                // service, and clean up repeating requests there instead.
597decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk
598decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                // If we received a result for a repeating request and have
599decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                // prior repeating requests queued for deletion, remove those
600decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                // requests from mCaptureListenerMap.
6017a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                if (holder != null && holder.isRepeating() && !quirkIsPartialResult
602decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                        && mRepeatingRequestIdDeletedList.size() > 0) {
603decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                    Iterator<Integer> iter = mRepeatingRequestIdDeletedList.iterator();
604decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                    while (iter.hasNext()) {
605decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                        int deletedRequestId = iter.next();
606decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                        if (deletedRequestId < requestId) {
607decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                            CameraDevice.this.mCaptureListenerMap.remove(deletedRequestId);
608decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                            iter.remove();
609decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                        }
610decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                    }
611decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk                }
612decfe95fce05627fe6ff5d6fa5801864fb30dc6bRuben Brunk
61370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            }
61470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
6154af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala            // Check if we have a listener for this
61670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            if (holder == null) {
61770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                return;
61870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            }
61970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
620868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            if (isClosed()) return;
621868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
6226bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin            final CaptureRequest request = holder.getRequest();
6236bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin            final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId);
62470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
6257a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala            Runnable resultDispatch = null;
6267a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala
6277a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala            // Either send a partial result or the final capture completed result
6287a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala            if (quirkIsPartialResult) {
6297a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                // Partial result
6307a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                resultDispatch = new Runnable() {
6317a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                    @Override
6327a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                    public void run() {
6337a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                        if (!CameraDevice.this.isClosed()){
6347a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                            holder.getListener().onCapturePartial(
6357a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                                CameraDevice.this,
6367a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                                request,
6377a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                                resultAsCapture);
6387a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                        }
6397a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                    }
6407a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                };
6417a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala            } else {
6427a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                // Final capture result
6437a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                resultDispatch = new Runnable() {
6446bbf9dc5ae7ebc85991dcfe3e18e837b12d3f333Igor Murashkin                    @Override
6454af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala                    public void run() {
646868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                        if (!CameraDevice.this.isClosed()){
647868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                            holder.getListener().onCaptureCompleted(
648868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                CameraDevice.this,
649868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                request,
650868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                                resultAsCapture);
651868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala                        }
6524af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala                    }
6537a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala                };
6547a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala            }
6557a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala
6567a31310439b8ac6a9dca9e81dd3366221bbb1057Eino-Ville Talvala            holder.getHandler().post(resultDispatch);
65770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
65870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
65970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
66070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
661e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala    /**
662e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala     * Default handler management. If handler is null, get the current thread's
663e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala     * Looper to create a Handler with. If no looper exists, throw exception.
664e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala     */
665e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala    private Handler checkHandler(Handler handler) {
666e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        if (handler == null) {
667e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            Looper looper = Looper.myLooper();
668e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            if (looper == null) {
669e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                throw new IllegalArgumentException(
670e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala                    "No handler given, and current thread has no looper!");
671e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            }
672e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala            handler = new Handler(looper);
673e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        }
674e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala        return handler;
675e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala    }
676e841d4e16526a2e466f662305682aa3459d07c15Eino-Ville Talvala
6777f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He    private void checkIfCameraClosed() {
6787f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He        if (mRemoteDevice == null) {
6797f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He            throw new IllegalStateException("CameraDevice was already closed");
6807f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He        }
6817f4d3147d1851d2f0c544e45390c139bda9fd9aaZhijun He    }
682868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala
683868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    private boolean isClosed() {
684868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        synchronized(mLock) {
685868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala            return (mRemoteDevice == null);
686868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala        }
687868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala    }
68870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
689