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.captureintent.resource;
18 
19 import com.google.common.logging.eventprotos;
20 
21 import com.android.camera.SoundPlayer;
22 import com.android.camera.async.MainThread;
23 import com.android.camera.async.RefCountBase;
24 import com.android.camera.captureintent.CaptureIntentModuleUI;
25 import com.android.camera.captureintent.CaptureIntentSessionFactory;
26 import com.android.camera.debug.Log;
27 import com.android.camera.hardware.HeadingSensor;
28 import com.android.camera.one.OneCamera;
29 import com.android.camera.session.CaptureSession;
30 import com.android.camera.session.CaptureSessionManager;
31 import com.android.camera.session.CaptureSessionManagerImpl;
32 import com.android.camera.session.SessionStorageManagerImpl;
33 import com.android.camera.settings.Keys;
34 import com.android.camera.settings.SettingsManager;
35 import com.android.camera.ui.focus.FocusController;
36 import com.android.camera.ui.focus.FocusSound;
37 import com.android.camera.util.AndroidServices;
38 import com.android.camera.util.CameraUtil;
39 import com.android.camera2.R;
40 
41 import android.media.MediaActionSound;
42 
43 public final class ResourceCaptureToolsImpl implements ResourceCaptureTools {
44     private static final Log.Tag TAG = new Log.Tag("ResCapTools");
45 
46     private final RefCountBase<ResourceConstructed> mResourceConstructed;
47     private final RefCountBase<ResourceSurfaceTexture> mResourceSurfaceTexture;
48     private final RefCountBase<ResourceOpenedCamera> mResourceOpenedCamera;
49 
50     private final CaptureSessionManager mCaptureSessionManager;
51     private final FocusController mFocusController;
52     private final HeadingSensor mHeadingSensor;
53     private final SoundPlayer mSoundPlayer;
54     private final MediaActionSound mMediaActionSound;
55 
56     /**
57      * Creates a reference counted {@link ResourceCaptureToolsImpl} object.
58      */
create( RefCountBase<ResourceConstructed> resourceConstructed, RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture, RefCountBase<ResourceOpenedCamera> resourceOpenedCamera)59     public static RefCountBase<ResourceCaptureTools> create(
60             RefCountBase<ResourceConstructed> resourceConstructed,
61             RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture,
62             RefCountBase<ResourceOpenedCamera> resourceOpenedCamera) {
63         CaptureSessionManager captureSessionManager = new CaptureSessionManagerImpl(
64                 new CaptureIntentSessionFactory(),
65                 SessionStorageManagerImpl.create(resourceConstructed.get().getContext()),
66                 resourceConstructed.get().getMainThread());
67         HeadingSensor headingSensor =
68                 new HeadingSensor(AndroidServices.instance().provideSensorManager());
69         SoundPlayer soundPlayer = new SoundPlayer(resourceConstructed.get().getContext());
70         FocusSound focusSound = new FocusSound(soundPlayer, R.raw.material_camera_focus);
71         FocusController focusController = new FocusController(
72                 resourceConstructed.get().getModuleUI().getFocusRing(),
73                 focusSound,
74                 resourceConstructed.get().getMainThread());
75         MediaActionSound mediaActionSound = new MediaActionSound();
76         ResourceCaptureTools resourceCaptureTools = new ResourceCaptureToolsImpl(
77                 resourceConstructed, resourceSurfaceTexture, resourceOpenedCamera,
78                 captureSessionManager, focusController, headingSensor, soundPlayer,
79                 mediaActionSound);
80         return new RefCountBase<>(resourceCaptureTools);
81     }
82 
ResourceCaptureToolsImpl( RefCountBase<ResourceConstructed> resourceConstructed, RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture, RefCountBase<ResourceOpenedCamera> resourceOpenedCamera, CaptureSessionManager captureSessionManager, FocusController focusController, HeadingSensor headingSensor, SoundPlayer soundPlayer, MediaActionSound mediaActionSound)83     private ResourceCaptureToolsImpl(
84             RefCountBase<ResourceConstructed> resourceConstructed,
85             RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture,
86             RefCountBase<ResourceOpenedCamera> resourceOpenedCamera,
87             CaptureSessionManager captureSessionManager,
88             FocusController focusController,
89             HeadingSensor headingSensor,
90             SoundPlayer soundPlayer,
91             MediaActionSound mediaActionSound) {
92         mResourceConstructed = resourceConstructed;
93         mResourceConstructed.addRef();     // Will be balanced in close().
94         mResourceSurfaceTexture = resourceSurfaceTexture;
95         mResourceSurfaceTexture.addRef();  // Will be balanced in close().
96         mResourceOpenedCamera = resourceOpenedCamera;
97         mResourceOpenedCamera.addRef();    // Will be balanced in close().
98         mCaptureSessionManager = captureSessionManager;
99         mHeadingSensor = headingSensor;
100         mHeadingSensor.activate();  // Will be balanced in close().
101         mSoundPlayer = soundPlayer;
102         mSoundPlayer.loadSound(R.raw.timer_final_second);  // Will be balanced in close().
103         mSoundPlayer.loadSound(R.raw.timer_increment);     // Will be balanced in close().
104         mMediaActionSound = mediaActionSound;
105         mFocusController = focusController;
106     }
107 
108     @Override
close()109     public void close() {
110         Log.d(TAG, "close");
111         mResourceConstructed.close();
112         mResourceSurfaceTexture.close();
113         mResourceOpenedCamera.close();
114         mHeadingSensor.deactivate();
115         mSoundPlayer.unloadSound(R.raw.timer_increment);
116         mSoundPlayer.unloadSound(R.raw.timer_final_second);
117     }
118 
119     @Override
getResourceConstructed()120     public RefCountBase<ResourceConstructed> getResourceConstructed() {
121         return mResourceConstructed;
122     }
123 
124     @Override
getResourceSurfaceTexture()125     public RefCountBase<ResourceSurfaceTexture> getResourceSurfaceTexture() {
126         return mResourceSurfaceTexture;
127     }
128 
129     @Override
getResourceOpenedCamera()130     public RefCountBase<ResourceOpenedCamera> getResourceOpenedCamera() {
131         return mResourceOpenedCamera;
132     }
133 
134     @Override
getCaptureSessionManager()135     public CaptureSessionManager getCaptureSessionManager() {
136         return mCaptureSessionManager;
137     }
138 
139     @Override
getFocusController()140     public FocusController getFocusController() {
141         return mFocusController;
142     }
143 
144     @Override
getMediaActionSound()145     public MediaActionSound getMediaActionSound() {
146         return mMediaActionSound;
147     }
148 
149     @Override
takePictureNow( OneCamera.PictureCallback pictureCallback, CaptureLoggingInfo captureLoggingInfo)150     public void takePictureNow(
151             OneCamera.PictureCallback pictureCallback,
152             CaptureLoggingInfo captureLoggingInfo) {
153         final ResourceConstructed resource = mResourceConstructed.get();
154         final ResourceOpenedCamera openedCamera = mResourceOpenedCamera.get();
155 
156         /**
157          * Disable the shutter button immediately. The button will be
158          * re-enabled when users press re-take button.
159          */
160         resource.getMainThread().execute(new Runnable() {
161             @Override
162             public void run() {
163                 resource.getModuleUI().setShutterButtonEnabled(false);
164             }
165         });
166 
167         /** Create a new capture session. */
168         final long timestamp = System.currentTimeMillis();
169         final String fileName = CameraUtil.instance().createJpegName(timestamp);
170         final android.location.Location location =
171                 resource.getLocationManager().getCurrentLocation();
172         final CaptureSession session =
173                 mCaptureSessionManager.createNewSession(fileName, timestamp, location);
174         session.startEmpty(null, openedCamera.getPictureSize());
175 
176         /** Logging */
177         final SettingsManager settingsManager = resource.getSettingsManager();
178         boolean isGridLinesOn = Keys.areGridLinesOn(settingsManager);
179         session.getCollector().decorateAtTimeCaptureRequest(
180                 eventprotos.NavigationChange.Mode.PHOTO_CAPTURE,
181                 session.getTitle() + ".jpg",
182                 (openedCamera.getCameraFacing() == OneCamera.Facing.FRONT),
183                 false, /** hdrPlusEnabled */
184                 openedCamera.getZoomRatio(),
185                 openedCamera.getCaptureSetting().getFlashSetting().get().encodeSettingsString(),
186                 isGridLinesOn,
187                 (float) captureLoggingInfo.getCountDownDuration(),
188                 captureLoggingInfo.getTouchPointInsideShutterButton(),
189                 null /* TODO: Implement Volume Button Shutter Click Instrumentation */,
190                 openedCamera.getCameraCharacteristics().getSensorInfoActiveArraySize()
191         );
192 
193         OneCamera.PhotoCaptureParameters params = new OneCamera.PhotoCaptureParameters(
194                 session.getTitle(),
195                 resource.getOrientationManager().getDeviceOrientation().getDegrees(),
196                 session.getLocation(),
197                 resource.getContext().getExternalCacheDir(),
198                 pictureCallback,
199                 mPictureSaverCallback,
200                 mHeadingSensor.getCurrentHeading(),
201                 openedCamera.getZoomRatio(),
202                 0);
203         openedCamera.getCamera().takePicture(params, session);
204     }
205 
206     @Override
playCountDownSound(int remainingSeconds)207     public void playCountDownSound(int remainingSeconds) {
208         if (remainingSeconds == 1) {
209             mSoundPlayer.play(R.raw.timer_final_second, 0.6f);
210         } else if (remainingSeconds == 2 || remainingSeconds == 3) {
211             mSoundPlayer.play(R.raw.timer_increment, 0.6f);
212         }
213     }
214 
215     @Override
getMainThread()216     public MainThread getMainThread() {
217         return mResourceConstructed.get().getMainThread();
218     }
219 
220     @Override
getModuleUI()221     public CaptureIntentModuleUI getModuleUI() {
222         return mResourceConstructed.get().getModuleUI();
223     }
224 
225     @Override
getCamera()226     public OneCamera getCamera() {
227         return mResourceOpenedCamera.get().getCamera();
228     }
229 
230     private final OneCamera.PictureSaverCallback mPictureSaverCallback =
231             new OneCamera.PictureSaverCallback() {
232                 @Override
233                 public void onRemoteThumbnailAvailable(byte[] jpegImage) {
234                 }
235             };
236 }
237