1 /*
2  * Copyright (C) 2014 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.one.v2;
18 
19 import android.annotation.TargetApi;
20 import android.graphics.ImageFormat;
21 import android.hardware.camera2.CameraDevice;
22 import android.hardware.camera2.CaptureRequest;
23 import android.os.Build;
24 import android.view.Surface;
25 
26 import com.android.camera.FatalErrorHandler;
27 import com.android.camera.async.HandlerFactory;
28 import com.android.camera.async.Lifetime;
29 import com.android.camera.async.MainThread;
30 import com.android.camera.async.Observable;
31 import com.android.camera.async.Observables;
32 import com.android.camera.async.Updatable;
33 import com.android.camera.burst.BurstFacade;
34 import com.android.camera.debug.Loggers;
35 import com.android.camera.one.OneCamera;
36 import com.android.camera.one.OneCameraCharacteristics;
37 import com.android.camera.one.config.OneCameraFeatureConfig;
38 import com.android.camera.one.v2.camera2proxy.AndroidImageReaderProxy;
39 import com.android.camera.one.v2.camera2proxy.CameraCaptureSessionProxy;
40 import com.android.camera.one.v2.camera2proxy.CameraDeviceProxy;
41 import com.android.camera.one.v2.camera2proxy.CameraDeviceRequestBuilderFactory;
42 import com.android.camera.one.v2.camera2proxy.ImageReaderProxy;
43 import com.android.camera.one.v2.camera2proxy.TotalCaptureResultProxy;
44 import com.android.camera.one.v2.commands.CameraCommandExecutor;
45 import com.android.camera.one.v2.commands.BasicPreviewCommandFactory;
46 import com.android.camera.one.v2.common.BasicCameraFactory;
47 import com.android.camera.one.v2.common.SimpleCaptureStream;
48 import com.android.camera.one.v2.core.FrameServer;
49 import com.android.camera.one.v2.core.FrameServerFactory;
50 import com.android.camera.one.v2.core.RequestBuilder;
51 import com.android.camera.one.v2.core.RequestTemplate;
52 import com.android.camera.one.v2.core.ResponseListeners;
53 import com.android.camera.one.v2.errorhandling.FramerateJankDetector;
54 import com.android.camera.one.v2.imagesaver.ImageSaver;
55 import com.android.camera.one.v2.initialization.CameraStarter;
56 import com.android.camera.one.v2.initialization.InitializedOneCameraFactory;
57 import com.android.camera.one.v2.photo.ImageRotationCalculator;
58 import com.android.camera.one.v2.photo.LegacyPictureTakerFactory;
59 import com.android.camera.one.v2.photo.PictureTaker;
60 import com.android.camera.one.v2.photo.PictureTakerFactory;
61 import com.android.camera.one.v2.sharedimagereader.ManagedImageReader;
62 import com.android.camera.one.v2.sharedimagereader.SharedImageReaderFactory;
63 import com.android.camera.stats.UsageStatistics;
64 import com.android.camera.util.AndroidContext;
65 import com.android.camera.util.GservicesHelper;
66 import com.android.camera.util.Provider;
67 import com.android.camera.util.Size;
68 import com.google.common.base.Supplier;
69 
70 import java.util.ArrayList;
71 import java.util.Arrays;
72 import java.util.List;
73 import java.util.concurrent.ExecutorService;
74 import java.util.concurrent.Executors;
75 
76 /**
77  * Creates a camera which takes jpeg images using the hardware encoder with
78  * baseline functionality.
79  */
80 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
81 public class SimpleOneCameraFactory implements OneCameraFactory {
82     private final int mImageFormat;
83     private final int mMaxImageCount;
84     private final ImageRotationCalculator mImageRotationCalculator;
85 
86     /**
87      * @param imageFormat The {@link ImageFormat} to use for full-size images to
88      *            be saved.
89      * @param maxImageCount The size of the image reader to use for full-size
90      *            images.
91      */
SimpleOneCameraFactory(int imageFormat, int maxImageCount, ImageRotationCalculator imageRotationCalculator)92     public SimpleOneCameraFactory(int imageFormat, int maxImageCount,
93             ImageRotationCalculator imageRotationCalculator) {
94         mImageFormat = imageFormat;
95         mMaxImageCount = maxImageCount;
96         mImageRotationCalculator = imageRotationCalculator;
97     }
98 
99     @Override
createOneCamera(final CameraDeviceProxy device, final OneCameraCharacteristics characteristics, final OneCameraFeatureConfig.CaptureSupportLevel supportLevel, final MainThread mainExecutor, final Size pictureSize, final ImageSaver.Builder imageSaverBuilder, final Observable<OneCamera.PhotoCaptureParameters.Flash> flashSetting, final Observable<Integer> exposureSetting, final Observable<Boolean> hdrSceneSetting, final BurstFacade burstFacade, final FatalErrorHandler fatalErrorHandler)100     public OneCamera createOneCamera(final CameraDeviceProxy device,
101             final OneCameraCharacteristics characteristics,
102             final OneCameraFeatureConfig.CaptureSupportLevel supportLevel,
103             final MainThread mainExecutor,
104             final Size pictureSize,
105             final ImageSaver.Builder imageSaverBuilder,
106             final Observable<OneCamera.PhotoCaptureParameters.Flash> flashSetting,
107             final Observable<Integer> exposureSetting,
108             final Observable<Boolean> hdrSceneSetting,
109             final BurstFacade burstFacade,
110             final FatalErrorHandler fatalErrorHandler) {
111         final Lifetime lifetime = new Lifetime();
112 
113         final ImageReaderProxy imageReader = new CloseWhenDoneImageReader(new LoggingImageReader(
114                 AndroidImageReaderProxy.newInstance(
115                         pictureSize.getWidth(), pictureSize.getHeight(),
116                         mImageFormat, mMaxImageCount),
117                 Loggers.tagFactory()));
118 
119         lifetime.add(imageReader);
120         lifetime.add(device);
121 
122         List<Surface> outputSurfaces = new ArrayList<>();
123         outputSurfaces.add(imageReader.getSurface());
124 
125         /**
126          * Finishes constructing the camera when prerequisites, e.g. the preview
127          * stream and capture session, are ready.
128          */
129         CameraStarter cameraStarter = new CameraStarter() {
130             @Override
131             public CameraStarter.CameraControls startCamera(Lifetime cameraLifetime,
132                     CameraCaptureSessionProxy cameraCaptureSession,
133                     Surface previewSurface,
134                     Observable<Float> zoomState,
135                     Updatable<TotalCaptureResultProxy> metadataCallback,
136                     Updatable<Boolean> readyState) {
137                 // Create the FrameServer from the CaptureSession.
138                 FrameServerFactory frameServerComponent = new FrameServerFactory(
139                         new Lifetime(cameraLifetime), cameraCaptureSession, new HandlerFactory());
140 
141                 CameraCommandExecutor cameraCommandExecutor = new CameraCommandExecutor(
142                         Loggers.tagFactory(),
143                         new Provider<ExecutorService>() {
144                             @Override
145                             public ExecutorService get() {
146                                 // Use a dynamically-expanding thread pool to
147                                 // allow any number of commands to execute
148                                 // simultaneously.
149                                 return Executors.newCachedThreadPool();
150                             }
151                         });
152 
153                 // Create the shared image reader.
154                 SharedImageReaderFactory sharedImageReaderFactory =
155                         new SharedImageReaderFactory(new Lifetime(cameraLifetime), imageReader,
156                                 new HandlerFactory());
157                 Updatable<Long> globalTimestampCallback =
158                         sharedImageReaderFactory.provideGlobalTimestampQueue();
159                 ManagedImageReader managedImageReader =
160                         sharedImageReaderFactory.provideSharedImageReader();
161 
162                 // Create the request builder used by all camera operations.
163                 // Streams, ResponseListeners, and Parameters added to
164                 // this will be applied to *all* requests sent to the camera.
165                 RequestTemplate rootBuilder = new RequestTemplate
166                         (new CameraDeviceRequestBuilderFactory(device));
167                 // The shared image reader must be wired to receive every
168                 // timestamp for every image (including the preview).
169                 rootBuilder.addResponseListener(
170                         ResponseListeners.forTimestamps(globalTimestampCallback));
171                 rootBuilder.addStream(new SimpleCaptureStream(previewSurface));
172                 rootBuilder.addResponseListener(ResponseListeners.forFinalMetadata(
173                         metadataCallback));
174 
175                 FrameServer ephemeralFrameServer =
176                       frameServerComponent.provideEphemeralFrameServer();
177 
178                 // Create basic functionality (zoom, AE, AF).
179                 BasicCameraFactory basicCameraFactory = new BasicCameraFactory(new Lifetime
180                         (cameraLifetime),
181                         characteristics,
182                         ephemeralFrameServer,
183                         rootBuilder,
184                         cameraCommandExecutor,
185                         new BasicPreviewCommandFactory(ephemeralFrameServer),
186                         flashSetting,
187                         exposureSetting,
188                         zoomState,
189                         hdrSceneSetting,
190                         CameraDevice.TEMPLATE_PREVIEW);
191 
192                 // Register the dynamic updater via orientation supplier
193                 rootBuilder.setParam(CaptureRequest.JPEG_ORIENTATION,
194                         mImageRotationCalculator.getSupplier());
195 
196                 if (GservicesHelper.isJankStatisticsEnabled(AndroidContext.instance().get()
197                       .getContentResolver())) {
198                     rootBuilder.addResponseListener(
199                           new FramerateJankDetector(Loggers.tagFactory(),
200                                 UsageStatistics.instance()));
201                 }
202 
203                 RequestBuilder.Factory meteredZoomedRequestBuilder =
204                         basicCameraFactory.provideMeteredZoomedRequestBuilder();
205 
206                 // Create the picture-taker.
207                 PictureTaker pictureTaker;
208                 if (supportLevel == OneCameraFeatureConfig.CaptureSupportLevel.LEGACY_JPEG) {
209                     pictureTaker = new LegacyPictureTakerFactory(imageSaverBuilder,
210                             cameraCommandExecutor, mainExecutor,
211                             frameServerComponent.provideFrameServer(),
212                             meteredZoomedRequestBuilder, managedImageReader).providePictureTaker();
213                 } else {
214                     pictureTaker = PictureTakerFactory.create(Loggers.tagFactory(), mainExecutor,
215                             cameraCommandExecutor, imageSaverBuilder,
216                             frameServerComponent.provideFrameServer(),
217                             meteredZoomedRequestBuilder, managedImageReader, flashSetting,
218                             characteristics.isContinuousPictureAutoFocusSupported())
219                             .providePictureTaker();
220                 }
221 
222                 // Wire-together ready-state.
223                 final Observable<Integer> availableImageCount = sharedImageReaderFactory
224                         .provideAvailableImageCount();
225                 final Observable<Boolean> frameServerAvailability = frameServerComponent
226                         .provideReadyState();
227                 Observable<Boolean> ready = Observables.transform(
228                         Arrays.asList(availableImageCount, frameServerAvailability),
229                         new Supplier<Boolean>() {
230                             @Override
231                             public Boolean get() {
232                                 boolean atLeastOneImageAvailable = availableImageCount.get() >= 1;
233                                 boolean frameServerAvailable = frameServerAvailability.get();
234                                 return atLeastOneImageAvailable && frameServerAvailable;
235                             }
236                         });
237 
238                 lifetime.add(Observables.addThreadSafeCallback(ready, readyState));
239 
240                 basicCameraFactory.providePreviewUpdater().run();
241 
242                 return new CameraStarter.CameraControls(
243                         pictureTaker,
244                         basicCameraFactory.provideManualAutoFocus());
245             }
246         };
247 
248         float maxZoom = characteristics.getAvailableMaxDigitalZoom();
249         List<Size> supportedPreviewSizes = characteristics.getSupportedPreviewSizes();
250         OneCamera.Facing direction = characteristics.getCameraDirection();
251 
252         return new InitializedOneCameraFactory(lifetime, cameraStarter, device, outputSurfaces,
253                 mainExecutor, new HandlerFactory(), maxZoom, supportedPreviewSizes,
254                 characteristics.getLensFocusRange(), direction)
255                 .provideOneCamera();
256     }
257 }
258