Home | History | Annotate | Download | only in legacy
      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 android.hardware.camera2.legacy;
     18 
     19 import android.hardware.Camera;
     20 import android.hardware.Camera.Parameters;
     21 import android.hardware.camera2.impl.CameraMetadataNative;
     22 import android.hardware.camera2.CaptureRequest;
     23 import android.hardware.camera2.CaptureResult;
     24 import android.hardware.camera2.utils.ParamsUtils;
     25 import android.util.Log;
     26 
     27 import java.util.Objects;
     28 
     29 import static android.hardware.camera2.CaptureRequest.*;
     30 import static com.android.internal.util.Preconditions.*;
     31 
     32 /**
     33  * Map capture request data into legacy focus state transitions.
     34  *
     35  * <p>This object will asynchronously process auto-focus changes, so no interaction
     36  * with it is necessary beyond reading the current state and updating with the latest trigger.</p>
     37  */
     38 @SuppressWarnings("deprecation")
     39 public class LegacyFocusStateMapper {
     40     private static String TAG = "LegacyFocusStateMapper";
     41     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     42 
     43     private final Camera mCamera;
     44 
     45     private int mAfStatePrevious = CONTROL_AF_STATE_INACTIVE;
     46     private String mAfModePrevious = null;
     47 
     48     /** Guard mAfRun and mAfState */
     49     private final Object mLock = new Object();
     50     /** Guard access with mLock */
     51     private int mAfRun = 0;
     52     /** Guard access with mLock */
     53     private int mAfState = CONTROL_AF_STATE_INACTIVE;
     54 
     55     /**
     56      * Instantiate a new focus state mapper.
     57      *
     58      * @param camera a non-{@code null} camera1 device
     59      *
     60      * @throws NullPointerException if any of the args were {@code null}
     61      */
     62     public LegacyFocusStateMapper(Camera camera) {
     63         mCamera = checkNotNull(camera, "camera must not be null");
     64     }
     65 
     66     /**
     67      * Process the AF triggers from the request as a camera1 autofocus routine.
     68      *
     69      * <p>This method should be called after the parameters are {@link LegacyRequestMapper mapped}
     70      * with the request.</p>
     71      *
     72      * <p>Callbacks are processed in the background, and the next call to {@link #mapResultTriggers}
     73      * will have the latest AF state as reflected by the camera1 callbacks.</p>
     74      *
     75      * <p>None of the arguments will be mutated.</p>
     76      *
     77      * @param captureRequest a non-{@code null} request
     78      * @param parameters a non-{@code null} parameters corresponding to this request (read-only)
     79      */
     80     public void processRequestTriggers(CaptureRequest captureRequest,
     81             Camera.Parameters parameters) {
     82         checkNotNull(captureRequest, "captureRequest must not be null");
     83 
     84         /*
     85          * control.afTrigger
     86          */
     87         int afTrigger = ParamsUtils.getOrDefault(captureRequest, CONTROL_AF_TRIGGER,
     88                 CONTROL_AF_TRIGGER_IDLE);
     89 
     90         final String afMode = parameters.getFocusMode();
     91 
     92         if (!Objects.equals(mAfModePrevious, afMode)) {
     93             if (VERBOSE) {
     94                 Log.v(TAG, "processRequestTriggers - AF mode switched from " + mAfModePrevious +
     95                         " to " + afMode);
     96             }
     97 
     98             // Switching modes always goes back to INACTIVE; ignore callbacks from previous modes
     99 
    100             synchronized (mLock) {
    101                 ++mAfRun;
    102                 mAfState = CONTROL_AF_STATE_INACTIVE;
    103             }
    104             mCamera.cancelAutoFocus();
    105         }
    106 
    107         mAfModePrevious = afMode;
    108 
    109         // Passive AF Scanning
    110         {
    111             final int currentAfRun;
    112 
    113             synchronized (mLock) {
    114                 currentAfRun = mAfRun;
    115             }
    116 
    117             Camera.AutoFocusMoveCallback afMoveCallback = new Camera.AutoFocusMoveCallback() {
    118                 @Override
    119                 public void onAutoFocusMoving(boolean start, Camera camera) {
    120                     synchronized (mLock) {
    121                         int latestAfRun = mAfRun;
    122 
    123                         if (VERBOSE) {
    124                             Log.v(TAG,
    125                                     "onAutoFocusMoving - start " + start + " latest AF run " +
    126                                             latestAfRun + ", last AF run " + currentAfRun
    127                             );
    128                         }
    129 
    130                         if (currentAfRun != latestAfRun) {
    131                             Log.d(TAG,
    132                                     "onAutoFocusMoving - ignoring move callbacks from old af run"
    133                                             + currentAfRun
    134                             );
    135                             return;
    136                         }
    137 
    138                         int newAfState = start ?
    139                                 CONTROL_AF_STATE_PASSIVE_SCAN :
    140                                 CONTROL_AF_STATE_PASSIVE_FOCUSED;
    141                         // We never send CONTROL_AF_STATE_PASSIVE_UNFOCUSED
    142 
    143                         switch (afMode) {
    144                             case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
    145                             case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
    146                                 break;
    147                             // This callback should never be sent in any other AF mode
    148                             default:
    149                                 Log.w(TAG, "onAutoFocus - got unexpected onAutoFocus in mode "
    150                                         + afMode);
    151 
    152                         }
    153 
    154                         mAfState = newAfState;
    155                     }
    156                 }
    157             };
    158 
    159             // Only set move callback if we can call autofocus.
    160             switch (afMode) {
    161                 case Parameters.FOCUS_MODE_AUTO:
    162                 case Parameters.FOCUS_MODE_MACRO:
    163                 case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
    164                 case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
    165                     mCamera.setAutoFocusMoveCallback(afMoveCallback);
    166             }
    167         }
    168 
    169 
    170         // AF Locking
    171         switch (afTrigger) {
    172             case CONTROL_AF_TRIGGER_START:
    173 
    174                 int afStateAfterStart;
    175                 switch (afMode) {
    176                     case Parameters.FOCUS_MODE_AUTO:
    177                     case Parameters.FOCUS_MODE_MACRO:
    178                         afStateAfterStart = CONTROL_AF_STATE_ACTIVE_SCAN;
    179                         break;
    180                     case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
    181                     case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
    182                         afStateAfterStart = CONTROL_AF_STATE_PASSIVE_SCAN;
    183                         break;
    184                     default:
    185                         // EDOF, INFINITY
    186                         afStateAfterStart = CONTROL_AF_STATE_INACTIVE;
    187                 }
    188 
    189                 final int currentAfRun;
    190                 synchronized (mLock) {
    191                     currentAfRun = ++mAfRun;
    192                     mAfState = afStateAfterStart;
    193                 }
    194 
    195                 if (VERBOSE) {
    196                     Log.v(TAG, "processRequestTriggers - got AF_TRIGGER_START, " +
    197                             "new AF run is " + currentAfRun);
    198                 }
    199 
    200                 // Avoid calling autofocus unless we are in a state that supports calling this.
    201                 if (afStateAfterStart == CONTROL_AF_STATE_INACTIVE) {
    202                     break;
    203                 }
    204 
    205                 mCamera.autoFocus(new Camera.AutoFocusCallback() {
    206                     @Override
    207                     public void onAutoFocus(boolean success, Camera camera) {
    208                         synchronized (mLock) {
    209                             int latestAfRun = mAfRun;
    210 
    211                             if (VERBOSE) {
    212                                 Log.v(TAG, "onAutoFocus - success " + success + " latest AF run " +
    213                                         latestAfRun + ", last AF run " + currentAfRun);
    214                             }
    215 
    216                             // Ignore old auto-focus results, since another trigger was requested
    217                             if (latestAfRun != currentAfRun) {
    218                                 Log.d(TAG, String.format("onAutoFocus - ignoring AF callback " +
    219                                         "(old run %d, new run %d)", currentAfRun, latestAfRun));
    220 
    221                                 return;
    222                             }
    223 
    224                             int newAfState = success ?
    225                                     CONTROL_AF_STATE_FOCUSED_LOCKED :
    226                                     CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
    227 
    228                             switch (afMode) {
    229                                 case Parameters.FOCUS_MODE_AUTO:
    230                                 case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
    231                                 case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
    232                                 case Parameters.FOCUS_MODE_MACRO:
    233                                     break;
    234                                 // This callback should never be sent in any other AF mode
    235                                 default:
    236                                     Log.w(TAG, "onAutoFocus - got unexpected onAutoFocus in mode "
    237                                             + afMode);
    238 
    239                             }
    240 
    241                             mAfState = newAfState;
    242                         }
    243                     }
    244                 });
    245 
    246                 break;
    247             case CONTROL_AF_TRIGGER_CANCEL:
    248                 synchronized (mLock) {
    249                     int updatedAfRun;
    250 
    251                     synchronized (mLock) {
    252                         updatedAfRun = ++mAfRun;
    253                         mAfState = CONTROL_AF_STATE_INACTIVE;
    254                     }
    255 
    256                     mCamera.cancelAutoFocus();
    257 
    258                     if (VERBOSE) {
    259                         Log.v(TAG, "processRequestTriggers - got AF_TRIGGER_CANCEL, " +
    260                                 "new AF run is " + updatedAfRun);
    261                     }
    262                 }
    263 
    264                 break;
    265             case CONTROL_AF_TRIGGER_IDLE:
    266                 // No action necessary. The callbacks will handle transitions.
    267                 break;
    268             default:
    269                 Log.w(TAG, "processRequestTriggers - ignoring unknown control.afTrigger = "
    270                         + afTrigger);
    271         }
    272     }
    273 
    274     /**
    275      * Update the {@code result} camera metadata map with the new value for the
    276      * {@code control.afState}.
    277      *
    278      * <p>AF callbacks are processed in the background, and each call to {@link #mapResultTriggers}
    279      * will have the latest AF state as reflected by the camera1 callbacks.</p>
    280      *
    281      * @param result a non-{@code null} result
    282      */
    283     public void mapResultTriggers(CameraMetadataNative result) {
    284         checkNotNull(result, "result must not be null");
    285 
    286         int newAfState;
    287         synchronized (mLock) {
    288             newAfState = mAfState;
    289         }
    290 
    291         if (VERBOSE && newAfState != mAfStatePrevious) {
    292             Log.v(TAG, String.format("mapResultTriggers - afState changed from %s to %s",
    293                     afStateToString(mAfStatePrevious), afStateToString(newAfState)));
    294         }
    295 
    296         result.set(CaptureResult.CONTROL_AF_STATE, newAfState);
    297 
    298         mAfStatePrevious = newAfState;
    299     }
    300 
    301     private static String afStateToString(int afState) {
    302         switch (afState) {
    303             case CONTROL_AF_STATE_ACTIVE_SCAN:
    304                 return "ACTIVE_SCAN";
    305             case CONTROL_AF_STATE_FOCUSED_LOCKED:
    306                 return "FOCUSED_LOCKED";
    307             case CONTROL_AF_STATE_INACTIVE:
    308                 return "INACTIVE";
    309             case CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
    310                 return "NOT_FOCUSED_LOCKED";
    311             case CONTROL_AF_STATE_PASSIVE_FOCUSED:
    312                 return "PASSIVE_FOCUSED";
    313             case CONTROL_AF_STATE_PASSIVE_SCAN:
    314                 return "PASSIVE_SCAN";
    315             case CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
    316                 return "PASSIVE_UNFOCUSED";
    317             default :
    318                 return "UNKNOWN(" + afState + ")";
    319         }
    320     }
    321 }
    322