11d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde/*
21d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * Copyright (C) 2015 The Android Open Source Project
31d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde *
41d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * Licensed under the Apache License, Version 2.0 (the "License");
51d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * you may not use this file except in compliance with the License.
61d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * You may obtain a copy of the License at
71d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde *
81d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde *      http://www.apache.org/licenses/LICENSE-2.0
91d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde *
101d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * Unless required by applicable law or agreed to in writing, software
111d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * distributed under the License is distributed on an "AS IS" BASIS,
121d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * See the License for the specific language governing permissions and
141d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * limitations under the License.
151d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde */
161d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
171d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdepackage com.android.camera.one.v1;
181d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
191d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport android.hardware.Camera;
201d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
211d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.debug.Log;
221d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.debug.Log.Tag;
231d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.device.CameraId;
241d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.one.OneCamera.Facing;
251d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.one.OneCameraAccessException;
261d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.one.OneCameraCharacteristics;
271d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.one.OneCameraManager;
281d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.google.common.base.Optional;
291d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
301d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport javax.annotation.Nonnull;
311d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
321d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde/**
331d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * The {@link com.android.camera.one.OneCameraManager} implementation on top of the Camera API 1.
341d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde */
351d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdepublic class LegacyOneCameraManagerImpl implements OneCameraManager {
361d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private static final Tag TAG = new Tag("LegacyHM");
371d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private static final int NO_DEVICE = -1;
381d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private static final long CAMERA_ACCESS_TIMEOUT_MILLIS = 750;
391d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
401d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    // Lazy singleton
411d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private static Optional<LegacyOneCameraManagerImpl> INSTANCE;
421d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
431d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private final CameraId mFirstBackCameraId;
441d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private final CameraId mFirstFrontCameraId;
451d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private final Camera.CameraInfo[] mCameraInfos;
461d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
471d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private OneCameraCharacteristics mBackCameraCharacteristics;
481d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private OneCameraCharacteristics mFrontCameraCharacteristics;
491d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
501d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public static Optional<LegacyOneCameraManagerImpl> instance() {
511d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        if (INSTANCE != null) {
521d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            return INSTANCE;
531d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        }
541d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
551d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        int numberOfCameras;
561d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        Camera.CameraInfo[] cameraInfos;
571d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        try {
581d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            numberOfCameras = Camera.getNumberOfCameras();
591d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            cameraInfos = new Camera.CameraInfo[numberOfCameras];
601d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            for (int i = 0; i < numberOfCameras; i++) {
611d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                cameraInfos[i] = new Camera.CameraInfo();
621d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                Camera.getCameraInfo(i, cameraInfos[i]);
631d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            }
641d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        } catch (RuntimeException ex) {
651d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            Log.e(TAG, "Exception while creating CameraDeviceInfo", ex);
661d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            return Optional.absent();
671d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        }
681d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
691d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        int firstFront = NO_DEVICE;
701d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        int firstBack = NO_DEVICE;
711d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        // Get the first (smallest) back and first front camera id.
721d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        for (int i = numberOfCameras - 1; i >= 0; i--) {
731d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
741d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                firstBack = i;
751d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            } else {
761d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
771d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                    firstFront = i;
781d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                }
791d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            }
801d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        }
811d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
821d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        CameraId frontCameraId = firstFront >= 0 ? CameraId.fromLegacyId(firstFront) : null;
831d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        CameraId backCameraId = firstBack >= 0 ? CameraId.fromLegacyId(firstBack) : null;
841d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
851d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        LegacyOneCameraManagerImpl cameraManager =
861d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde              new LegacyOneCameraManagerImpl(backCameraId, frontCameraId, cameraInfos);
871d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        INSTANCE = Optional.of(cameraManager);
881d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        return INSTANCE;
891d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    }
901d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
911d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    /**
921d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde     * Instantiates a new {@link com.android.camera.one.OneCameraManager} for Camera1 API.
931d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde     */
941d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public LegacyOneCameraManagerImpl(
951d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde          CameraId firstBackCameraId,
961d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde          CameraId firstFrontCameraId,
971d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde          Camera.CameraInfo[] info) {
981d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        mFirstBackCameraId = firstBackCameraId;
991d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        mFirstFrontCameraId = firstFrontCameraId;
1001d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1011d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        mCameraInfos = info;
1021d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    }
1031d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1041d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    @Override
1051d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public boolean hasCamera() {
1061d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        return false;
1071d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    }
1081d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1091d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    @Override
1101d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public boolean hasCameraFacing(@Nonnull Facing facing) {
1111d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        return findFirstCameraFacing(facing) != null;
1121d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    }
1131d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1141d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    @Override
1151d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public CameraId findFirstCamera() {
1161d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        return mFirstBackCameraId;
1171d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    }
1181d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1191d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    @Override
1201d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public CameraId findFirstCameraFacing(@Nonnull Facing facing) {
1211d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        if (facing == Facing.BACK && mFirstBackCameraId != null) {
1221d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            return mFirstBackCameraId;
1231d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        } else if (facing == Facing.FRONT && mFirstFrontCameraId != null) {
1241d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            return mFirstFrontCameraId;
1251d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        }
1261d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        return null;
1271d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    }
1281d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1291d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    @Override
1301d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public OneCameraCharacteristics getOneCameraCharacteristics(@Nonnull CameraId cameraId)
1311d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde          throws OneCameraAccessException {
1321d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        // Returns the cached object if there exists one.
1331d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        if (cameraId.equals(mFirstBackCameraId)) {
1341d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            if (mBackCameraCharacteristics == null) {
1351d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                Log.w(TAG, "WARNING: Computing potentially long running device access!"
1361d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                      + cameraId);
1371d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                mBackCameraCharacteristics = computeCameraCharacteristics(cameraId);
1381d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            }
1391d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1401d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            Log.w(TAG, "Returning camera characteristics for back camera."
1411d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                  + cameraId);
1421d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1431d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            return mBackCameraCharacteristics;
1441d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        } else if (cameraId.equals(mFirstFrontCameraId)) {
1451d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            if (mFrontCameraCharacteristics == null) {
1461d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                Log.w(TAG, "WARNING: Computing potentially long running device access!"
1471d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                      + cameraId);
1481d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                mFrontCameraCharacteristics = computeCameraCharacteristics(cameraId);
1491d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            }
1501d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1511d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            Log.w(TAG, "Returning camera characteristics for front camera."
1521d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                  + cameraId);
1531d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            return mFrontCameraCharacteristics;
1541d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        }
1551d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1561d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        Log.e(TAG, "BackCamera: " + mFirstBackCameraId + ", " + " ==? " + (mFirstBackCameraId
1571d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde              == cameraId));
1581d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        Log.e(TAG, "FrontCamera: " + mFirstFrontCameraId);
1591d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        Log.e(TAG, "No matching camera id for: " + cameraId);
1601d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        return null;
1611d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    }
1621d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1631d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public OneCameraCharacteristics computeCameraCharacteristics(CameraId key)
1641d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde          throws OneCameraAccessException  {
1651d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        OneCameraCharacteristics characteristics;
1661d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        Camera camera = null;
1671d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        try {
1681d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            camera = Camera.open(key.getLegacyValue());
1691d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            Camera.Parameters cameraParameters = camera.getParameters();
1701d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            if (cameraParameters == null) {
1711d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                Log.e(TAG, "Camera object returned null parameters!");
1721d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                throw new OneCameraAccessException("API1 Camera.getParameters() returned null");
1731d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            }
1741d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            characteristics = new OneCameraCharacteristicsImpl(
1751d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                  mCameraInfos[key.getLegacyValue()], cameraParameters);
1761d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        } finally {
1771d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            if (camera != null) {
1781d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde                camera.release();
1791d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            }
1801d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        }
1811d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1821d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        return characteristics;
1831d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    }
1841d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde}