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.ui.focus;
18 
19 import android.graphics.RectF;
20 
21 import com.android.camera.async.MainThread;
22 import com.android.camera.debug.Log;
23 import com.android.camera.debug.Log.Tag;
24 import com.android.camera.one.OneCamera.FocusDistanceListener;
25 import com.android.camera.ui.motion.LinearScale;
26 
27 /**
28  * The focus controller interacts with the focus ring UI element.
29  */
30 public class FocusController implements FocusDistanceListener {
31     private static final Tag TAG = new Tag("FocusController");
32 
33     private final FocusRing mFocusRing;
34     private final FocusSound mFocusSound;
35     private final MainThread mMainThread;
36 
FocusController(FocusRing focusRing, FocusSound focusSound, MainThread mainThread)37     public FocusController(FocusRing focusRing, FocusSound focusSound, MainThread mainThread) {
38         mFocusRing = focusRing;
39         mFocusSound = focusSound;
40         mMainThread = mainThread;
41     }
42 
43     /**
44      * Show a passive focus animation at the center of the active area.
45      * This will likely be different than the view bounds due to varying image
46      * ratios and dimensions.
47      */
showPassiveFocusAtCenter()48     public void showPassiveFocusAtCenter() {
49         mMainThread.execute(new Runnable() {
50             @Override
51             public void run() {
52                 Log.v(TAG, "Running showPassiveFocusAtCenter()");
53                 mFocusRing.startPassiveFocus();
54                 mFocusRing.centerFocusLocation();
55             }
56         });
57     }
58 
59     /**
60      * Show a passive focus animation at the given viewX and viewY position.
61      * This is usually indicates the camera subsystem kicked off an auto-focus
62      * at the given screen position.
63      *
64      * @param viewX the view's x coordinate
65      * @param viewY the view's y coordinate
66      */
showPassiveFocusAt(final int viewX, final int viewY)67     public void showPassiveFocusAt(final int viewX, final int viewY) {
68         mMainThread.execute(new Runnable() {
69             @Override
70             public void run() {
71                 Log.v(TAG, "Running showPassiveFocusAt(" + viewX + ", " + viewY + ")");
72                 mFocusRing.startPassiveFocus();
73                 mFocusRing.setFocusLocation(viewX, viewY);
74             }
75         });
76     }
77 
78     /**
79      * Show an active focus animation at the given viewX and viewY position.
80      * This is normally initiated by the user touching the screen at a given
81      * point.
82      *
83      * @param viewX the view's x coordinate
84      * @param viewY the view's y coordinate
85      */
showActiveFocusAt(final int viewX, final int viewY)86     public void showActiveFocusAt(final int viewX, final int viewY) {
87         mMainThread.execute(new Runnable() {
88             @Override
89             public void run() {
90                 Log.v(TAG, "showActiveFocusAt(" + viewX + ", " + viewY + ")");
91                 mFocusRing.startActiveFocus();
92                 mFocusRing.setFocusLocation(viewX, viewY);
93 
94                 // TODO: Enable focus sound when better audio controls exist.
95                 // mFocusSound.play();
96             }
97         });
98     }
99 
100     /**
101      * Stop any currently executing focus animation.
102      */
clearFocusIndicator()103     public void clearFocusIndicator() {
104         mMainThread.execute(new Runnable() {
105             @Override
106             public void run() {
107                 Log.v(TAG, "clearFocusIndicator()");
108                 mFocusRing.stopFocusAnimations();
109             }
110         });
111     }
112 
113     /**
114      * Computing the correct location for the focus ring requires knowing
115      * the screen position and size of the preview area so the drawing
116      * operations can be clipped correctly.
117      */
configurePreviewDimensions(final RectF previewArea)118     public void configurePreviewDimensions(final RectF previewArea) {
119         mMainThread.execute(new Runnable() {
120             @Override
121             public void run() {
122                Log.v(TAG, "configurePreviewDimensions(" + previewArea + ")");
123                mFocusRing.configurePreviewDimensions(previewArea);
124             }
125         });
126     }
127 
128     /**
129      * Set the radius of the focus ring as a radius between 0 and 1.
130      * This will map to the min and max values computed for the UI.
131      */
setFocusRatio(final float ratio)132     public void setFocusRatio(final float ratio) {
133         mMainThread.execute(new Runnable() {
134             @Override
135             public void run() {
136                 if (mFocusRing.isPassiveFocusRunning() ||
137                       mFocusRing.isActiveFocusRunning()) {
138                     mFocusRing.setRadiusRatio(ratio);
139                 }
140             }
141         });
142     }
143 
144     @Override
onFocusDistance(float lensDistance, LinearScale lensRange)145     public void onFocusDistance(float lensDistance, LinearScale lensRange) {
146         if (lensRange.isInDomain(lensDistance)) {
147             setFocusRatio(lensRange.scale(lensDistance));
148         }
149     }
150 }
151