Merge "SnapdragonCamera: Fix auto HDR indication issue" into camera.lnx.1.0-dev.1.0
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 13e4f5d..ac727e2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -4,7 +4,7 @@
package="org.codeaurora.snapcam">
<uses-sdk
- android:minSdkVersion="21"
+ android:minSdkVersion="23"
android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
diff --git a/res/layout/capture_module.xml b/res/layout/capture_module.xml
index 2715dcb..02c32ac 100644
--- a/res/layout/capture_module.xml
+++ b/res/layout/capture_module.xml
@@ -40,8 +40,8 @@
<SurfaceView
android:id="@+id/mdp_preview_content2"
- android:layout_width="100dp"
- android:layout_height="100dp" />
+ android:layout_width="300dp"
+ android:layout_height="300dp" />
</FrameLayout>
<View
diff --git a/res/layout/video_module.xml b/res/layout/video_module.xml
index 1c1db44..c106351 100644
--- a/res/layout/video_module.xml
+++ b/res/layout/video_module.xml
@@ -26,8 +26,7 @@
<SurfaceView
android:id="@+id/mdp_preview_content"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone" />
+ android:layout_height="match_parent" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
diff --git a/res/values/qcomarrays.xml b/res/values/qcomarrays.xml
index a4c4637..40c8b8a 100644
--- a/res/values/qcomarrays.xml
+++ b/res/values/qcomarrays.xml
@@ -863,5 +863,15 @@
<item>@string/pref_camera_dual_camera_value_bayer</item>
<item>@string/pref_camera_dual_camera_value_mono</item>
</string-array>
+
+ <string-array name="pref_camera_mono_preview_entries" translatable="true">
+ <item>@string/pref_camera_mono_preview_entry_on</item>
+ <item>@string/pref_camera_mono_preview_entry_off</item>
+ </string-array>
+
+ <string-array name="pref_camera_mono_preview_entryvalues" translatable="false">
+ <item>@string/pref_camera_mono_preview_value_on</item>
+ <item>@string/pref_camera_mono_preview_value_off</item>
+ </string-array>
</resources>
diff --git a/res/values/qcomstrings.xml b/res/values/qcomstrings.xml
index 0e21bb5..888000c 100644
--- a/res/values/qcomstrings.xml
+++ b/res/values/qcomstrings.xml
@@ -953,9 +953,8 @@
<string name="pref_camera_camera2_value_enable">enable</string>
<string name="pref_camera_camera2_value_disable">disable</string>
-
<string name="pref_camera_dual_camera_title">Dual Camera Mode</string>
- <string name="pref_camera_dual_camera_default">bayer</string>
+ <string name="pref_camera_dual_camera_default">dual</string>
<string name="pref_camera_dual_camera_entry_dual">Dual-camera Linked</string>
<string name="pref_camera_dual_camera_entry_bayer">Single Bayer Camera</string>
<string name="pref_camera_dual_camera_entry_mono">Single Mono Camera</string>
@@ -963,5 +962,13 @@
<string name="pref_camera_dual_camera_value_dual">dual</string>
<string name="pref_camera_dual_camera_value_bayer">bayer</string>
<string name="pref_camera_dual_camera_value_mono">mono</string>
+
+ <string name="pref_camera_mono_preview_title">Mono Preview</string>
+ <string name="pref_camera_mono_preview_default">off</string>
+ <string name="pref_camera_mono_preview_entry_on">On</string>
+ <string name="pref_camera_mono_preview_entry_off">Off</string>
+
+ <string name="pref_camera_mono_preview_value_on">on</string>
+ <string name="pref_camera_mono_preview_value_off">off</string>
</resources>
diff --git a/res/xml/camera_preferences.xml b/res/xml/camera_preferences.xml
index 028ff4d..86eb36f 100644
--- a/res/xml/camera_preferences.xml
+++ b/res/xml/camera_preferences.xml
@@ -379,4 +379,11 @@
camera:title="@string/pref_camera_dual_camera_title"
camera:entries="@array/pref_camera_dual_camera_entries"
camera:entryValues="@array/pref_camera_dual_camera_entryvalues" />
+
+ <ListPreference
+ camera:key="pref_camera_mono_preview_key"
+ camera:defaultValue="@string/pref_camera_mono_preview_default"
+ camera:title="@string/pref_camera_mono_preview_title"
+ camera:entries="@array/pref_camera_mono_preview_entries"
+ camera:entryValues="@array/pref_camera_mono_preview_entryvalues" />
</PreferenceGroup>
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 80387a9..fafb408 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -1813,7 +1813,9 @@
public void onModuleSelected(int moduleIndex) {
if (moduleIndex == 0 && CAMERA_2_ON) moduleIndex = ModuleSwitcher.CAPTURE_MODULE_INDEX;
if (mCurrentModuleIndex == moduleIndex) {
- return;
+ if (mCurrentModuleIndex != ModuleSwitcher.CAPTURE_MODULE_INDEX) {
+ return;
+ }
}
CameraHolder.instance().keep();
closeModule(mCurrentModule);
@@ -1840,7 +1842,6 @@
mCameraVideoModuleRootView.setVisibility(View.GONE);
mCameraPanoModuleRootView.setVisibility(View.GONE);
mCameraCaptureModuleRootView.setVisibility(View.GONE);
- mCameraRootFrame.removeAllViews();
mCurrentModuleIndex = moduleIndex;
switch (moduleIndex) {
case ModuleSwitcher.VIDEO_MODULE_INDEX:
@@ -1851,7 +1852,6 @@
mVideoModule.reinit();
}
mCurrentModule = mVideoModule;
- mCameraRootFrame.addView(mCameraVideoModuleRootView);
mCameraVideoModuleRootView.setVisibility(View.VISIBLE);
break;
@@ -1863,7 +1863,6 @@
mPhotoModule.reinit();
}
mCurrentModule = mPhotoModule;
- mCameraRootFrame.addView(mCameraPhotoModuleRootView);
mCameraPhotoModuleRootView.setVisibility(View.VISIBLE);
break;
@@ -1873,7 +1872,6 @@
mPanoModule.init(this, mCameraPanoModuleRootView);
}
mCurrentModule = mPanoModule;
- mCameraRootFrame.addView(mCameraPanoModuleRootView);
mCameraPanoModuleRootView.setVisibility(View.VISIBLE);
break;
@@ -1883,7 +1881,6 @@
mCaptureModule.init(this, mCameraCaptureModuleRootView);
}
mCurrentModule = mCaptureModule;
- mCameraRootFrame.addView(mCameraCaptureModuleRootView);
mCameraCaptureModuleRootView.setVisibility(View.VISIBLE);
break;
case ModuleSwitcher.LIGHTCYCLE_MODULE_INDEX: //Unused module for now
@@ -1897,7 +1894,6 @@
mPhotoModule.reinit();
}
mCurrentModule = mPhotoModule;
- mCameraRootFrame.addView(mCameraPhotoModuleRootView);
mCameraPhotoModuleRootView.setVisibility(View.VISIBLE);
break;
}
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 48d161d..b0bc9c8 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -248,6 +248,7 @@
public static final String KEY_CAMERA2 = "pref_camera_camera2_key";
public static final String KEY_DUAL_CAMERA = "pref_camera_dual_camera_key";
+ public static final String KEY_MONO_PREVIEW = "pref_camera_mono_preview_key";
public static final String KEY_REFOCUS_PROMPT = "refocus-prompt";
diff --git a/src/com/android/camera/CaptureMenu.java b/src/com/android/camera/CaptureMenu.java
index dbc8132..99f919a 100644
--- a/src/com/android/camera/CaptureMenu.java
+++ b/src/com/android/camera/CaptureMenu.java
@@ -26,6 +26,7 @@
import android.graphics.Rect;
import android.preference.PreferenceManager;
import android.text.TextUtils;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -91,14 +92,24 @@
mOtherKeys1 = new String[]{
CameraSettings.KEY_FLASH_MODE,
+ CameraSettings.KEY_RECORD_LOCATION,
+ CameraSettings.KEY_JPEG_QUALITY,
+ CameraSettings.KEY_CAMERA_SAVEPATH,
+ CameraSettings.KEY_WHITE_BALANCE,
CameraSettings.KEY_CAMERA2,
CameraSettings.KEY_DUAL_CAMERA
};
+ //Todo: 2nd string to contain only developer settings
mOtherKeys2 = new String[]{
CameraSettings.KEY_FLASH_MODE,
+ CameraSettings.KEY_RECORD_LOCATION,
+ CameraSettings.KEY_JPEG_QUALITY,
+ CameraSettings.KEY_CAMERA_SAVEPATH,
+ CameraSettings.KEY_WHITE_BALANCE,
CameraSettings.KEY_CAMERA2,
- CameraSettings.KEY_DUAL_CAMERA
+ CameraSettings.KEY_DUAL_CAMERA,
+ CameraSettings.KEY_MONO_PREVIEW
};
}
@@ -106,9 +117,8 @@
@Override
// Hit when an item in a popup gets selected
public void onListPrefChanged(ListPreference pref) {
- animateFadeOut(mListSubMenu, 2);
onSettingChanged(pref);
- ((ListMenu) mListMenu).resetHighlight();
+ closeView();
}
public boolean handleBackKey() {
@@ -384,6 +394,12 @@
listMenu.initialize(mPreferenceGroup, keys);
mListMenu = listMenu;
+ ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_DUAL_CAMERA);
+ if (!pref.getValue().equals("dual")) {
+ setPreference(CameraSettings.KEY_MONO_PREVIEW, "off");
+ mListMenu.setPreferenceEnabled(CameraSettings.KEY_MONO_PREVIEW, false);
+ }
+
if (mListener != null) {
mListener.onSharedPreferenceChanged();
}
@@ -516,18 +532,29 @@
@Override
public void onSettingChanged(ListPreference pref) {
super.onSettingChanged(pref);
- if (same(pref, CameraSettings.KEY_CAMERA2, "enable")) {
+ String key = pref.getKey();
+ String value = pref.getValue();
+ Log.d(TAG, "" + key + " " + value);
+ //Todo: restructure by using switch and create function for each case
+ if (key.equals(CameraSettings.KEY_CAMERA2)) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(mActivity);
- prefs.edit().putBoolean(CameraSettings.KEY_CAMERA2, true).apply();
- CameraActivity.CAMERA_2_ON = true;
- mActivity.onModuleSelected(ModuleSwitcher.CAPTURE_MODULE_INDEX);
- } else if (notSame(pref, CameraSettings.KEY_CAMERA2, "enable")) {
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(mActivity);
- prefs.edit().putBoolean(CameraSettings.KEY_CAMERA2, false).apply();
- CameraActivity.CAMERA_2_ON = false;
- mActivity.onModuleSelected(ModuleSwitcher.PHOTO_MODULE_INDEX);
+ if (value.equals("enable")) {
+ prefs.edit().putBoolean(CameraSettings.KEY_CAMERA2, true).apply();
+ CameraActivity.CAMERA_2_ON = true;
+ mActivity.onModuleSelected(ModuleSwitcher.CAPTURE_MODULE_INDEX);
+ } else if (value.equals("disable")) {
+ prefs.edit().putBoolean(CameraSettings.KEY_CAMERA2, false).apply();
+ CameraActivity.CAMERA_2_ON = false;
+ mActivity.onModuleSelected(ModuleSwitcher.PHOTO_MODULE_INDEX);
+ }
+ } else if (key.equals(CameraSettings.KEY_DUAL_CAMERA)) {
+ boolean changeMode = CaptureModule.setMode(value);
+ if (changeMode) mActivity.onModuleSelected(ModuleSwitcher.CAPTURE_MODULE_INDEX);
+ } else if (key.equals(CameraSettings.KEY_MONO_PREVIEW)) {
+ if (value.equals("on")) {
+ } else if (value.equals("off")) {
+ }
}
}
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 604a705..52f9327 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -26,6 +26,7 @@
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.ImageFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
@@ -36,22 +37,30 @@
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.CameraProfile;
import android.media.Image;
import android.media.ImageReader;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.KeyEvent;
+import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
+import android.widget.Toast;
import com.android.camera.PhotoModule.NamedImages;
import com.android.camera.PhotoModule.NamedImages.NamedEntity;
+import com.android.camera.ui.RotateTextToast;
+import com.android.camera.util.CameraUtil;
import org.codeaurora.snapcam.R;
@@ -60,13 +69,20 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-public class CaptureModule implements CameraModule, PhotoController {
- private static final int NUMCAM = 1;
+public class CaptureModule implements CameraModule, PhotoController,
+ MediaSaveService.Listener {
+ public static final int DUAL_MODE = 0;
+ public static final int BAYER_MODE = 1;
+ public static final int MONO_MODE = 2;
+ private static final int OPEN_CAMERA = 0;
+ private static final int MAX_NUM_CAM = 3;
/**
* Conversion from screen rotation to JPEG orientation.
*/
@@ -91,7 +107,11 @@
* Camera state: Picture was taken.
*/
private static final int STATE_PICTURE_TAKEN = 4;
+ //Todo: Read ids from the device dynamically
+ private static final int BAYER_ID = 0;
+ private static final int MONO_ID = 1;
private static final String TAG = "SnapCam_CaptureModule";
+ private static int MODE = DUAL_MODE;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
@@ -100,44 +120,45 @@
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
+ MeteringRectangle[][] mAFRegions = new MeteringRectangle[MAX_NUM_CAM][];
+ CaptureRequest.Key<Byte> BayerMonoLinkEnableKey =
+ new CaptureRequest.Key<>("org.codeaurora.qcamera3.dualcam_link_meta_data.enable",
+ Byte.class);
+ CaptureRequest.Key<Byte> BayerMonoLinkMainKey =
+ new CaptureRequest.Key<>("org.codeaurora.qcamera3.dualcam_link_meta_data.is_main",
+ Byte.class);
+ CaptureRequest.Key<Integer> BayerMonoLinkSessionIdKey =
+ new CaptureRequest.Key<>("org.codeaurora.qcamera3.dualcam_link_meta_data" +
+ ".related_camera_id", Integer.class);
+ private int mLastResultAFState = -1;
+ private Rect[] mCropRegion = new Rect[MAX_NUM_CAM];
+ private boolean mAutoFocusSupported;
+ // The degrees of the device rotated clockwise from its natural orientation.
+ private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
+ private int mJpegQuality;
+ private Map<String, String> mSettings = new HashMap<String, String>();
+ private boolean mFirstTimeInitialized;
+ private boolean mInitialized = false;
+ private boolean mIsLinked = false;
private long mCaptureStartTime;
+ private boolean mPaused = true;
private boolean mSurfaceReady = false;
- private boolean mCameraOpened = false;
- private CameraDevice[] mCameraDevice = new CameraDevice[NUMCAM];
- private String[] mCameraId = new String[NUMCAM];
+ private boolean[] mCameraOpened = new boolean[MAX_NUM_CAM];
+ private CameraDevice[] mCameraDevice = new CameraDevice[MAX_NUM_CAM];
+ private String[] mCameraId = new String[MAX_NUM_CAM];
private CaptureUI mUI;
private CameraActivity mActivity;
private PreferenceGroup mPreferenceGroup;
private ComboPreferences mPreferences;
- private CaptureRequest.Builder[] mCaptureBuilder = new CaptureRequest.Builder[NUMCAM];
- private final CameraPreference.OnPreferenceChangedListener prefListener = new
- CameraPreference.OnPreferenceChangedListener() {
- @Override
- public void onSharedPreferenceChanged(ListPreference pref) {
- applyPreference(0, pref);
- mUI.overrideSettings(pref.getKey(), null);
- }
-
- @Override
- public void onSharedPreferenceChanged() {
- }
-
- @Override
- public void onRestorePreferencesClicked() {
- }
-
- @Override
- public void onOverriddenPreferencesClicked() {
- }
-
- @Override
- public void onCameraPickerClicked(int cameraId) {
- }
- };
+ private CameraCharacteristics[] mCharacteristics = new CameraCharacteristics[MAX_NUM_CAM];
+ private List<Integer> mCharacteristicsIndex;
+ private float mZoomValue = 1f;
+ private FocusStateListener mFocusStateListener;
+ private LocationManager mLocationManager;
/**
* A {@link CameraCaptureSession } for camera preview.
*/
- private CameraCaptureSession[] mCaptureSession = new CameraCaptureSession[NUMCAM];
+ private CameraCaptureSession[] mCaptureSession = new CameraCaptureSession[MAX_NUM_CAM];
/**
* An additional thread for running tasks that shouldn't block the UI.
*/
@@ -153,7 +174,7 @@
/**
* An {@link ImageReader} that handles still image capture.
*/
- private ImageReader[] mImageReader = new ImageReader[NUMCAM];
+ private ImageReader[] mImageReader = new ImageReader[MAX_NUM_CAM];
private NamedImages mNamedImages;
private ContentResolver mContentResolver;
private MediaSaveService.OnMediaSavedListener mOnMediaSavedListener =
@@ -174,6 +195,7 @@
@Override
public void onImageAvailable(ImageReader reader) {
+ Log.d(TAG, "image available");
mCaptureStartTime = System.currentTimeMillis();
mNamedImages.nameNewImage(mCaptureStartTime);
NamedEntity name = mNamedImages.getNextNameEntity();
@@ -182,30 +204,27 @@
Image mImage = reader.acquireNextImage();
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
+ //Todo: dont create new buffer and use the one from ImageReader
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
mActivity.getMediaSaveService().addImage(
bytes, title, date, null, reader.getWidth(), reader.getHeight(),
0, null, mOnMediaSavedListener, mContentResolver, "jpeg");
+ mImage.close();
}
};
-
/**
* {@link CaptureRequest.Builder} for the camera preview
*/
- private CaptureRequest.Builder[] mPreviewRequestBuilder = new CaptureRequest.Builder[NUMCAM];
- /**
- * {@link CaptureRequest} generated by {@link #mPreviewRequestBuilder}
- */
- private CaptureRequest[] mPreviewRequest = new CaptureRequest[NUMCAM];
+ private CaptureRequest.Builder[] mPreviewRequestBuilder = new CaptureRequest.Builder[MAX_NUM_CAM];
/**
* The current state of camera state for taking pictures.
*
* @see #mCaptureCallback
*/
- private int mState = STATE_PREVIEW;
+ private int[] mState = new int[MAX_NUM_CAM];
/**
* A {@link Semaphore} make sure the camera open callback happens first before closing the
* camera.
@@ -218,23 +237,28 @@
= new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult result) {
- switch (mState) {
+ int id = (int) result.getRequest().getTag();
+
+ switch (mState[id]) {
case STATE_PREVIEW: {
- // We have nothing to do when the camera preview is working normally.
break;
}
case STATE_WAITING_LOCK: {
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
+ Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+ Log.d(TAG, "STATE_WAITING_LOCK afState:" + afState + " aeState:" + aeState);
+ // AF_PASSIVE is added for continous auto focus mode
if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
- CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
+ CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState ||
+ CaptureRequest.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState ||
+ CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED == afState) {
// CONTROL_AE_STATE can be null on some devices
- Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
- if (aeState == null ||
- aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
- mState = STATE_PICTURE_TAKEN;
- captureStillPicture(0);
+ if (aeState == null || (aeState == CaptureResult
+ .CONTROL_AE_STATE_CONVERGED) && isFlashOff()) {
+ mState[id] = STATE_PICTURE_TAKEN;
+ captureStillPicture(id);
} else {
- runPrecaptureSequence(0);
+ runPrecaptureSequence(id);
}
}
break;
@@ -245,7 +269,7 @@
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
- mState = STATE_WAITING_NON_PRECAPTURE;
+ mState[id] = STATE_WAITING_NON_PRECAPTURE;
}
break;
}
@@ -253,8 +277,8 @@
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
- mState = STATE_PICTURE_TAKEN;
- captureStillPicture(0);
+ mState[id] = STATE_PICTURE_TAKEN;
+ captureStillPicture(id);
}
break;
}
@@ -265,6 +289,8 @@
public void onCaptureProgressed(CameraCaptureSession session,
CaptureRequest request,
CaptureResult partialResult) {
+ int id = (int) partialResult.getRequest().getTag();
+ if (id == getMainCameraId()) updateFocusStateChange(partialResult);
process(partialResult);
}
@@ -272,63 +298,208 @@
public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request,
TotalCaptureResult result) {
+ int id = (int) result.getRequest().getTag();
+ if (id == getMainCameraId()) updateFocusStateChange(result);
process(result);
}
-
};
+ private final CameraPreference.OnPreferenceChangedListener prefListener = new
+ CameraPreference.OnPreferenceChangedListener() {
+ @Override
+ public void onSharedPreferenceChanged(ListPreference pref) {
+ if (mPaused) return;
+ if (CameraSettings.KEY_CAMERA_SAVEPATH.equals(pref.getKey())) {
+ Storage.setSaveSDCard(
+ mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0")
+ .equals("1"));
+ mActivity.updateStorageSpaceAndHint();
+ }
+
+ switch (MODE) {
+ case BAYER_MODE:
+ applyPreference(0, pref);
+ break;
+ case MONO_MODE:
+ applyPreference(1, pref);
+ break;
+ case DUAL_MODE:
+ applyPreference(0, pref);
+ applyPreference(1, pref);
+ }
+ mUI.overrideSettings(pref.getKey(), null);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged() {
+ if (mPaused) return;
+ boolean recordLocation = RecordLocationPreference.get(
+ mPreferences, mContentResolver);
+ mLocationManager.recordLocation(recordLocation);
+ }
+
+ @Override
+ public void onRestorePreferencesClicked() {
+ }
+
+ @Override
+ public void onOverriddenPreferencesClicked() {
+ }
+
+ @Override
+ public void onCameraPickerClicked(int cameraId) {
+ }
+ };
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
int id = Integer.parseInt(cameraDevice.getId());
-
+ Log.d(TAG, "onOpened " + id);
mCameraOpenCloseLock.release();
-
- PreferenceInflater inflater = new PreferenceInflater(mActivity);
- PreferenceGroup group =
- (PreferenceGroup) inflater.inflate(R.xml.camera_preferences);
- mPreferenceGroup = group;
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mUI.onCameraOpened(mPreferenceGroup, prefListener);
- }
-
-
- });
+ if (mPaused) {
+ return;
+ }
+ if (MODE == DUAL_MODE && id == BAYER_ID) {
+ Message msg = Message.obtain();
+ msg.what = OPEN_CAMERA;
+ msg.arg1 = MONO_ID;
+ mCameraHandler.sendMessage(msg);
+ }
+ if (!mInitialized) {
+ mInitialized = true;
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mUI.onCameraOpened(mCharacteristics, mCharacteristicsIndex,
+ mPreferenceGroup, prefListener);
+ }
+ });
+ }
mCameraDevice[id] = cameraDevice;
- mCameraOpened = true;
+ mCameraOpened[id] = true;
createSession(id);
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
- mCameraOpenCloseLock.release();
+ int id = Integer.parseInt(cameraDevice.getId());
+ Log.d(TAG, "onDisconnected " + id);
cameraDevice.close();
mCameraDevice = null;
+ mCameraOpenCloseLock.release();
}
@Override
public void onError(CameraDevice cameraDevice, int error) {
int id = Integer.parseInt(cameraDevice.getId());
- mCameraOpenCloseLock.release();
+ Log.d(TAG, "onError " + id + error);
cameraDevice.close();
- mCameraDevice = null;
+ mCameraDevice[id] = null;
+ mCameraOpenCloseLock.release();
if (null != mActivity) {
mActivity.finish();
}
}
+ @Override
+ public void onClosed(CameraDevice cameraDevice) {
+ int id = Integer.parseInt(cameraDevice.getId());
+ Log.d(TAG, "onClosed " + id);
+ mCameraDevice[id] = null;
+ mCameraOpenCloseLock.release();
+ }
+
};
+ public static boolean setMode(String value) {
+ int mode = DUAL_MODE;
+ switch (value) {
+ case "dual":
+ mode = DUAL_MODE;
+ break;
+ case "bayer":
+ mode = BAYER_MODE;
+ break;
+ case "mono":
+ mode = MONO_MODE;
+ break;
+ }
+ if (MODE == mode) return false;
+ MODE = mode;
+ return true;
+ }
+
+ public static int getQualityNumber(String jpegQuality) {
+ try {
+ int qualityPercentile = Integer.parseInt(jpegQuality);
+ if (qualityPercentile >= 0 && qualityPercentile <= 100)
+ return qualityPercentile;
+ else
+ return 85;
+ } catch (NumberFormatException nfe) {
+ //chosen quality is not a number, continue
+ }
+ int value = 0;
+ switch (jpegQuality) {
+ case "superfine":
+ value = CameraProfile.QUALITY_HIGH;
+ break;
+ case "fine":
+ value = CameraProfile.QUALITY_MEDIUM;
+ break;
+ case "normal":
+ value = CameraProfile.QUALITY_LOW;
+ break;
+ default:
+ return 85;
+ }
+ return CameraProfile.getJpegEncodingQualityParameter(value);
+ }
+
+ private void initializeFirstTime() {
+ if (mFirstTimeInitialized || mPaused) {
+ return;
+ }
+
+ //Todo: test record location. Jack to provide instructions
+ // Initialize location service.
+ boolean recordLocation = RecordLocationPreference.get(
+ mPreferences, mContentResolver);
+ mLocationManager.recordLocation(recordLocation);
+
+ mUI.initializeFirstTime();
+ MediaSaveService s = mActivity.getMediaSaveService();
+ // We set the listener only when both service and shutterbutton
+ // are initialized.
+ if (s != null) {
+ s.setListener(this);
+ }
+
+ mNamedImages = new NamedImages();
+ mFirstTimeInitialized = true;
+ }
+
+ private void initializeSecondTime() {
+ // Start location update if needed.
+ boolean recordLocation = RecordLocationPreference.get(
+ mPreferences, mContentResolver);
+ mLocationManager.recordLocation(recordLocation);
+ MediaSaveService s = mActivity.getMediaSaveService();
+ if (s != null) {
+ s.setListener(this);
+ }
+ mNamedImages = new NamedImages();
+ mUI.initializeSecondTime();
+ }
+
private void createSession(final int id) {
- if (!mCameraOpened || !mSurfaceReady) return;
+ if (mPaused || !mCameraOpened[id] || !mSurfaceReady) return;
List<Surface> list = new LinkedList<Surface>();
mUI.hidePreviewCover();
try {
Surface surface;
- if (id == 0) {
+ if (id == BAYER_ID || (id == MONO_ID && MODE == MONO_MODE)) {
SurfaceHolder sh = mUI.getSurfaceHolder();
if (sh == null) {
return;
@@ -344,19 +515,9 @@
// We set up a CaptureRequest.Builder with the output Surface.
mPreviewRequestBuilder[id] = mCameraDevice[id].createCaptureRequest(CameraDevice
.TEMPLATE_PREVIEW);
+ mPreviewRequestBuilder[id].setTag(id);
mPreviewRequestBuilder[id].addTarget(surface);
- // This is the CaptureRequest.Builder that we use to take a picture.
- mCaptureBuilder[id] =
- mCameraDevice[id].createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
- mCaptureBuilder[id].addTarget(mImageReader[id].getSurface());
-
- // Use the same AE and AF modes as the preview.
- mCaptureBuilder[id].set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
- mCaptureBuilder[id].set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
-
list.add(surface);
list.add(mImageReader[id].getSurface());
// Here, we create a CameraCaptureSession for camera preview.
@@ -366,24 +527,20 @@
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
// The camera is already closed
- if (null == mCameraDevice[id]) {
+ if (mPaused || null == mCameraDevice[id]) {
return;
}
// When the session is ready, we start displaying the preview.
mCaptureSession[id] = cameraCaptureSession;
+ initializePreviewConfiguration(id);
try {
- // Auto focus should be continuous for camera preview.
- mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
- // Flash is automatically enabled when necessary.
- mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
-
+ if (MODE == DUAL_MODE) {
+ linkBayerMono(id);
+ mIsLinked = true;
+ }
// Finally, we start displaying the camera preview.
- mPreviewRequest[id] = mPreviewRequestBuilder[id].build();
- mCaptureSession[id].setRepeatingRequest(mPreviewRequest[id],
- mCaptureCallback, mCameraHandler);
- applyAllSettings(0);
+ mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
+ .build(), mCaptureCallback, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
@@ -401,64 +558,149 @@
@Override
public void init(CameraActivity activity, View parent) {
- mCameraOpened = false;
+ Log.d(TAG, "init");
+ for (int i = 0; i < MAX_NUM_CAM; i++) {
+ mCameraOpened[i] = false;
+ }
mSurfaceReady = false;
+
mActivity = activity;
+ for (int i = 0; i < MAX_NUM_CAM; i++) {
+ mState[i] = STATE_PREVIEW;
+ }
mPreferences = new ComboPreferences(mActivity);
CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal(), activity);
- mPreferences.setLocalId(mActivity, 0);
+ mPreferences.setLocalId(mActivity, BAYER_ID);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
+ PreferenceInflater inflater = new PreferenceInflater(mActivity);
+ PreferenceGroup group =
+ (PreferenceGroup) inflater.inflate(R.xml.camera_preferences);
+ mPreferenceGroup = group;
+
+ ListPreference pref = group.findPreference(CameraSettings.KEY_DUAL_CAMERA);
+ setMode(pref.getValue());
+
mContentResolver = mActivity.getContentResolver();
mUI = new CaptureUI(activity, this, parent);
mUI.initializeControlByIntent();
- mNamedImages = new NamedImages();
+ mFocusStateListener = new FocusStateListener(mUI);
+ mLocationManager = new LocationManager(mActivity, mUI);
+ Storage.setSaveSDCard(
+ mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1"));
}
/**
* Initiate a still image capture.
*/
private void takePicture() {
- lockFocus(0);
+ Log.d(TAG, "takePicture");
+ switch (MODE) {
+ case DUAL_MODE:
+ lockFocus(BAYER_ID);
+ lockFocus(MONO_ID);
+ break;
+ case BAYER_MODE:
+ lockFocus(BAYER_ID);
+ break;
+ case MONO_MODE:
+ lockFocus(MONO_ID);
+ break;
+ }
}
/**
* Lock the focus as the first step for a still image capture.
*/
private void lockFocus(int id) {
+ Log.d(TAG, "lockFocus " + id);
try {
- // This is how to tell the camera to lock focus.
- mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AF_TRIGGER,
- CameraMetadata.CONTROL_AF_TRIGGER_START);
- // Tell #mCaptureCallback to wait for the lock.
- mState = STATE_WAITING_LOCK;
- mCaptureSession[id].capture(mPreviewRequestBuilder[id].build(), mCaptureCallback,
- mCameraHandler);
+ CaptureRequest.Builder builder = mCameraDevice[id].createCaptureRequest(CameraDevice
+ .TEMPLATE_PREVIEW);
+ builder.setTag(id);
+ builder.addTarget(getPreviewSurface(id));
+
+ builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+ builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO);
+ builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
+ applyWhiteBalance(builder);
+ applyZoom(builder, id);
+ mState[id] = STATE_WAITING_LOCK;
+ mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
+ private void autoFocusTrigger(int id) {
+ Log.d(TAG, "autoFocusTrigger " + id);
+ try {
+ CaptureRequest.Builder builder = mCameraDevice[id].createCaptureRequest(CameraDevice
+ .TEMPLATE_PREVIEW);
+ builder.setTag(id);
+ builder.addTarget(getPreviewSurface(id));
+
+ builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+ builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO);
+ builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
+ applyWhiteBalance(builder);
+ applyZoom(builder, id);
+ applyAFRegions(builder, id);
+ mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void linkBayerMono(int id) {
+ Log.d(TAG, "linkBayerMono " + id);
+ if (id == BAYER_ID) {
+ mPreviewRequestBuilder[id].set(BayerMonoLinkEnableKey, (byte) 1);
+ mPreviewRequestBuilder[id].set(BayerMonoLinkMainKey, (byte) 1);
+ mPreviewRequestBuilder[id].set(BayerMonoLinkSessionIdKey, MONO_ID);
+ } else if (id == MONO_ID) {
+ mPreviewRequestBuilder[id].set(BayerMonoLinkEnableKey, (byte) 1);
+ mPreviewRequestBuilder[id].set(BayerMonoLinkMainKey, (byte) 0);
+ mPreviewRequestBuilder[id].set(BayerMonoLinkSessionIdKey, BAYER_ID);
+ }
+ }
+
+ public void unLinkBayerMono(int id) {
+ Log.d(TAG, "unlinkBayerMono " + id);
+ if (id == BAYER_ID) {
+ mPreviewRequestBuilder[id].set(BayerMonoLinkEnableKey, (byte) 0);
+ } else if (id == MONO_ID) {
+ mPreviewRequestBuilder[id].set(BayerMonoLinkEnableKey, (byte) 0);
+ }
+ }
+
+
/**
* Capture a still picture. This method should be called when we get a response in
* {@link #mCaptureCallback} from both {@link #lockFocus()}.
*/
private void captureStillPicture(final int id) {
+ Log.d(TAG, "captureStillPicture " + id);
try {
- if (null == mActivity || null == mCameraDevice) {
+ if (null == mActivity || null == mCameraDevice[id]) {
return;
}
+ CaptureRequest.Builder captureBuilder =
+ mCameraDevice[id].createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+
+ captureBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+ captureBuilder.addTarget(getPreviewSurface(id));
+ captureBuilder.addTarget(mImageReader[id].getSurface());
+ captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
+ captureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest
+ .CONTROL_AF_TRIGGER_IDLE);
+ applyCaptureSettings(captureBuilder, id);
// Orientation
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- mCaptureBuilder[id].set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
- List<CaptureRequest> burstList = new ArrayList<CaptureRequest>();
-
- for (int i = 0; i < 1; i++) {
- burstList.add(mCaptureBuilder[id].build());
- }
+ captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
@@ -467,16 +709,18 @@
public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request,
TotalCaptureResult result) {
+ Log.d(TAG, "captureStillPicture onCaptureCompleted");
}
@Override
public void onCaptureSequenceCompleted(CameraCaptureSession session, int
sequenceId, long frameNumber) {
+ Log.d(TAG, "captureStillPicture onCaptureSequenceCompleted");
unlockFocus(id);
}
-
};
- mCaptureSession[id].captureBurst(burstList, CaptureCallback, mCallbackHandler);
+ mCaptureSession[id].stopRepeating();
+ mCaptureSession[id].capture(captureBuilder.build(), CaptureCallback, mCallbackHandler);
} catch (CameraAccessException e) {
Log.d(TAG, "Capture still picture has failed");
e.printStackTrace();
@@ -488,14 +732,21 @@
* we get a response in {@link #mCaptureCallback} from {@link #lockFocus()}.
*/
private void runPrecaptureSequence(int id) {
+ Log.d(TAG, "runPrecaptureSequence");
try {
- // This is how to tell the camera to trigger.
- mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+ CaptureRequest.Builder builder = mCameraDevice[id].createCaptureRequest(CameraDevice
+ .TEMPLATE_PREVIEW);
+ builder.setTag(id);
+ builder.addTarget(getPreviewSurface(id));
+ builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+ builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
- // Tell #mCaptureCallback to wait for the precapture sequence to be set.
- mState = STATE_WAITING_PRECAPTURE;
- mCaptureSession[id].capture(mPreviewRequestBuilder[id].build(), mCaptureCallback,
- mCameraHandler);
+ // Applying flash only to capture does not work. Need to apply flash here.
+ applyFlash(builder);
+ applyWhiteBalance(builder);
+ applyZoom(builder, id);
+ mState[id] = STATE_WAITING_PRECAPTURE;
+ mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
@@ -508,33 +759,36 @@
* @param height The height of available size for camera preview
*/
private void setUpCameraOutputs() {
- Activity activity = mActivity;
- CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+ CameraManager manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
try {
String[] cameraIdList = manager.getCameraIdList();
- for (int i = 0; i < NUMCAM; i++) {
+
+ for (int i = 0; i < cameraIdList.length; i++) {
String cameraId = cameraIdList[i];
CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
-
+ mCharacteristics[i] = characteristics;
+ mCharacteristicsIndex.add(i);
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
continue;
}
-
+ Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
+ Log.d(TAG, "flash : " + (available == null ? false : available));
// For still image captures, we use the largest available size.
Size largest = Collections.max(
Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
new CompareSizesByArea());
mImageReader[i] = ImageReader.newInstance(largest.getWidth(), largest.getHeight(),
- ImageFormat.JPEG, 10);
+ ImageFormat.JPEG, 3);
mImageReader[i].setOnImageAvailableListener(
mOnImageAvailableListener, mImageAvailableHandler);
mCameraId[i] = cameraId;
- //return;
}
+ mAutoFocusSupported = CameraUtil.isAutoFocusSupported(mCharacteristics,
+ mCharacteristicsIndex);
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (NullPointerException e) {
@@ -546,45 +800,73 @@
* finished.
*/
private void unlockFocus(int id) {
+ Log.d(TAG, "unlockFocus " + id);
try {
- // Reset the auto-focus trigger
- mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AF_TRIGGER,
- CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
- mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
- mCaptureSession[id].capture(mPreviewRequestBuilder[id].build(), mCaptureCallback,
- mCameraHandler);
- // After this, the camera will go back to the normal state of preview.
- mState = STATE_PREVIEW;
- mCaptureSession[id].setRepeatingRequest(mPreviewRequest[id], mCaptureCallback,
- mCameraHandler);
+ CaptureRequest.Builder builder = mCameraDevice[id].createCaptureRequest(CameraDevice
+ .TEMPLATE_PREVIEW);
+ builder.setTag(id);
+ builder.addTarget(getPreviewSurface(id));
+ builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest
+ .CONTROL_MODE_AUTO);
+ builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest
+ .CONTROL_AF_MODE_AUTO);
+ builder.set(CaptureRequest.CONTROL_AF_TRIGGER,
+ CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
+ //Todo: Create applyCommonSettings function for settings applied everytime
+ applyWhiteBalance(builder);
+ applyZoom(builder, id);
+ mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler);
+ mState[id] = STATE_PREVIEW;
+ mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(),
+ mCaptureCallback, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
+
/**
* Closes the current {@link CameraDevice}.
*/
private void closeCamera() {
+ Log.d(TAG, "closeCamera");
try {
mCameraOpenCloseLock.acquire();
- for (int i = 0; i < NUMCAM; i++) {
+ for (int i = 0; i < MAX_NUM_CAM; i++) {
if (null != mCaptureSession[i]) {
+ if (mIsLinked) {
+ unLinkBayerMono(i);
+ try {
+ mCaptureSession[i].capture(mPreviewRequestBuilder[i].build(), null,
+ mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
mCaptureSession[i].close();
mCaptureSession[i] = null;
}
- if (null != mCameraDevice[i]) {
- mCameraDevice[i].close();
- mCameraDevice[i] = null;
- mCameraOpened = false;
- }
if (null != mImageReader[i]) {
mImageReader[i].close();
mImageReader[i] = null;
}
}
+ for (int i = 0; i < MAX_NUM_CAM; i++) {
+ if (null != mCameraDevice[i]) {
+ mCameraDevice[i].close();
+ mCameraDevice[i] = null;
+ mCameraOpened[i] = false;
+ }
+ }
+ /* no need to set this in the callback and handle asynchronously. This is the same
+ reason as why we release the semaphore here, not in camera close callback function
+ as we don't have to protect the case where camera open() gets called during camera
+ close(). The low level framework/HAL handles the synchronization for open()
+ happens after close() */
+ mIsLinked = false;
} catch (InterruptedException e) {
+ mCameraOpenCloseLock.release();
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
} finally {
mCameraOpenCloseLock.release();
@@ -602,7 +884,7 @@
mCallbackThread = new HandlerThread("CameraCallback");
mCallbackThread.start();
- mCameraHandler = new Handler(mCameraThread.getLooper());
+ mCameraHandler = new MyCameraHandler(mCameraThread.getLooper());
mImageAvailableHandler = new Handler(mImageAvailableThread.getLooper());
mCallbackHandler = new Handler(mCallbackThread.getLooper());
}
@@ -638,12 +920,17 @@
}
private void openCamera(int id) {
+ if (mPaused) {
+ return;
+ }
+ Log.d(TAG, "openCamera " + id);
CameraManager manager;
try {
manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
mCameraId[id] = manager.getCameraIdList()[id];
- if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
+ if (!mCameraOpenCloseLock.tryAcquire(5000, TimeUnit.MILLISECONDS)) {
Log.d(TAG, "Time out waiting to lock camera opening.");
+ throw new RuntimeException("Time out waiting to lock camera opening");
}
manager.openCamera(mCameraId[id], mStateCallback, mCameraHandler);
} catch (CameraAccessException e) {
@@ -655,17 +942,19 @@
@Override
public void onPreviewFocusChanged(boolean previewFocused) {
-
+ mUI.onPreviewFocusChanged(previewFocused);
}
@Override
public void onPauseBeforeSuper() {
-
+ mPaused = true;
}
@Override
public void onPauseAfterSuper() {
+ Log.d(TAG, "onPause");
mUI.showPreviewCover();
+ if (mLocationManager != null) mLocationManager.recordLocation(false);
stopBackgroundThread();
closeCamera();
mUI.onPause();
@@ -673,17 +962,37 @@
@Override
public void onResumeBeforeSuper() {
-
+ mPaused = false;
}
@Override
public void onResumeAfterSuper() {
+ Log.d(TAG, "onResume " + MODE);
+ mCharacteristicsIndex = new ArrayList<>();
setUpCameraOutputs();
- openCamera(0);
+ readInitialValues();
startBackgroundThread();
+ Message msg = Message.obtain();
+ msg.what = OPEN_CAMERA;
+ switch (MODE) {
+ case DUAL_MODE:
+ case BAYER_MODE:
+ msg.arg1 = BAYER_ID;
+ mCameraHandler.sendMessage(msg);
+ break;
+ case MONO_MODE:
+ msg.what = OPEN_CAMERA;
+ msg.arg1 = MONO_ID;
+ mCameraHandler.sendMessage(msg);
+ break;
+ }
+ if (!mFirstTimeInitialized) {
+ initializeFirstTime();
+ } else {
+ initializeSecondTime();
+ }
mUI.hidePreviewCover();
mUI.enableShutter(true);
- mUI.initializeFirstTime();
}
@Override
@@ -708,7 +1017,7 @@
@Override
public boolean onBackPressed() {
- return false;
+ return mUI.onBackPressed();
}
@Override
@@ -727,13 +1036,31 @@
}
@Override
+ public void onZoomChanged(float requestedZoom) {
+ mZoomValue = requestedZoom;
+
+ switch (MODE) {
+ case DUAL_MODE:
+ applyZoomAndUpdate(BAYER_ID);
+ applyZoomAndUpdate(MONO_ID);
+ break;
+ case BAYER_MODE:
+ applyZoomAndUpdate(BAYER_ID);
+ break;
+ case MONO_MODE:
+ applyZoomAndUpdate(MONO_ID);
+ break;
+ }
+ }
+
+ @Override
public boolean isImageCaptureIntent() {
return false;
}
@Override
public boolean isCameraIdle() {
- return false;
+ return true;
}
@Override
@@ -768,7 +1095,42 @@
@Override
public void onSingleTapUp(View view, int x, int y) {
+ if (mPaused || mCameraDevice == null || !mFirstTimeInitialized || !mAutoFocusSupported ||
+ !isStatePreview()) {
+ return;
+ }
+ mUI.setFocusPosition(x, y);
+ mUI.onFocusStarted();
+ switch (MODE) {
+ case DUAL_MODE:
+ triggerFocusAtPoint(x, y, BAYER_ID);
+ triggerFocusAtPoint(x, y, MONO_ID);
+ break;
+ case BAYER_MODE:
+ triggerFocusAtPoint(x, y, BAYER_ID);
+ break;
+ case MONO_MODE:
+ triggerFocusAtPoint(x, y, MONO_ID);
+ break;
+ }
+ }
+ private int getMainCameraId() {
+ switch (MODE) {
+ case DUAL_MODE:
+ case BAYER_MODE:
+ return BAYER_ID;
+ case MONO_MODE:
+ return MONO_ID;
+ }
+ return 0;
+ }
+
+ private boolean isStatePreview() {
+ for (int i = 0; i < mState.length; i++) {
+ if (mState[i] != STATE_PREVIEW) return false;
+ }
+ return true;
}
@Override
@@ -793,13 +1155,37 @@
@Override
public void enableRecordingLocation(boolean enable) {
+ Log.d(TAG, "CaptureModule enableRecordingLocation " + enable);
+ setLocationPreference(enable ? RecordLocationPreference.VALUE_ON
+ : RecordLocationPreference.VALUE_OFF);
+ }
+ private void setLocationPreference(String value) {
+ mPreferences.edit()
+ .putString(CameraSettings.KEY_RECORD_LOCATION, value)
+ .apply();
+ prefListener.onSharedPreferenceChanged();
}
@Override
public void onPreviewUIReady() {
+ if (mPaused) {
+ return;
+ }
+ Log.d(TAG, "onPreviewUIReady");
mSurfaceReady = true;
- createSession(0);
+ switch (MODE) {
+ case DUAL_MODE:
+ createSession(BAYER_ID);
+ createSession(MONO_ID);
+ break;
+ case BAYER_MODE:
+ createSession(BAYER_ID);
+ break;
+ case MONO_MODE:
+ createSession(MONO_ID);
+ break;
+ }
}
@Override
@@ -829,7 +1215,15 @@
@Override
public void onOrientationChanged(int orientation) {
-
+ // We keep the last known orientation. So if the user first orient
+ // the camera then point the camera to floor or sky, we still have
+ // the correct orientation.
+ if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return;
+ int oldOrientation = mOrientation;
+ mOrientation = CameraUtil.roundOrientation(orientation, mOrientation);
+ if (oldOrientation != mOrientation) {
+ mUI.setOrientation(mOrientation, true);
+ }
}
@Override
@@ -839,7 +1233,9 @@
@Override
public void onMediaSaveServiceConnected(MediaSaveService s) {
-
+ if (mFirstTimeInitialized) {
+ s.setListener(this);
+ }
}
@Override
@@ -854,7 +1250,15 @@
@Override
public void onSwitchSavePath() {
-
+ if (mUI.mMenuInitialized) {
+ mUI.setPreference(CameraSettings.KEY_CAMERA_SAVEPATH, "1");
+ } else {
+ mPreferences.edit()
+ .putString(CameraSettings.KEY_CAMERA_SAVEPATH, "1")
+ .apply();
+ }
+ RotateTextToast.makeText(mActivity, R.string.on_switch_save_path_to_sdcard,
+ Toast.LENGTH_SHORT).show();
}
@Override
@@ -872,23 +1276,225 @@
}
- private void applyPreference(int cameraId, ListPreference pref) {
- if (pref.getKey().equals(CameraSettings.KEY_FLASH_MODE)) {
- if (pref.getValue().equals("on")) {
- mCaptureBuilder[cameraId].set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
- } else if (pref.getValue().equals("auto")) {
- mCaptureBuilder[cameraId].set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
- } else if (pref.getValue().equals("off")) {
- mCaptureBuilder[cameraId].set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON);
+ private boolean isFlashOff() {
+ return readSetting(CameraSettings.KEY_FLASH_MODE).equals("off");
+ }
+
+ private void initializePreviewConfiguration(int id) {
+ mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_MODE, CaptureRequest
+ .CONTROL_MODE_AUTO);
+ mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest
+ .CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+ mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest
+ .CONTROL_AF_TRIGGER_IDLE);
+ mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest
+ .CONTROL_AE_MODE_ON);
+ mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest
+ .FLASH_MODE_OFF);
+ applyWhiteBalance(mPreviewRequestBuilder[id]);
+ applyZoom(mPreviewRequestBuilder[id], id);
+ }
+
+ private void readInitialValues() {
+ for (int i = 0; i < mPreferenceGroup.size(); i++) {
+ CameraPreference pref = mPreferenceGroup.get(i);
+ if (pref instanceof ListPreference) {
+ ListPreference listPref = (ListPreference) pref;
+ storeSetting(listPref.getKey(), listPref.getValue());
}
}
}
- private void applyAllSettings(int cameraId) {
+ public Rect cropRegionForZoom(int id) {
+ Log.d(TAG, "cropRegionForZoom " + id);
+ Rect activeRegion = mCharacteristics[id].get(CameraCharacteristics
+ .SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ Rect cropRegion = new Rect();
+ int xCenter = activeRegion.width() / 2;
+ int yCenter = activeRegion.height() / 2;
+ int xDelta = (int) (activeRegion.width() / (2 * mZoomValue));
+ int yDelta = (int) (activeRegion.height() / (2 * mZoomValue));
+ cropRegion.set(xCenter - xDelta, yCenter - yDelta, xCenter + xDelta, yCenter + yDelta);
+ mCropRegion[id] = cropRegion;
+ return mCropRegion[id];
+ }
+
+ private void applyZoom(CaptureRequest.Builder request, int id) {
+ request.set(CaptureRequest.SCALER_CROP_REGION, cropRegionForZoom(id));
+ }
+
+ private void applyCaptureSettings(CaptureRequest.Builder request, int id) {
+ applyFlash(request);
+ applyWhiteBalance(request);
+ applyJpegQuality(request);
+ applyZoom(request, id);
+ }
+
+ private void applyPreference(int cameraId, ListPreference pref) {
+ boolean updatePreview = false;
+ String key = pref.getKey();
+ String value = pref.getValue();
+ storeSetting(key, value);
+ switch (key) {
+ //Todo: CreateUISettings file and add UI preference settings to there
+ case CameraSettings.KEY_JPEG_QUALITY:
+ mJpegQuality = getQualityNumber(value);
+ break;
+ case CameraSettings.KEY_WHITE_BALANCE:
+ updatePreview = true;
+ applyWhiteBalance(mPreviewRequestBuilder[cameraId]);
+ break;
+ }
+ if (updatePreview) {
+ try {
+ mCaptureSession[cameraId].setRepeatingRequest(mPreviewRequestBuilder[cameraId]
+ .build(), mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void applyZoomAndUpdate(int id) {
+ applyZoom(mPreviewRequestBuilder[id], id);
+ try {
+ mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
+ .build(), mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void storeSetting(String key, String value) {
+ mSettings.put(key, value);
+ }
+
+ private String readSetting(String key) {
+ return mSettings.get(key);
+ }
+
+ private void applyJpegQuality(CaptureRequest.Builder request) {
+ request.set(CaptureRequest.JPEG_QUALITY, (byte) mJpegQuality);
+ }
+
+ private void applyAFRegions(CaptureRequest.Builder request, int id) {
+ request.set(CaptureRequest.CONTROL_AF_REGIONS, mAFRegions[id]);
+ }
+
+ private void applyWhiteBalance(CaptureRequest.Builder request) {
+ String value = readSetting(CameraSettings.KEY_WHITE_BALANCE);
+ switch (value) {
+ case "incandescent":
+ request.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest
+ .CONTROL_AWB_MODE_INCANDESCENT);
+ break;
+ case "fluorescent":
+ request.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest
+ .CONTROL_AWB_MODE_FLUORESCENT);
+ break;
+ case "auto":
+ request.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest
+ .CONTROL_AWB_MODE_AUTO);
+ break;
+ case "daylight":
+ request.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest
+ .CONTROL_AWB_MODE_DAYLIGHT);
+ break;
+ case "cloudy-daylight":
+ request.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest
+ .CONTROL_AWB_MODE_CLOUDY_DAYLIGHT);
+ break;
+ }
+ }
+
+ private Surface getPreviewSurface(int id) {
+ if (MODE == DUAL_MODE && id == MONO_ID) {
+ return mUI.getSurfaceHolder2().getSurface();
+ } else {
+ return mUI.getSurfaceHolder().getSurface();
+ }
+ }
+
+ private void applyFlash(CaptureRequest.Builder request, String value) {
+ switch (value) {
+ case "on":
+ request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest
+ .CONTROL_AE_MODE_ON_ALWAYS_FLASH);
+ request.set(CaptureRequest.FLASH_MODE, CaptureRequest
+ .FLASH_MODE_SINGLE);
+ break;
+ case "auto":
+ request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest
+ .CONTROL_AE_MODE_ON_AUTO_FLASH);
+ break;
+ case "off":
+ request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest
+ .CONTROL_AE_MODE_ON);
+ request.set(CaptureRequest.FLASH_MODE, CaptureRequest
+ .FLASH_MODE_OFF);
+ break;
+ }
+ }
+
+ private void applyFlash(CaptureRequest.Builder request) {
+ String value = readSetting(CameraSettings.KEY_FLASH_MODE);
+ applyFlash(request, value);
+ }
+
+ @Override
+ public void onQueueStatus(boolean full) {
+ mUI.enableShutter(!full);
+ }
+
+ public void triggerFocusAtPoint(float x, float y, int id) {
+ Point p;
+ if (id == getMainCameraId()) {
+ p = mUI.getSurfaceViewSize();
+ } else {
+ p = mUI.getSurfaceView2Size();
+ }
+ int width = p.x;
+ int height = p.y;
+ x = x / width;
+ y = y / height;
+ mAFRegions[id] = afRectangle(x, y, mCropRegion[id]);
+ autoFocusTrigger(id);
+ }
+
+ private MeteringRectangle[] afRectangle(float x, float y, Rect cropRegion) {
+ int side = Math.max(cropRegion.width(), cropRegion.height()) / 8;
+ int xCenter = (int) (cropRegion.left + x * cropRegion.width());
+ int yCenter = (int) (cropRegion.top + y * cropRegion.height());
+ Rect meteringRegion = new Rect(xCenter - side / 2, yCenter - side / 2, xCenter +
+ side / 2, yCenter + side / 2);
+
+ meteringRegion.left = CameraUtil.clamp(meteringRegion.left, cropRegion.left, cropRegion
+ .right);
+ meteringRegion.top = CameraUtil.clamp(meteringRegion.top, cropRegion.top, cropRegion
+ .bottom);
+ meteringRegion.right = CameraUtil.clamp(meteringRegion.right, cropRegion.left, cropRegion
+ .right);
+ meteringRegion.bottom = CameraUtil.clamp(meteringRegion.bottom, cropRegion.top,
+ cropRegion.bottom);
+ MeteringRectangle[] meteringRectangle = new MeteringRectangle[1];
+ meteringRectangle[0] = new MeteringRectangle(meteringRegion, 1);
+ return meteringRectangle;
+ }
+
+ private void updateFocusStateChange(CaptureResult result) {
+ final int resultAFState = result.get(CaptureResult.CONTROL_AF_STATE);
+
+ // Report state change when AF state has changed.
+ if (resultAFState != mLastResultAFState && mFocusStateListener != null) {
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mFocusStateListener.onFocusStatusUpdate(resultAFState);
+ }
+ });
+ }
+ mLastResultAFState = resultAFState;
}
/**
@@ -904,4 +1510,23 @@
}
}
+
+ private class MyCameraHandler extends Handler {
+
+ public MyCameraHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case OPEN_CAMERA: {
+ int id = msg.arg1;
+ openCamera(id);
+ break;
+ }
+ }
+ }
+ }
+
}
diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java
index 9095cd1..a6accae 100644
--- a/src/com/android/camera/CaptureUI.java
+++ b/src/com/android/camera/CaptureUI.java
@@ -24,8 +24,8 @@
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
-import android.hardware.Camera;
import android.hardware.Camera.Face;
+import android.hardware.camera2.CameraCharacteristics;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -70,7 +70,7 @@
CameraManager.CameraFaceDetectionCallback {
private static final String TAG = "SnapCam_CaptureUI";
- private boolean mMenuInitialized = false;
+ public boolean mMenuInitialized = false;
private boolean surface1created = false;
private boolean surface2created = false;
private CameraActivity mActivity;
@@ -111,8 +111,6 @@
private OnScreenIndicators mOnScreenIndicators;
private PieRenderer mPieRenderer;
private ZoomRenderer mZoomRenderer;
- private int mZoomMax;
- private List<Integer> mZoomRatios;
private int mPreviewWidth = 0;
private int mPreviewHeight = 0;
private int mOriginalPreviewWidth = 0;
@@ -189,16 +187,12 @@
mPreviewCover = mRootView.findViewById(R.id.preview_cover);
// display the view
mSurfaceView = (SurfaceView) mRootView.findViewById(R.id.mdp_preview_content);
- mSurfaceView.setVisibility(View.VISIBLE);
mSurfaceView2 = (SurfaceView) mRootView.findViewById(R.id.mdp_preview_content2);
- //mSurfaceView2.setVisibility(View.VISIBLE);
+ mSurfaceView2.setZOrderMediaOverlay(true);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
- //mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder2 = mSurfaceView2.getHolder();
mSurfaceHolder2.addCallback(callback);
- //mSurfaceHolder2.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- mSurfaceView.addOnLayoutChangeListener(mLayoutListener);
Log.v(TAG, "Using mdp_preview_content (MDP path)");
mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay);
@@ -284,7 +278,15 @@
mRootView.findViewById(R.id.on_screen_indicators));
}
- public void onCameraOpened(PreferenceGroup prefGroup, OnPreferenceChangedListener listener) {
+ public void onCameraOpened(CameraCharacteristics[] characteristics,
+ List<Integer> characteristicsIndex, PreferenceGroup prefGroup,
+ OnPreferenceChangedListener listener) {
+ if (mPieRenderer == null) {
+ mPieRenderer = new PieRenderer(mActivity);
+ mPieRenderer.setPieListener(this);
+ mRenderOverlay.addRenderer(mPieRenderer);
+ }
+
if (mMenu == null) {
mMenu = new CaptureMenu(mActivity, this);
mMenu.setListener(listener);
@@ -304,8 +306,11 @@
}
mGestures.setCaptureMenu(mMenu);
+ mGestures.setZoomEnabled(CameraUtil.isZoomSupported(characteristics, characteristicsIndex));
mGestures.setRenderOverlay(mRenderOverlay);
mRenderOverlay.requestLayout();
+
+ initializeZoom(characteristics, characteristicsIndex);
mActivity.setPreviewGestures(mGestures);
}
@@ -355,31 +360,32 @@
mShutterButton.setVisibility(View.VISIBLE);
}
+ // called from onResume every other time
+ public void initializeSecondTime() {
+ if (mMenu != null) {
+ mMenu.reloadPreferences();
+ }
+ }
+
public void doShutterAnimation() {
AnimationDrawable frameAnimation = (AnimationDrawable) mShutterButton.getDrawable();
frameAnimation.stop();
frameAnimation.start();
}
- // called from onResume every other time
- public void initializeSecondTime(Camera.Parameters params) {
- initializeZoom(params);
- if (mMenu != null) {
- mMenu.reloadPreferences();
- }
- }
-
- public void initializeZoom(Camera.Parameters params) {
- if ((params == null) || !params.isZoomSupported()
- || (mZoomRenderer == null)) return;
- mZoomMax = params.getMaxZoom();
- mZoomRatios = params.getZoomRatios();
- // Currently we use immediate zoom for fast zooming to get better UX and
- // there is no plan to take advantage of the smooth zoom.
+ public void initializeZoom(CameraCharacteristics[] characteristics,
+ List<Integer> characteristicsIndex) {
+ if ((characteristics == null) || !CameraUtil.isZoomSupported(characteristics,
+ characteristicsIndex) || (mZoomRenderer == null))
+ return;
if (mZoomRenderer != null) {
- mZoomRenderer.setZoomMax(mZoomMax);
- mZoomRenderer.setZoom(params.getZoom());
- mZoomRenderer.setZoomValue(mZoomRatios.get(params.getZoom()));
+ float zoomMax = Float.MAX_VALUE;
+ for (int i = 0; i < characteristicsIndex.size(); i++) {
+ zoomMax = Math.min(characteristics[characteristicsIndex.get(i)].get
+ (CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM), zoomMax);
+ }
+ mZoomRenderer.setZoomMax(zoomMax);
+ mZoomRenderer.setZoom(1f);
mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener());
}
}
@@ -671,6 +677,14 @@
}
}
+ public void hideSurfaceView() {
+ mSurfaceView.setVisibility(View.INVISIBLE);
+ }
+
+ public void showSurfaceView() {
+ mSurfaceView.setVisibility(View.VISIBLE);
+ }
+
public void onPause() {
// Clear UI.
collapseCameraControls();
@@ -678,7 +692,7 @@
// focus UI implementation
private FocusIndicator getFocusIndicator() {
- return null;
+ return mPieRenderer;
}
@Override
@@ -689,6 +703,10 @@
public void clearFaces() {
}
+ public void setPreference(String key, String value) {
+ mMenu.setPreference(key, value);
+ }
+
@Override
public void clearFocus() {
FocusIndicator indicator = getFocusIndicator();
@@ -768,16 +786,28 @@
}
}
+ public Point getSurfaceViewSize() {
+ Point point = new Point();
+ if (mSurfaceView != null) point.set(mSurfaceView.getWidth(), mSurfaceView.getHeight());
+ return point;
+ }
+
+ public Point getSurfaceView2Size() {
+ Point point = new Point();
+ if (mSurfaceView2 != null) point.set(mSurfaceView2.getWidth(), mSurfaceView2.getHeight());
+ return point;
+ }
+
public int getOrientation() {
return mOrientation;
}
private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener {
@Override
- public void onZoomValueChanged(int index) {
- int newZoom = mController.onZoomChanged(index);
+ public void onZoomValueChanged(float mZoomValue) {
+ mController.onZoomChanged(mZoomValue);
if (mZoomRenderer != null) {
- mZoomRenderer.setZoomValue(mZoomRatios.get(newZoom));
+ mZoomRenderer.setZoom(mZoomValue);
}
}
@@ -795,6 +825,11 @@
mPieRenderer.setBlockFocus(false);
}
}
+
+ @Override
+ public void onZoomValueChanged(int index) {
+
+ }
}
}
diff --git a/src/com/android/camera/FocusStateListener.java b/src/com/android/camera/FocusStateListener.java
new file mode 100644
index 0000000..42edd5c
--- /dev/null
+++ b/src/com/android/camera/FocusStateListener.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.camera;
+
+import android.hardware.camera2.CaptureResult;
+
+public class FocusStateListener {
+ private CaptureUI mUI;
+
+ public FocusStateListener(CaptureUI ui) {
+ mUI = ui;
+ }
+
+ public void onFocusStatusUpdate(int focusState) {
+ switch (focusState) {
+ case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN:
+ mUI.onFocusStarted();
+ break;
+ case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
+ mUI.onFocusSucceeded(true);
+ break;
+ case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+ mUI.onFocusFailed(true);
+ break;
+ case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
+ mUI.onFocusSucceeded(true);
+ break;
+ case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
+ mUI.onFocusStarted();
+ break;
+ case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
+ mUI.onFocusFailed(true);
+ break;
+ case CaptureResult.CONTROL_AF_STATE_INACTIVE:
+ mUI.clearFocus();
+ break;
+ }
+ }
+}
diff --git a/src/com/android/camera/PhotoController.java b/src/com/android/camera/PhotoController.java
index b08f8c0..887f0d3 100644
--- a/src/com/android/camera/PhotoController.java
+++ b/src/com/android/camera/PhotoController.java
@@ -37,6 +37,8 @@
// returns the actual set zoom value
public int onZoomChanged(int requestedZoom);
+ public void onZoomChanged(float requestedZoom);
+
public boolean isImageCaptureIntent();
public boolean isCameraIdle();
diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java
index b3c6117..b9ecdcc 100644
--- a/src/com/android/camera/PhotoMenu.java
+++ b/src/com/android/camera/PhotoMenu.java
@@ -16,6 +16,7 @@
package com.android.camera;
+import java.util.HashSet;
import java.util.Locale;
import android.animation.Animator;
@@ -117,6 +118,7 @@
private MakeupLevelListener mMakeupListener;
private MakeupHandler mHandler = new MakeupHandler();
private static final int MAKEUP_MESSAGE_ID = 0;
+ private HashSet<View> mWasVisibleSet = new HashSet<View>();
public PhotoMenu(CameraActivity activity, PhotoUI ui, MakeupLevelListener makeupListener) {
super(activity);
@@ -1509,7 +1511,17 @@
}
mSceneModeSwitcher.setVisibility(status);
mFilterModeSwitcher.setVisibility(status);
- mCameraSwitcher.setVisibility(status);
+ if(status == View.INVISIBLE) {
+ if(mCameraSwitcher.getVisibility() == View.VISIBLE) {
+ mWasVisibleSet.add(mCameraSwitcher);
+ }
+ mCameraSwitcher.setVisibility(status);
+ } else {
+ if(mWasVisibleSet.contains(mCameraSwitcher)) {
+ mCameraSwitcher.setVisibility(status);
+ mWasVisibleSet.remove(mCameraSwitcher);
+ }
+ }
mPreviewThumbnail.setVisibility(status);
}
}
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index d7353ba..4d2ec6a 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -696,6 +696,7 @@
private void switchCamera() {
if (mPaused) return;
+ mUI.applySurfaceChange(PhotoUI.SURFACE_STATUS.HIDE);
Log.v(TAG, "Start to switch camera. id=" + mPendingSwitchCameraId);
mCameraId = mPendingSwitchCameraId;
mPendingSwitchCameraId = -1;
@@ -735,6 +736,7 @@
mFocusManager.setParameters(mInitialParams);
setupPreview();
+ mUI.applySurfaceChange(PhotoUI.SURFACE_STATUS.SURFACE_VIEW);
// reset zoom value index
mZoomValue = 0;
resizeForPreviewAspectRatio();
@@ -2367,6 +2369,7 @@
@Override
public void onResumeAfterSuper() {
mLastPhotoTakenWithRefocus = false;
+ mUI.showSurfaceView();
// Add delay on resume from lock screen only, in order to to speed up
// the onResume --> onPause --> onResume cycle from lock screen.
// Don't do always because letting go of thread can cause delay.
@@ -2375,17 +2378,17 @@
|| MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action)) {
Log.v(TAG, "On resume, from lock screen.");
+ // Check if there is a need to take a snapshot without
+ // waiting for the shutter click
+ if (isInstantCaptureEnabled()) {
+ mInstantCaptureSnapShot = true;
+ }
+
// Note: onPauseAfterSuper() will delete this runnable, so we will
// at most have 1 copy queued up.
mHandler.postDelayed(new Runnable() {
public void run() {
onResumeTasks();
-
- // Check if there is a need to take a snapshot without
- // waiting for the shutter click
- if (isInstantCaptureEnabled()) {
- mInstantCaptureSnapShot = true;
- }
}
}, ON_RESUME_TASKS_DELAY_MSEC);
} else {
@@ -2428,6 +2431,8 @@
mOpenCameraThread.start();
}
+ mUI.applySurfaceChange(PhotoUI.SURFACE_STATUS.SURFACE_VIEW);
+
mJpegPictureCallbackTime = 0;
mZoomValue = 0;
@@ -2466,6 +2471,8 @@
@Override
public void onPauseBeforeSuper() {
mPaused = true;
+ mUI.applySurfaceChange(PhotoUI.SURFACE_STATUS.HIDE);
+
Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (gsensor != null) {
mSensorManager.unregisterListener(this, gsensor);
@@ -2494,6 +2501,7 @@
public void onPauseAfterSuper() {
Log.v(TAG, "On pause.");
mUI.showPreviewCover();
+ mUI.hideSurfaceView();
try {
if (mOpenCameraThread != null) {
@@ -2567,12 +2575,6 @@
// we will update focus manager with proper UI.
if (mFocusManager != null && mUI != null) {
mFocusManager.setPhotoUI(mUI);
-
- View root = mUI.getRootView();
- // These depend on camera parameters.
- int width = root.getWidth();
- int height = root.getHeight();
- mFocusManager.setPreviewSize(width, height);
}
}
@@ -4660,6 +4662,11 @@
}
@Override
+ public void onZoomChanged(float requestedZoom) {
+
+ }
+
+ @Override
public int getCameraState() {
return mCameraState;
}
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 7e3659f..d4503af 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -160,26 +160,15 @@
private int mOrientation;
private float mScreenBrightness = 0.0f;
+ public enum SURFACE_STATUS {
+ HIDE,
+ SURFACE_VIEW;
+ }
+
public interface SurfaceTextureSizeChangedListener {
public void onSurfaceTextureSizeChanged(int uncroppedWidth, int uncroppedHeight);
}
- private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right,
- int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
- tryToCloseSubList();
-
- Camera.Parameters parameters = ((PhotoModule)mController).getParameters();
- if(parameters != null) {
- Camera.Size size = parameters.getPreviewSize();
- if (size != null) {
- setAspectRatio((float) size.width / size.height);
- }
- }
- }
- };
-
public CameraControls getCameraControls() {
return mCameraControls;
}
@@ -233,6 +222,14 @@
}
}
+ public synchronized void applySurfaceChange(SURFACE_STATUS status) {
+ if(status == SURFACE_STATUS.HIDE) {
+ mSurfaceView.setVisibility(View.GONE);
+ return;
+ }
+ mSurfaceView.setVisibility(View.VISIBLE);
+ }
+
public PhotoUI(CameraActivity activity, PhotoController controller, View parent) {
mActivity = activity;
mController = controller;
@@ -246,11 +243,8 @@
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- mSurfaceView.addOnLayoutChangeListener(mLayoutListener);
Log.v(TAG, "Using mdp_preview_content (MDP path)");
-
- View surfaceContainer = mRootView.findViewById(R.id.preview_container);
- surfaceContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ mSurfaceView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight,
@@ -258,6 +252,8 @@
int width = right - left;
int height = bottom - top;
+ tryToCloseSubList();
+
if (mMaxPreviewWidth == 0 && mMaxPreviewHeight == 0) {
mMaxPreviewWidth = width;
mMaxPreviewHeight = height;
@@ -478,9 +474,6 @@
if (mFaceView != null) {
mFaceView.setLayoutParams(lp);
}
-
- mController.onScreenSizeChanged((int) mSurfaceTextureUncroppedWidth,
- (int) mSurfaceTextureUncroppedHeight);
}
public void setSurfaceTextureSizeChangedListener(SurfaceTextureSizeChangedListener listener) {
@@ -597,6 +590,7 @@
});
if (mController.isImageCaptureIntent()) {
hideSwitcher();
+ mCameraControls.hideRemainingPhotoCnt();
mSwitcher.setSwitcherVisibility(false);
ViewGroup cameraControls = (ViewGroup) mRootView.findViewById(R.id.camera_controls);
mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls);
@@ -1148,6 +1142,11 @@
mPieRenderer.setBlockFocus(false);
}
}
+
+ @Override
+ public void onZoomValueChanged(float value) {
+
+ }
}
@Override
@@ -1176,6 +1175,13 @@
return mSurfaceHolder;
}
+ public void hideSurfaceView() {
+ mSurfaceView.setVisibility(View.INVISIBLE);
+ }
+
+ public void showSurfaceView() {
+ mSurfaceView.setVisibility(View.VISIBLE);
+ }
// Countdown timer
private void initializeCountDown() {
diff --git a/src/com/android/camera/PreviewGestures.java b/src/com/android/camera/PreviewGestures.java
index 00f7d02..4f26240 100644
--- a/src/com/android/camera/PreviewGestures.java
+++ b/src/com/android/camera/PreviewGestures.java
@@ -107,8 +107,9 @@
else if (mCaptureMenu != null && !mCaptureMenu.isMenuBeingShown())
mCaptureMenu.openFirstLevel();
return true;
+ } else {
+ return onSingleTapUp(e2);
}
- return false;
}
private boolean isLeftSwipe(int orientation, int deltaX, int deltaY) {
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index 4724bd2..8e2dc90 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -1094,6 +1094,8 @@
mUI.enableShutter(true);
}
+ mUI.applySurfaceChange(VideoUI.SURFACE_STATUS.SURFACE_VIEW);
+
mUI.initDisplayChangeListener();
// Initializing it here after the preview is started.
mUI.initializeZoom(mParameters);
@@ -1279,6 +1281,7 @@
if(mWasMute != mIsMute) {
setMute(mWasMute, false);
}
+ mUI.applySurfaceChange(VideoUI.SURFACE_STATUS.HIDE);
}
@Override
@@ -1657,12 +1660,13 @@
long duration = 0L;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- retriever.setDataSource(mCurrentVideoFilename);
+
try {
+ retriever.setDataSource(mCurrentVideoFilename);
duration = Long.valueOf(retriever.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_DURATION));
- } catch (NumberFormatException e) {
- Log.e(TAG, "cannot retrieve duration metadata");
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "cannot access the file");
}
retriever.release();
@@ -2716,6 +2720,7 @@
}
Log.d(TAG, "Start to switch camera.");
+ mUI.applySurfaceChange(VideoUI.SURFACE_STATUS.HIDE);
mCameraId = mPendingSwitchCameraId;
mPendingSwitchCameraId = -1;
setCameraId(mCameraId);
@@ -2727,6 +2732,7 @@
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
openCamera();
readVideoPreferences();
+ mUI.applySurfaceChange(VideoUI.SURFACE_STATUS.SURFACE_VIEW);
startPreview();
initializeVideoSnapshot();
resizeForPreviewAspectRatio();
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 9a882e9..8447db2 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -130,13 +130,10 @@
private float mSurfaceTextureUncroppedWidth;
private float mSurfaceTextureUncroppedHeight;
- private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right,
- int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
- tryToCloseSubList();
- }
- };
+ public enum SURFACE_STATUS {
+ HIDE,
+ SURFACE_VIEW;
+ }
public void showPreviewCover() {
mPreviewCover.setVisibility(View.VISIBLE);
@@ -177,6 +174,14 @@
}
}
+ public synchronized void applySurfaceChange(SURFACE_STATUS status) {
+ if(status == SURFACE_STATUS.HIDE) {
+ mSurfaceView.setVisibility(View.GONE);
+ return;
+ }
+ mSurfaceView.setVisibility(View.VISIBLE);
+ }
+
public VideoUI(CameraActivity activity, VideoController controller, View parent) {
mActivity = activity;
mController = controller;
@@ -190,9 +195,7 @@
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- mSurfaceView.addOnLayoutChangeListener(mLayoutListener);
Log.v(TAG, "Using mdp_preview_content (MDP path)");
-
View surfaceContainer = mRootView.findViewById(R.id.preview_container);
surfaceContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
@@ -202,6 +205,7 @@
int width = right - left;
int height = bottom - top;
+ tryToCloseSubList();
if (mMaxPreviewWidth == 0 && mMaxPreviewHeight == 0) {
mMaxPreviewWidth = width;
mMaxPreviewHeight = height;
@@ -1108,6 +1112,11 @@
mPieRenderer.setBlockFocus(false);
}
}
+
+ @Override
+ public void onZoomValueChanged(float value) {
+
+ }
}
// SurfaceHolder callbacks
diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java
index 587cfca..9895689 100644
--- a/src/com/android/camera/ui/CameraControls.java
+++ b/src/com/android/camera/ui/CameraControls.java
@@ -84,7 +84,7 @@
private float[][] mLocY = new float[4][10];
private boolean[] mTempEnabled = new boolean[10];
private boolean mLocSet = false;
-
+ private boolean mHideRemainingPhoto = false;
private LinearLayout mRemainingPhotos;
private TextView mRemainingPhotosText;
private int mCurrentRemaining = -1;
@@ -706,7 +706,8 @@
mPreview.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
break;
}
- if (mRemainingPhotos.getVisibility() == View.INVISIBLE) {
+ if ((mRemainingPhotos.getVisibility() == View.INVISIBLE) &&
+ !mHideRemainingPhoto){
mRemainingPhotos.setVisibility(View.VISIBLE);
}
mRefocusToast.setVisibility(View.GONE);
@@ -922,7 +923,7 @@
public void updateRemainingPhotos(int remaining) {
long remainingStorage = Storage.getAvailableSpace() - Storage.LOW_STORAGE_THRESHOLD_BYTES;
- if (remaining < 0 && remainingStorage <= 0) {
+ if ((remaining < 0 && remainingStorage <= 0) || mHideRemainingPhoto) {
mRemainingPhotos.setVisibility(View.GONE);
} else {
for (int i = mRemainingPhotos.getChildCount() - 1; i >= 0; --i) {
@@ -961,7 +962,7 @@
public void showRefocusToast(boolean show) {
mRefocusToast.setVisibility(show ? View.VISIBLE : View.GONE);
- if (mCurrentRemaining > 0 ) {
+ if ((mCurrentRemaining > 0 ) && !mHideRemainingPhoto) {
mRemainingPhotos.setVisibility(show ? View.GONE : View.VISIBLE);
}
}
@@ -1003,6 +1004,12 @@
mMenu.setVisibility(View.VISIBLE);
}
+ public void hideRemainingPhotoCnt() {
+ mHideRemainingPhoto = true;
+ mRemainingPhotos.setVisibility(View.GONE);
+ mRemainingPhotosText.setVisibility(View.GONE);
+ }
+
private class ArrowTextView extends TextView {
private static final int TEXT_SIZE = 14;
private static final int PADDING_SIZE = 18;
diff --git a/src/com/android/camera/ui/ZoomRenderer.java b/src/com/android/camera/ui/ZoomRenderer.java
index 7a2e2e8..0358bda 100644
--- a/src/com/android/camera/ui/ZoomRenderer.java
+++ b/src/com/android/camera/ui/ZoomRenderer.java
@@ -49,11 +49,16 @@
private int mZoomFraction;
private Rect mTextBounds;
private int mOrientation;
+ private boolean mCamera2 = false;
+ private float mZoomValue;
+ private float mZoomMinValue;
+ private float mZoomMaxValue;
public interface OnZoomChangedListener {
void onZoomStart();
void onZoomEnd();
void onZoomValueChanged(int index); // only for immediate zoom
+ void onZoomValueChanged(float value);
}
public ZoomRenderer(Context ctx) {
@@ -81,10 +86,23 @@
mMinZoom = 0;
}
+ public void setZoomMax(float zoomMax) {
+ mCamera2 = true;
+ mZoomMaxValue = zoomMax;
+ mZoomMinValue = 1f;
+ }
+
public void setZoom(int index) {
mCircleSize = mMinCircle + index * (mMaxCircle - mMinCircle) / (mMaxZoom - mMinZoom);
}
+ public void setZoom(float zoomValue) {
+ mCamera2 = true;
+ mZoomValue = zoomValue;
+ mCircleSize = (int) (mMinCircle + (mMaxCircle - mMinCircle) * (mZoomValue - mZoomMinValue) /
+ (mZoomMaxValue - mZoomMinValue));
+ }
+
public void setZoomValue(int value) {
value = value / 10;
mZoomSig = value / 10;
@@ -120,6 +138,7 @@
canvas.drawCircle((float) mCenterX, (float) mCenterY,
mCircleSize, mPaint);
String txt = mZoomSig+"."+mZoomFraction+"x";
+ if (mCamera2) txt = "" + mZoomValue;
mTextPaint.getTextBounds(txt, 0, txt.length(), mTextBounds);
canvas.drawText(txt, mCenterX - mTextBounds.centerX(), mCenterY - mTextBounds.centerY(),
mTextPaint);
@@ -133,8 +152,16 @@
circle = Math.min(mMaxCircle, circle);
if (mListener != null && circle != mCircleSize) {
mCircleSize = circle;
- int zoom = mMinZoom + (int) ((mCircleSize - mMinCircle) * (mMaxZoom - mMinZoom) / (mMaxCircle - mMinCircle));
- mListener.onZoomValueChanged(zoom);
+ if (mCamera2) {
+ float zoom = mZoomMinValue + (mZoomMaxValue - mZoomMinValue) / (mMaxCircle -
+ mMinCircle) * (mCircleSize - mMinCircle);
+ zoom = ((int) (zoom * 10)) / 10.0f;
+ mListener.onZoomValueChanged(zoom);
+ } else {
+ int zoom = mMinZoom + (int) ((mCircleSize - mMinCircle) * (mMaxZoom - mMinZoom) /
+ (mMaxCircle - mMinCircle));
+ mListener.onZoomValueChanged(zoom);
+ }
update();
}
return true;
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index 812220c..b1deca6 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -35,6 +35,7 @@
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
+import android.hardware.camera2.CameraCharacteristics;
import android.location.Location;
import android.net.Uri;
import android.os.Handler;
@@ -1168,4 +1169,32 @@
return retRatio;
}
+ public static boolean isZoomSupported(CameraCharacteristics[] characteristics, List<Integer>
+ characteristicsIndex) {
+ for (int i = 0; i < characteristicsIndex.size(); i++) {
+ if (!isZoomSupported(characteristics[characteristicsIndex.get(i)]))
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean isZoomSupported(CameraCharacteristics characteristic) {
+ return characteristic.get(CameraCharacteristics
+ .SCALER_AVAILABLE_MAX_DIGITAL_ZOOM) > 1f;
+ }
+
+ public static boolean isAutoFocusSupported(CameraCharacteristics[] characteristics, List<Integer>
+ characteristicsIndex) {
+ for (int i = 0; i < characteristicsIndex.size(); i++) {
+ if (!isAutoFocusSupported(characteristics[characteristicsIndex.get(i)]))
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean isAutoFocusSupported(CameraCharacteristics characteristic) {
+ Integer maxAfRegions = characteristic.get(
+ CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
+ return maxAfRegions != null && maxAfRegions > 0;
+ }
}