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
17package com.android.camera.one;
18
19import android.content.Context;
20import android.location.Location;
21import android.net.Uri;
22import android.view.Surface;
23
24import com.android.camera.session.CaptureSession;
25import com.android.camera.settings.SettingsManager;
26import com.android.camera.ui.motion.LinearScale;
27import com.android.camera.util.Size;
28
29import java.io.File;
30
31import javax.annotation.Nonnull;
32
33/**
34 * OneCamera is a camera API tailored around our Google Camera application
35 * needs. It's not a general purpose API but instead offers an API with exactly
36 * what's needed from the app's side.
37 */
38public interface OneCamera {
39
40    /** Which way the camera is facing. */
41    public static enum Facing {
42        FRONT, BACK;
43    }
44
45    /**
46     * Auto focus system status; 1:1 mapping from camera2 AF_STATE.
47     * <ul>
48     * <li>{@link #INACTIVE}</li>
49     * <li>{@link #ACTIVE_SCAN}</li>
50     * <li>{@link #ACTIVE_FOCUSED}</li>
51     * <li>{@link #ACTIVE_UNFOCUSED}</li>
52     * <li>{@link #PASSIVE_SCAN}</li>
53     * <li>{@link #PASSIVE_FOCUSED}</li>
54     * <li>{@link #PASSIVE_UNFOCUSED}</li>
55     * </ul>
56     */
57    public static enum AutoFocusState {
58        /** Indicates AF system is inactive for some reason (could be an error). */
59        INACTIVE,
60        /** Indicates active scan in progress. */
61        ACTIVE_SCAN,
62        /** Indicates active scan success (in focus). */
63        ACTIVE_FOCUSED,
64        /** Indicates active scan failure (not in focus). */
65        ACTIVE_UNFOCUSED,
66        /** Indicates passive scan in progress. */
67        PASSIVE_SCAN,
68        /** Indicates passive scan success (in focus). */
69        PASSIVE_FOCUSED,
70        /** Indicates passive scan failure (not in focus). */
71        PASSIVE_UNFOCUSED
72    }
73
74    /**
75     * Classes implementing this interface will be called when the camera was
76     * opened or failed to open.
77     */
78    public static interface OpenCallback {
79        /**
80         * Called when the camera was opened successfully.
81         *
82         * @param camera the camera instance that was successfully opened
83         */
84        public void onCameraOpened(@Nonnull OneCamera camera);
85
86        /**
87         * Called if opening the camera failed.
88         */
89        public void onFailure();
90
91        /**
92         * Called if the camera is closed or disconnected while attempting to
93         * open.
94         */
95        public void onCameraClosed();
96    }
97
98    /**
99     * Classes implementing this interface can be informed when we're ready to
100     * take a picture of if setting up the capture pipeline failed.
101     */
102    public static interface CaptureReadyCallback {
103        /** After this is called, the system is ready for capture requests. */
104        public void onReadyForCapture();
105
106        /**
107         * Indicates that something went wrong during setup and the system is
108         * not ready for capture requests.
109         */
110        public void onSetupFailed();
111    }
112
113    /**
114     * Classes implementing this interface can be informed when the state of
115     * capture changes.
116     */
117    public static interface ReadyStateChangedListener {
118        /**
119         * Called when the camera is either ready or not ready to take a picture
120         * right now.
121         */
122        public void onReadyStateChanged(boolean readyForCapture);
123    }
124
125    /**
126     * A class implementing this interface can be passed into the call to take a
127     * picture in order to receive the resulting image or updated about the
128     * progress.
129     */
130    public static interface PictureCallback {
131        /**
132         * Called near the the when an image is being exposed for cameras which
133         * are exposing a single frame, so that a UI can be presented for the
134         * capture.
135         */
136        public void onQuickExpose();
137
138        /**
139         * Called when a thumbnail image is provided before the final image is
140         * finished.
141         */
142        public void onThumbnailResult(byte[] jpegData);
143
144        /**
145         * Called when the final picture is done taking
146         *
147         * @param session the capture session
148         */
149        public void onPictureTaken(CaptureSession session);
150
151        /**
152         * Called when the picture has been saved to disk.
153         *
154         * @param uri the URI of the stored data.
155         */
156        public void onPictureSaved(Uri uri);
157
158        /**
159         * Called when picture taking failed.
160         */
161        public void onPictureTakingFailed();
162
163        /**
164         * Called when capture session is reporting a processing update. This
165         * should only be called by capture sessions that require the user to
166         * hold still for a while.
167         *
168         * @param progress a value from 0...1, indicating the current processing
169         *            progress.
170         */
171        public void onTakePictureProgress(float progress);
172    }
173
174    /**
175     * A class implementing this interface can be passed to a picture saver in
176     * order to receive image processing events.
177     */
178    public static interface PictureSaverCallback {
179        /**
180         * Called when compressed data for Thumbnail on a remote device (such as
181         * Android wear) is available.
182         */
183        public void onRemoteThumbnailAvailable(byte[] jpegImage);
184    }
185
186    /**
187     * Classes implementing this interface will be called when the state of the
188     * focus changes. Guaranteed not to stay stuck in scanning state past some
189     * reasonable timeout even if Camera API is stuck.
190     */
191    public static interface FocusStateListener {
192        /**
193         * Called when state of auto focus system changes.
194         *
195         * @param state Current auto focus state.
196         * @param frameNumber Frame number if available.
197         */
198        public void onFocusStatusUpdate(AutoFocusState state, long frameNumber);
199    }
200
201    /**
202     * Classes implementing this interface will be called when the focus
203     * distance of the physical lens changes.
204     */
205    public static interface FocusDistanceListener {
206        /**
207         * Called when physical lens distance on the camera changes.
208         */
209        public void onFocusDistance(float distance, LinearScale lensRange);
210    }
211
212    /**
213     * Single instance of the current camera AF state.
214     */
215    public static class FocusState {
216        public final float lensDistance;
217        public final boolean isActive;
218
219        /**
220         * @param lensDistance The current focal distance.
221         * @param isActive Whether the lens is moving, e.g. because of either an
222         *            "active scan" or a "passive scan".
223         */
224        public FocusState(float lensDistance, boolean isActive) {
225            this.lensDistance = lensDistance;
226            this.isActive = isActive;
227        }
228
229        @Override
230        public boolean equals(Object o) {
231            if (this == o)
232                return true;
233            if (o == null || getClass() != o.getClass())
234                return false;
235
236            FocusState that = (FocusState) o;
237
238            if (Float.compare(that.lensDistance, lensDistance) != 0)
239                return false;
240            if (isActive != that.isActive)
241                return false;
242
243            return true;
244        }
245
246        @Override
247        public int hashCode() {
248            int result = (lensDistance != +0.0f ? Float.floatToIntBits(lensDistance) : 0);
249            result = 31 * result + (isActive ? 1 : 0);
250            return result;
251        }
252
253        @Override
254        public String toString() {
255            return "FocusState{" +
256                  "lensDistance=" + lensDistance +
257                  ", isActive=" + isActive +
258                  '}';
259        }
260    }
261
262    /**
263     * Parameters to be given to capture requests.
264     */
265    public static abstract class CaptureParameters {
266        /** The title/filename (without suffix) for this capture. */
267        public final String title;
268
269        /** The device orientation so we can compute the right JPEG rotation. */
270        public final int orientation;
271
272        /** The location of this capture. */
273        public final Location location;
274
275        /** Set this to provide a debug folder for this capture. */
276        public final File debugDataFolder;
277
278        public CaptureParameters(String title, int orientation, Location location, File
279                debugDataFolder) {
280            this.title = title;
281            this.orientation = orientation;
282            this.location = location;
283            this.debugDataFolder = debugDataFolder;
284        }
285    }
286
287    /**
288     * Parameters to be given to photo capture requests.
289     */
290    public static class PhotoCaptureParameters extends CaptureParameters {
291        /**
292         * Flash modes.
293         * <p>
294         */
295        public static enum Flash {
296            AUTO("auto"), OFF("off"), ON("on");
297
298            /**
299             * The machine-readable (via {@link #encodeSettingsString} and
300             * {@link #decodeSettingsString} string used to represent this flash
301             * mode in {@link SettingsManager}.
302             * <p>
303             * This must be in sync with R.arrays.pref_camera_flashmode_entryvalues.
304             */
305            private final String mSettingsString;
306
307            Flash(@Nonnull String settingsString) {
308                mSettingsString = settingsString;
309            }
310
311            @Nonnull
312            public String encodeSettingsString() {
313                return mSettingsString;
314            }
315
316            @Nonnull
317            public static Flash decodeSettingsString(@Nonnull String setting) {
318                if (AUTO.encodeSettingsString().equals(setting)) {
319                    return AUTO;
320                } else if (OFF.encodeSettingsString().equals(setting)) {
321                    return OFF;
322                } else if (ON.encodeSettingsString().equals(setting)) {
323                    return ON;
324                }
325                throw new IllegalArgumentException("Not a valid setting");
326            }
327        }
328
329        /** Called when the capture is completed or failed. */
330        public final PictureCallback callback;
331        public final PictureSaverCallback saverCallback;
332        /** The heading of the device at time of capture. In degrees. */
333        public final int heading;
334        /** Zoom value. */
335        public final float zoom;
336        /** Timer duration in seconds or 0 for no timer. */
337        public final float timerSeconds;
338
339        public PhotoCaptureParameters(String title, int orientation, Location location, File
340                debugDataFolder, PictureCallback callback, PictureSaverCallback saverCallback,
341                int heading, float zoom, float timerSeconds) {
342            super(title, orientation, location, debugDataFolder);
343            this.callback = callback;
344            this.saverCallback = saverCallback;
345            this.heading = heading;
346            this.zoom = zoom;
347            this.timerSeconds = timerSeconds;
348        }
349    }
350
351
352    /**
353     * Meters and triggers auto focus scan with ROI around tap point.
354     * <p/>
355     * Normalized coordinates are referenced to portrait preview window with (0,
356     * 0) top left and (1, 1) bottom right. Rotation has no effect.
357     *
358     * @param nx normalized x coordinate.
359     * @param ny normalized y coordinate.
360     */
361    public void triggerFocusAndMeterAtPoint(float nx, float ny);
362
363    /**
364     * Call this to take a picture.
365     *
366     * @param params parameters for taking pictures.
367     * @param session the capture session for this picture.
368     */
369    public void takePicture(PhotoCaptureParameters params, CaptureSession session);
370
371    /**
372     * Sets or replaces a listener that is called whenever the focus state of
373     * the camera changes.
374     */
375    public void setFocusStateListener(FocusStateListener listener);
376
377    /**
378     * Sets or replaces a listener that is called whenever the focus state of
379     * the camera changes.
380     */
381    public void setFocusDistanceListener(FocusDistanceListener listener);
382
383    /**
384     * Sets or replaces a listener that is called whenever the state of the
385     * camera changes to be either ready or not ready to take another picture.
386     */
387    public void setReadyStateChangedListener(ReadyStateChangedListener listener);
388
389    /**
390     * Starts a preview stream and renders it to the given surface.
391     *
392     * @param surface the surface on which to render preview frames
393     * @param listener
394     */
395    public void startPreview(Surface surface, CaptureReadyCallback listener);
396
397    /**
398     * Closes the camera.
399     */
400    public void close();
401
402    /**
403     * @return The direction of the camera.
404     */
405    public Facing getDirection();
406
407    /**
408     * Get the maximum zoom value.
409     *
410     * @return A float number to represent the maximum zoom value(>= 1.0).
411     */
412    public float getMaxZoom();
413
414    /**
415     * This function sets the current zoom ratio value.
416     * <p>
417     * The zoom range must be [1.0, maxZoom]. The maxZoom can be queried by
418     * {@link #getMaxZoom}.
419     *
420     * @param zoom Zoom ratio value passed to scaler.
421     */
422    public void setZoom(float zoom);
423
424    /**
425     * Based on the selected picture size, this returns the best preview size.
426     *
427     * @param pictureSize the picture size as selected by the user. A camera
428     *            might choose not to obey these and therefore the returned
429     *            preview size might not match the aspect ratio of the given
430     *            size.
431     * @param context the android application context
432     * @return The preview size that best matches the picture aspect ratio that
433     *         will be taken.
434     */
435    public Size pickPreviewSize(Size pictureSize, Context context);
436}
437