FileDocCategorySizeDatePackage
LegacyFocusStateMapper.javaAPI DocAndroid 5.1 API12374Thu Mar 12 22:22:10 GMT 2015android.hardware.camera2.legacy

LegacyFocusStateMapper

public class LegacyFocusStateMapper extends Object
Map capture request data into legacy focus state transitions.

This object will asynchronously process auto-focus changes, so no interaction with it is necessary beyond reading the current state and updating with the latest trigger.

Fields Summary
private static String
TAG
private static final boolean
VERBOSE
private final android.hardware.Camera
mCamera
private int
mAfStatePrevious
private String
mAfModePrevious
private final Object
mLock
Guard mAfRun and mAfState
private int
mAfRun
Guard access with mLock
private int
mAfState
Guard access with mLock
Constructors Summary
public LegacyFocusStateMapper(android.hardware.Camera camera)
Instantiate a new focus state mapper.

param
camera a non-{@code null} camera1 device
throws
NullPointerException if any of the args were {@code null}


                                
       
        mCamera = checkNotNull(camera, "camera must not be null");
    
Methods Summary
private static java.lang.StringafStateToString(int afState)

        switch (afState) {
            case CONTROL_AF_STATE_ACTIVE_SCAN:
                return "ACTIVE_SCAN";
            case CONTROL_AF_STATE_FOCUSED_LOCKED:
                return "FOCUSED_LOCKED";
            case CONTROL_AF_STATE_INACTIVE:
                return "INACTIVE";
            case CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
                return "NOT_FOCUSED_LOCKED";
            case CONTROL_AF_STATE_PASSIVE_FOCUSED:
                return "PASSIVE_FOCUSED";
            case CONTROL_AF_STATE_PASSIVE_SCAN:
                return "PASSIVE_SCAN";
            case CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
                return "PASSIVE_UNFOCUSED";
            default :
                return "UNKNOWN(" + afState + ")";
        }
    
public voidmapResultTriggers(android.hardware.camera2.impl.CameraMetadataNative result)
Update the {@code result} camera metadata map with the new value for the {@code control.afState}.

AF callbacks are processed in the background, and each call to {@link #mapResultTriggers} will have the latest AF state as reflected by the camera1 callbacks.

param
result a non-{@code null} result

        checkNotNull(result, "result must not be null");

        int newAfState;
        synchronized (mLock) {
            newAfState = mAfState;
        }

        if (VERBOSE && newAfState != mAfStatePrevious) {
            Log.v(TAG, String.format("mapResultTriggers - afState changed from %s to %s",
                    afStateToString(mAfStatePrevious), afStateToString(newAfState)));
        }

        result.set(CaptureResult.CONTROL_AF_STATE, newAfState);

        mAfStatePrevious = newAfState;
    
public voidprocessRequestTriggers(android.hardware.camera2.CaptureRequest captureRequest, android.hardware.Camera.Parameters parameters)
Process the AF triggers from the request as a camera1 autofocus routine.

This method should be called after the parameters are {@link LegacyRequestMapper mapped} with the request.

Callbacks are processed in the background, and the next call to {@link #mapResultTriggers} will have the latest AF state as reflected by the camera1 callbacks.

None of the arguments will be mutated.

param
captureRequest a non-{@code null} request
param
parameters a non-{@code null} parameters corresponding to this request (read-only)

        checkNotNull(captureRequest, "captureRequest must not be null");

        /*
         * control.afTrigger
         */
        int afTrigger = ParamsUtils.getOrDefault(captureRequest, CONTROL_AF_TRIGGER,
                CONTROL_AF_TRIGGER_IDLE);

        final String afMode = parameters.getFocusMode();

        if (!Objects.equals(mAfModePrevious, afMode)) {
            if (VERBOSE) {
                Log.v(TAG, "processRequestTriggers - AF mode switched from " + mAfModePrevious +
                        " to " + afMode);
            }

            // Switching modes always goes back to INACTIVE; ignore callbacks from previous modes

            synchronized (mLock) {
                ++mAfRun;
                mAfState = CONTROL_AF_STATE_INACTIVE;
            }
            mCamera.cancelAutoFocus();
        }

        mAfModePrevious = afMode;

        // Passive AF Scanning
        {
            final int currentAfRun;

            synchronized (mLock) {
                currentAfRun = mAfRun;
            }

            Camera.AutoFocusMoveCallback afMoveCallback = new Camera.AutoFocusMoveCallback() {
                @Override
                public void onAutoFocusMoving(boolean start, Camera camera) {
                    synchronized (mLock) {
                        int latestAfRun = mAfRun;

                        if (VERBOSE) {
                            Log.v(TAG,
                                    "onAutoFocusMoving - start " + start + " latest AF run " +
                                            latestAfRun + ", last AF run " + currentAfRun
                            );
                        }

                        if (currentAfRun != latestAfRun) {
                            Log.d(TAG,
                                    "onAutoFocusMoving - ignoring move callbacks from old af run"
                                            + currentAfRun
                            );
                            return;
                        }

                        int newAfState = start ?
                                CONTROL_AF_STATE_PASSIVE_SCAN :
                                CONTROL_AF_STATE_PASSIVE_FOCUSED;
                        // We never send CONTROL_AF_STATE_PASSIVE_UNFOCUSED

                        switch (afMode) {
                            case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
                            case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
                                break;
                            // This callback should never be sent in any other AF mode
                            default:
                                Log.w(TAG, "onAutoFocus - got unexpected onAutoFocus in mode "
                                        + afMode);

                        }

                        mAfState = newAfState;
                    }
                }
            };

            // Only set move callback if we can call autofocus.
            switch (afMode) {
                case Parameters.FOCUS_MODE_AUTO:
                case Parameters.FOCUS_MODE_MACRO:
                case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
                case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
                    mCamera.setAutoFocusMoveCallback(afMoveCallback);
            }
        }


        // AF Locking
        switch (afTrigger) {
            case CONTROL_AF_TRIGGER_START:

                int afStateAfterStart;
                switch (afMode) {
                    case Parameters.FOCUS_MODE_AUTO:
                    case Parameters.FOCUS_MODE_MACRO:
                        afStateAfterStart = CONTROL_AF_STATE_ACTIVE_SCAN;
                        break;
                    case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
                    case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
                        afStateAfterStart = CONTROL_AF_STATE_PASSIVE_SCAN;
                        break;
                    default:
                        // EDOF, INFINITY
                        afStateAfterStart = CONTROL_AF_STATE_INACTIVE;
                }

                final int currentAfRun;
                synchronized (mLock) {
                    currentAfRun = ++mAfRun;
                    mAfState = afStateAfterStart;
                }

                if (VERBOSE) {
                    Log.v(TAG, "processRequestTriggers - got AF_TRIGGER_START, " +
                            "new AF run is " + currentAfRun);
                }

                // Avoid calling autofocus unless we are in a state that supports calling this.
                if (afStateAfterStart == CONTROL_AF_STATE_INACTIVE) {
                    break;
                }

                mCamera.autoFocus(new Camera.AutoFocusCallback() {
                    @Override
                    public void onAutoFocus(boolean success, Camera camera) {
                        synchronized (mLock) {
                            int latestAfRun = mAfRun;

                            if (VERBOSE) {
                                Log.v(TAG, "onAutoFocus - success " + success + " latest AF run " +
                                        latestAfRun + ", last AF run " + currentAfRun);
                            }

                            // Ignore old auto-focus results, since another trigger was requested
                            if (latestAfRun != currentAfRun) {
                                Log.d(TAG, String.format("onAutoFocus - ignoring AF callback " +
                                        "(old run %d, new run %d)", currentAfRun, latestAfRun));

                                return;
                            }

                            int newAfState = success ?
                                    CONTROL_AF_STATE_FOCUSED_LOCKED :
                                    CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;

                            switch (afMode) {
                                case Parameters.FOCUS_MODE_AUTO:
                                case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
                                case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
                                case Parameters.FOCUS_MODE_MACRO:
                                    break;
                                // This callback should never be sent in any other AF mode
                                default:
                                    Log.w(TAG, "onAutoFocus - got unexpected onAutoFocus in mode "
                                            + afMode);

                            }

                            mAfState = newAfState;
                        }
                    }
                });

                break;
            case CONTROL_AF_TRIGGER_CANCEL:
                synchronized (mLock) {
                    int updatedAfRun;

                    synchronized (mLock) {
                        updatedAfRun = ++mAfRun;
                        mAfState = CONTROL_AF_STATE_INACTIVE;
                    }

                    mCamera.cancelAutoFocus();

                    if (VERBOSE) {
                        Log.v(TAG, "processRequestTriggers - got AF_TRIGGER_CANCEL, " +
                                "new AF run is " + updatedAfRun);
                    }
                }

                break;
            case CONTROL_AF_TRIGGER_IDLE:
                // No action necessary. The callbacks will handle transitions.
                break;
            default:
                Log.w(TAG, "processRequestTriggers - ignoring unknown control.afTrigger = "
                        + afTrigger);
        }