1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera.device;
18
19import android.hardware.Camera;
20import android.os.Handler;
21
22import com.android.camera.async.HandlerFactory;
23import com.android.camera.async.Lifetime;
24import com.android.camera.debug.Log.Tag;
25import com.android.camera.debug.Logger;
26
27import javax.annotation.Nullable;
28import javax.annotation.ParametersAreNonnullByDefault;
29
30/**
31 * Set of device actions for opening and closing a single Legacy camera
32 * device.
33 */
34@ParametersAreNonnullByDefault
35public class LegacyCameraActions implements SingleDeviceActions<Camera> {
36    private static final Tag TAG = new Tag("Camera1Act");
37
38    private final CameraDeviceKey mId;
39    private final HandlerFactory mHandlerFactory;
40    private final Logger mLogger;
41
42    @Nullable
43    private Handler mCameraHandler;
44
45    public LegacyCameraActions(CameraDeviceKey id, HandlerFactory handlerFactory,
46          Logger.Factory logFactory) {
47        mId = id;
48        mHandlerFactory = handlerFactory;
49        mLogger = logFactory.create(TAG);
50    }
51
52    @Override
53    public void executeOpen(SingleDeviceOpenListener<Camera> openListener,
54          Lifetime deviceLifetime) throws UnsupportedOperationException {
55        mLogger.i("executeOpen(id: " + mId.getCameraId() + ")");
56
57        mCameraHandler = mHandlerFactory.create(deviceLifetime, "LegacyCamera Handler");
58        mCameraHandler.post(new OpenCameraRunnable(openListener,
59              mId.getCameraId().getLegacyValue(), mLogger));
60    }
61
62    @Override
63    public void executeClose(SingleDeviceCloseListener closeListener, Camera device)
64          throws UnsupportedOperationException {
65        mLogger.i("executeClose(" + mId.getCameraId() + ")");
66
67        Runnable closeCamera = new CloseCameraRunnable(closeListener,
68              device,
69              mId.getCameraId().getLegacyValue(),
70              mLogger);
71
72        if (mCameraHandler != null) {
73            mCameraHandler.post(closeCamera);
74        } else {
75            mLogger.e("executeClose() was executed before the handler was created!");
76            closeCamera.run();
77        }
78    }
79
80    /**
81     * Internal runnable that calls Camera.open and creates a new
82     * camera device.
83     */
84    private static class OpenCameraRunnable implements Runnable {
85        private final SingleDeviceOpenListener<Camera> mResults;
86        private final int mCameraId;
87        private final Logger mLogger;
88
89        public OpenCameraRunnable(SingleDeviceOpenListener<Camera> results,
90              int cameraId,
91              Logger logger) {
92            mCameraId = cameraId;
93            mResults = results;
94            mLogger = logger;
95        }
96
97        @Override
98        public void run() {
99            try {
100                mLogger.i("Camera.open(id: " + mCameraId + ")");
101                Camera device = Camera.open(mCameraId);
102                mResults.onDeviceOpened(device);
103            } catch (RuntimeException e) {
104                mLogger.e("Opening the camera produced an exception!", e);
105                mResults.onDeviceOpenException(e);
106            }
107        }
108    }
109
110    /**
111     * Internal runnable that releases the Camera device.
112     */
113    private static class CloseCameraRunnable implements Runnable {
114        private final SingleDeviceCloseListener mCloseListener;
115        private final int mCameraId;
116        private final Camera mCameraDevice;
117        private final Logger mLogger;
118
119        public CloseCameraRunnable(SingleDeviceCloseListener closeListener,
120              Camera cameraDevice,
121              int cameraId,
122              Logger logger) {
123            mCameraDevice = cameraDevice;
124            mCloseListener = closeListener;
125            mCameraId = cameraId;
126            mLogger = logger;
127        }
128
129        @Override
130        public void run() {
131            try {
132                mLogger.i("Camera.release(id: " + mCameraId + ")");
133                mCameraDevice.release();
134                mCloseListener.onDeviceClosed();
135            } catch (Exception e) {
136                mLogger.e("Closing the camera produced an exception!", e);
137                mCloseListener.onDeviceClosingException(e);
138            }
139        }
140    }
141}
142