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 
17 package com.android.camera.device;
18 
19 import android.hardware.Camera;
20 import android.os.Handler;
21 
22 import com.android.camera.async.HandlerFactory;
23 import com.android.camera.async.Lifetime;
24 import com.android.camera.debug.Log.Tag;
25 import com.android.camera.debug.Logger;
26 
27 import javax.annotation.Nullable;
28 import javax.annotation.ParametersAreNonnullByDefault;
29 
30 /**
31  * Set of device actions for opening and closing a single Legacy camera
32  * device.
33  */
34 @ParametersAreNonnullByDefault
35 public 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 
LegacyCameraActions(CameraDeviceKey id, HandlerFactory handlerFactory, Logger.Factory logFactory)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
executeOpen(SingleDeviceOpenListener<Camera> openListener, Lifetime deviceLifetime)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
executeClose(SingleDeviceCloseListener closeListener, Camera device)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 
OpenCameraRunnable(SingleDeviceOpenListener<Camera> results, int cameraId, Logger logger)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
run()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 
CloseCameraRunnable(SingleDeviceCloseListener closeListener, Camera cameraDevice, int cameraId, Logger logger)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
run()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