diff options
19 files changed, 365 insertions, 69 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 53ebaa39d..37ce25f8b 100644..100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -121,6 +121,7 @@ android:label="@string/snapcam_app_name" android:launchMode="singleInstance" android:logo="@mipmap/ic_launcher_gallery" + android:screenOrientation="portrait" android:taskAffinity="com.android.camera.SecureCameraActivity" android:theme="@style/Theme.Camera" android:windowSoftInputMode="stateAlwaysHidden|adjustPan" > diff --git a/assets/dependency.json b/assets/dependency.json index 763549320..390adcde4 100644 --- a/assets/dependency.json +++ b/assets/dependency.json @@ -35,7 +35,8 @@ "pref_camera2_whitebalance_key":"1", "pref_camera2_exposure_key":"0", "pref_camera2_clearsight_key":"off", - "pref_camera2_mono_preview_key":"off"} + "pref_camera2_mono_preview_key":"off", + "pref_camera2_mpo_key":"off"} , "100": {"pref_camera2_longshot_key":"off", @@ -44,6 +45,13 @@ , "0": {"pref_camera2_clearsight_key":"off", - "pref_camera2_mono_preview_key":"off"} + "pref_camera2_mono_preview_key":"off", + "pref_camera2_mpo_key":"off"} + }, + "pref_camera2_clearsight_key": + { + "off":{}, + "on": + {"pref_camera2_mpo_key":"on"} } } diff --git a/res/values/camera2arrays.xml b/res/values/camera2arrays.xml index 25105ba65..37a33ec17 100644 --- a/res/values/camera2arrays.xml +++ b/res/values/camera2arrays.xml @@ -100,6 +100,17 @@ <item>@string/pref_camera2_clearsight_value_on</item> </string-array> + <string-array name="pref_camera2_mpo_entries" translatable="true"> + <item>@string/pref_camera2_mpo_entry_off</item> + <item>@string/pref_camera2_mpo_entry_on</item> + </string-array> + + <string-array name="pref_camera2_mpo_entryvalues" translatable="false"> + <item>@string/pref_camera2_mpo_value_off</item> + <item>@string/pref_camera2_mpo_value_on</item> + </string-array> + + <!-- Refer to CONTROL_SCENE_MODE of Camera2 API for values -1 refers to ones not supported in Camera2 API 0 is special case added for auto (meaning off) diff --git a/res/values/qcomstrings.xml b/res/values/qcomstrings.xml index e8917f3ee..0fb750590 100644 --- a/res/values/qcomstrings.xml +++ b/res/values/qcomstrings.xml @@ -968,8 +968,8 @@ <string name="pref_camera2_clearsight_title" translatable="true">ClearSight</string> <string name="pref_camera2_clearsight_default" translatable="false">on</string> - <string name="pref_camera2_clearsight_entry_on" translatable="false">On</string> - <string name="pref_camera2_clearsight_entry_off" translatable="false">Off</string> + <string name="pref_camera2_clearsight_entry_on" translatable="true">On</string> + <string name="pref_camera2_clearsight_entry_off" translatable="true">Off</string> <string name="pref_camera2_clearsight_value_on" translatable="false">on</string> <string name="pref_camera2_clearsight_value_off" translatable="false">off</string> @@ -977,6 +977,14 @@ <string name="clearsight_capture_success">ClearSight capture successful</string> <string name="clearsight_capture_fail">ClearSight capture failed</string> + <string name="pref_camera2_mpo_title" translatable="true">MPO Format</string> + <string name="pref_camera2_mpo_default" translatable="false">off</string> + <string name="pref_camera2_mpo_entry_on" translatable="true">On</string> + <string name="pref_camera2_mpo_entry_off" translatable="true">Off</string> + + <string name="pref_camera2_mpo_value_on" translatable="false">on</string> + <string name="pref_camera2_mpo_value_off" translatable="false">off</string> + <string name="pref_camera2_scenemode_default" translatable="false">0</string> <string name="pref_camera2_whitebalance_default" translatable="false">1</string> <string name="pref_camera2_coloreffect_default" translatable="false">0</string> diff --git a/res/xml/capture_preferences.xml b/res/xml/capture_preferences.xml index c5aab1a7d..2f0849442 100644 --- a/res/xml/capture_preferences.xml +++ b/res/xml/capture_preferences.xml @@ -107,6 +107,13 @@ camera:key="pref_camera2_clearsight_key" camera:title="@string/pref_camera2_clearsight_title"/> + <ListPreference + camera:defaultValue="@string/pref_camera2_mpo_default" + camera:entries="@array/pref_camera2_mpo_entries" + camera:entryValues="@array/pref_camera2_mpo_entryvalues" + camera:key="pref_camera2_mpo_key" + camera:title="@string/pref_camera2_mpo_title"/> + <IconListPreference camera:defaultValue="@string/pref_camera2_coloreffect_default" camera:entries="@array/pref_camera2_coloreffect_entries" diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index e015d9c25..5666331fa 100644..100755 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -601,8 +601,8 @@ public class CameraActivity extends Activity try { Log.w(TAG, "Gallery not found"); Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); intent.putExtra(KEY_FROM_SNAPCAM, true); + startActivity(intent); } catch (ActivityNotFoundException e) { Log.w(TAG, "No Activity could be found to open image or video"); } diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java index bf63de271..4edf3ab9e 100644 --- a/src/com/android/camera/CaptureModule.java +++ b/src/com/android/camera/CaptureModule.java @@ -72,6 +72,8 @@ import android.view.SurfaceView; import android.view.View; import android.widget.Toast; +import com.android.camera.exif.ExifInterface; +import com.android.camera.Exif; import com.android.camera.imageprocessor.filter.ImageFilter; import com.android.camera.imageprocessor.PostProcessor; import com.android.camera.imageprocessor.FrameProcessor; @@ -144,6 +146,10 @@ public class CaptureModule implements CameraModule, PhotoController, * Camera state: Waiting for the touch-to-focus to converge. */ private static final int STATE_WAITING_TOUCH_FOCUS = 5; + /** + * Camera state: Focus and exposure has been locked and converged. + */ + private static final int STATE_AF_AE_LOCKED = 6; private static final String TAG = "SnapCam_CaptureModule"; // Used for check memory status for longshot mode @@ -214,6 +220,7 @@ public class CaptureModule implements CameraModule, PhotoController, private HandlerThread mCameraThread; private HandlerThread mImageAvailableThread; private HandlerThread mCaptureCallbackThread; + private HandlerThread mMpoSaveThread; /** * A {@link Handler} for running tasks in the background. @@ -227,6 +234,7 @@ public class CaptureModule implements CameraModule, PhotoController, private Handler mCameraHandler; private Handler mImageAvailableHandler; private Handler mCaptureCallbackHandler; + private Handler mMpoSaveHandler; /** * An {@link ImageReader} that handles still image capture. @@ -516,8 +524,7 @@ public class CaptureModule implements CameraModule, PhotoController, // CONTROL_AE_STATE can be null on some devices if (aeState == null || (aeState == CaptureResult .CONTROL_AE_STATE_CONVERGED) && isFlashOff(id)) { - mState[id] = STATE_PICTURE_TAKEN; - captureStillPicture(id); + checkAfAeStatesAndCapture(id); } else { runPrecaptureSequence(id); } @@ -542,8 +549,7 @@ public class CaptureModule implements CameraModule, PhotoController, Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); Log.d(TAG, "STATE_WAITING_NON_PRECAPTURE id: " + id + " aeState:" + aeState); if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) { - mState[id] = STATE_PICTURE_TAKEN; - captureStillPicture(id); + checkAfAeStatesAndCapture(id); } break; } @@ -552,12 +558,33 @@ public class CaptureModule implements CameraModule, PhotoController, } } + private void checkAfAeStatesAndCapture(int id) { + if(isBackCamera() && getCameraMode() == DUAL_MODE) { + mState[id] = STATE_AF_AE_LOCKED; + if(mState[BAYER_ID] == STATE_AF_AE_LOCKED && + mState[MONO_ID] == STATE_AF_AE_LOCKED) { + mState[BAYER_ID] = STATE_PICTURE_TAKEN; + mState[MONO_ID] = STATE_PICTURE_TAKEN; + captureStillPicture(BAYER_ID); + captureStillPicture(MONO_ID); + } + } else { + mState[id] = STATE_PICTURE_TAKEN; + captureStillPicture(id); + } + } + public void startFaceDetection() { mUI.onStartFaceDetection(mDisplayOrientation, mSettingsManager.isFacingFront(getMainCameraId()), mSettingsManager.getSensorActiveArraySize(getMainCameraId())); } + private boolean canStartMonoPreview() { + return getCameraMode() == MONO_MODE || + (getCameraMode() == DUAL_MODE && isMonoPreviewOn()); + } + private boolean isMonoPreviewOn() { String value = mSettingsManager.getValue(SettingsManager.KEY_MONO_PREVIEW); if (value == null) return false; @@ -586,6 +613,12 @@ public class CaptureModule implements CameraModule, PhotoController, return isBackCamera() && getCameraMode() == DUAL_MODE && value.equals("on"); } + private boolean isMpoOn() { + String value = mSettingsManager.getValue(SettingsManager.KEY_MPO); + if (value == null) return false; + return isBackCamera() && getCameraMode() == DUAL_MODE && value.equals("on"); + } + public static int getQualityNumber(String jpegQuality) { try { int qualityPercentile = Integer.parseInt(jpegQuality); @@ -720,8 +753,15 @@ public class CaptureModule implements CameraModule, PhotoController, mIsLinked = true; } // Finally, we start displaying the camera preview. - mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id] - .build(), mCaptureCallback, mCameraHandler); + // for cases where we are in dual mode with mono preview off, + // don't set repeating request for mono + if(id == MONO_ID && !canStartMonoPreview()) { + mCaptureSession[id].capture(mPreviewRequestBuilder[id] + .build(), mCaptureCallback, mCameraHandler); + } else { + mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id] + .build(), mCaptureCallback, mCameraHandler); + } if (isClearSightOn()) { ClearSightImageProcessor.getInstance().onCaptureSessionConfigured(id == BAYER_ID, cameraCaptureSession); } @@ -807,8 +847,13 @@ public class CaptureModule implements CameraModule, PhotoController, mPreviewRequestBuilder[id].set(CaptureRequest.LENS_FOCUS_DISTANCE, fd); mPreviewRequestBuilder[id].setTag(id); try { - mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id] - .build(), mCaptureCallback, mCameraHandler); + if(id == MONO_ID && !canStartMonoPreview()) { + mCaptureSession[id].capture(mPreviewRequestBuilder[id] + .build(), mCaptureCallback, mCameraHandler); + } else { + mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id] + .build(), mCaptureCallback, mCameraHandler); + } } catch (CameraAccessException e) { e.printStackTrace(); } @@ -1076,6 +1121,11 @@ public class CaptureModule implements CameraModule, PhotoController, } }, mCaptureCallbackHandler); } else { + if(isMpoOn()) { + mCaptureStartTime = System.currentTimeMillis(); + mMpoSaveHandler.obtainMessage(MpoSaveHandler.MSG_CONFIGURE, + Long.valueOf(mCaptureStartTime)).sendToTarget(); + } mCaptureSession[id].capture(captureBuilder.build(), new CameraCaptureSession.CaptureCallback() { @@ -1225,21 +1275,28 @@ public class CaptureModule implements CameraModule, PhotoController, public void onImageAvailable(ImageReader reader) { Log.d(TAG, "image available for cam: " + mCamId); Image image = reader.acquireNextImage(); - mCaptureStartTime = System.currentTimeMillis(); - mNamedImages.nameNewImage(mCaptureStartTime); - NamedEntity name = mNamedImages.getNextNameEntity(); - String title = (name == null) ? null : name.title; - long date = (name == null) ? -1 : name.date; - - ByteBuffer buffer = image.getPlanes()[0].getBuffer(); - byte[] bytes = new byte[buffer.remaining()]; - mLastJpegData = bytes; - buffer.get(bytes); - - mActivity.getMediaSaveService().addImage(bytes, title, date, - null, image.getWidth(), image.getHeight(), 0, null, - mOnMediaSavedListener, mContentResolver, "jpeg"); - image.close(); + + if(isMpoOn()) { + mMpoSaveHandler.obtainMessage( + MpoSaveHandler.MSG_NEW_IMG, mCamId, 0, image).sendToTarget(); + } else { + mCaptureStartTime = System.currentTimeMillis(); + mNamedImages.nameNewImage(mCaptureStartTime); + NamedEntity name = mNamedImages.getNextNameEntity(); + String title = (name == null) ? null : name.title; + long date = (name == null) ? -1 : name.date; + + byte[] bytes = getJpegData(image); + mLastJpegData = bytes; + + ExifInterface exif = Exif.getExif(bytes); + int orientation = Exif.getOrientation(exif); + + mActivity.getMediaSaveService().addImage(bytes, title, date, + null, image.getWidth(), image.getHeight(), orientation, null, + mOnMediaSavedListener, mContentResolver, "jpeg"); + image.close(); + } } }, mImageAvailableHandler); } @@ -1275,8 +1332,11 @@ public class CaptureModule implements CameraModule, PhotoController, mLastJpegData = bytes; buffer.get(bytes); + ExifInterface exif = Exif.getExif(bytes); + int orientation = Exif.getOrientation(exif); + mActivity.getMediaSaveService().addImage(bytes, title, date, - null, image.getWidth(), image.getHeight(), 0, null, + null, image.getWidth(), image.getHeight(), orientation, null, mOnMediaSavedListener, mContentResolver, "jpeg"); image.close(); } @@ -1300,8 +1360,13 @@ public class CaptureModule implements CameraModule, PhotoController, mState[id] = STATE_PREVIEW; mControlAFMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE; setAFModeToPreview(id, mControlAFMode); - mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(), - mCaptureCallback, mCameraHandler); + if(id == MONO_ID && !canStartMonoPreview()) { + mCaptureSession[id].capture(mPreviewRequestBuilder[id] + .build(), mCaptureCallback, mCameraHandler); + } else { + mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(), + mCaptureCallback, mCameraHandler); + } mTakingPicture[id] = false; mActivity.runOnUiThread(new Runnable() { @Override @@ -1454,10 +1519,13 @@ public class CaptureModule implements CameraModule, PhotoController, mImageAvailableThread.start(); mCaptureCallbackThread = new HandlerThread("CameraCaptureCallback"); mCaptureCallbackThread.start(); + mMpoSaveThread = new HandlerThread("MpoSaveHandler"); + mMpoSaveThread.start(); mCameraHandler = new MyCameraHandler(mCameraThread.getLooper()); mImageAvailableHandler = new Handler(mImageAvailableThread.getLooper()); mCaptureCallbackHandler = new Handler(mCaptureCallbackThread.getLooper()); + mMpoSaveHandler = new MpoSaveHandler(mMpoSaveThread.getLooper()); } /** @@ -1467,6 +1535,7 @@ public class CaptureModule implements CameraModule, PhotoController, mCameraThread.quitSafely(); mImageAvailableThread.quitSafely(); mCaptureCallbackThread.quitSafely(); + mMpoSaveThread.quitSafely(); try { mCameraThread.join(); @@ -1489,6 +1558,13 @@ public class CaptureModule implements CameraModule, PhotoController, } catch (InterruptedException e) { e.printStackTrace(); } + try { + mMpoSaveThread.join(); + mMpoSaveThread = null; + mMpoSaveHandler = null; + } catch (InterruptedException e) { + e.printStackTrace(); + } } private void openCamera(int id) { @@ -2625,8 +2701,13 @@ public class CaptureModule implements CameraModule, PhotoController, private void applyZoomAndUpdate(int id) { applyZoom(mPreviewRequestBuilder[id], id); try { - mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id] - .build(), mCaptureCallback, mCameraHandler); + if(id == MONO_ID && !canStartMonoPreview()) { + mCaptureSession[id].capture(mPreviewRequestBuilder[id] + .build(), mCaptureCallback, mCameraHandler); + } else { + mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id] + .build(), mCaptureCallback, mCameraHandler); + } } catch (CameraAccessException e) { e.printStackTrace(); } @@ -2961,8 +3042,13 @@ public class CaptureModule implements CameraModule, PhotoController, } if (updatePreviewMono) { try { - mCaptureSession[MONO_ID].setRepeatingRequest(mPreviewRequestBuilder[MONO_ID] - .build(), mCaptureCallback, mCameraHandler); + if(canStartMonoPreview()) { + mCaptureSession[MONO_ID].setRepeatingRequest(mPreviewRequestBuilder[MONO_ID] + .build(), mCaptureCallback, mCameraHandler); + } else { + mCaptureSession[MONO_ID].capture(mPreviewRequestBuilder[MONO_ID] + .build(), mCaptureCallback, mCameraHandler); + } } catch (CameraAccessException e) { e.printStackTrace(); } @@ -3096,6 +3182,69 @@ public class CaptureModule implements CameraModule, PhotoController, } } + private class MpoSaveHandler extends Handler { + static final int MSG_CONFIGURE = 0; + static final int MSG_NEW_IMG = 1; + + private Image monoImage; + private Image bayerImage; + private Long captureStartTime; + + public MpoSaveHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_CONFIGURE: + captureStartTime = (Long) msg.obj; + break; + case MSG_NEW_IMG: + processNewImage(msg); + break; + } + } + + private void processNewImage(Message msg) { + Log.d(TAG, "MpoSaveHandler:processNewImage for cam id: " + msg.arg1); + if(msg.arg1 == MONO_ID) { + monoImage = (Image)msg.obj; + } else if(bayerImage == null){ + bayerImage = (Image)msg.obj; + } + + if(monoImage != null && bayerImage != null) { + saveMpoImage(); + } + } + + private void saveMpoImage() { + mNamedImages.nameNewImage(captureStartTime); + NamedEntity namedEntity = mNamedImages.getNextNameEntity(); + String title = (namedEntity == null) ? null : namedEntity.title; + long date = (namedEntity == null) ? -1 : namedEntity.date; + int width = bayerImage.getWidth(); + int height = bayerImage.getHeight(); + byte[] bayerBytes = getJpegData(bayerImage); + byte[] monoBytes = getJpegData(monoImage); + + mLastJpegData = bayerBytes; + ExifInterface exif = Exif.getExif(bayerBytes); + int orientation = Exif.getOrientation(exif); + + mActivity.getMediaSaveService().addMpoImage( + null, bayerBytes, monoBytes, width, height, title, + date, null, orientation, mOnMediaSavedListener, mContentResolver, "jpeg"); + + bayerImage.close(); + bayerImage = null; + monoImage.close(); + monoImage = null; + namedEntity = null; + } + } + @Override public void onClearSightSuccess() { Log.d(TAG, "onClearSightSuccess"); @@ -3149,4 +3298,11 @@ public class CaptureModule implements CameraModule, PhotoController, public void onErrorListener(int error) { enableRecordingLocation(false); } + + private byte[] getJpegData(Image image) { + ByteBuffer buffer = image.getPlanes()[0].getBuffer(); + byte[] bytes = new byte[buffer.remaining()]; + buffer.get(bytes); + return bytes; + } } diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java index d455fa41c..dadbb3144 100644 --- a/src/com/android/camera/CaptureUI.java +++ b/src/com/android/camera/CaptureUI.java @@ -122,6 +122,7 @@ public class CaptureUI implements FocusOverlayManager.FocusUI, SettingsManager.KEY_MONO_ONLY, SettingsManager.KEY_CLEARSIGHT, SettingsManager.KEY_MONO_PREVIEW, + SettingsManager.KEY_MPO, SettingsManager.KEY_NOISE_REDUCTION, SettingsManager.KEY_DIS, SettingsManager.KEY_VIDEO_ENCODER, diff --git a/src/com/android/camera/PermissionsActivity.java b/src/com/android/camera/PermissionsActivity.java index 2b5901a58..c5e43e56d 100644 --- a/src/com/android/camera/PermissionsActivity.java +++ b/src/com/android/camera/PermissionsActivity.java @@ -119,21 +119,24 @@ public class PermissionsActivity extends Activity { String permissions[], int[] grantResults) { if (mShouldRequestCameraPermission) { - if (grantResults[mIndexPermissionRequestCamera] == PackageManager.PERMISSION_GRANTED) { + if ((grantResults.length >= mIndexPermissionRequestCamera + 1) && + (grantResults[mIndexPermissionRequestCamera] == PackageManager.PERMISSION_GRANTED)) { mFlagHasCameraPermission = true; } else { mCriticalPermissionDenied = true; } } if (mShouldRequestMicrophonePermission) { - if (grantResults[mIndexPermissionRequestMicrophone] == PackageManager.PERMISSION_GRANTED) { + if ((grantResults.length >= mIndexPermissionRequestMicrophone + 1) && + (grantResults[mIndexPermissionRequestMicrophone] == PackageManager.PERMISSION_GRANTED)) { mFlagHasMicrophonePermission = true; } else { mCriticalPermissionDenied = true; } } if (mShouldRequestStoragePermission) { - if (grantResults[mIndexPermissionRequestStorage] == PackageManager.PERMISSION_GRANTED) { + if ((grantResults.length >= mIndexPermissionRequestStorage + 1) && + (grantResults[mIndexPermissionRequestStorage] == PackageManager.PERMISSION_GRANTED)) { mFlagHasStoragePermission = true; } else { mCriticalPermissionDenied = true; @@ -141,7 +144,8 @@ public class PermissionsActivity extends Activity { } if (mShouldRequestLocationPermission) { - if (grantResults[mIndexPermissionRequestLocation] == PackageManager.PERMISSION_GRANTED) { + if ((grantResults.length >= mIndexPermissionRequestLocation + 1) && + (grantResults[mIndexPermissionRequestLocation] == PackageManager.PERMISSION_GRANTED)) { // Do nothing } else { // Do nothing diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java index 8988e8e2a..c2f9a538b 100644..100755 --- a/src/com/android/camera/PhotoMenu.java +++ b/src/com/android/camera/PhotoMenu.java @@ -693,6 +693,7 @@ public class PhotoMenu extends MenuController popup1.setPreferenceEnabled(CameraSettings.KEY_FLASH_MODE, false); popup1.setPreferenceEnabled(CameraSettings.KEY_WHITE_BALANCE, false); popup1.setPreferenceEnabled(CameraSettings.KEY_EXPOSURE, false); + popup1.setPreferenceEnabled(CameraSettings.KEY_QC_CHROMA_FLASH, false); } if ((autohdr != null) && autohdr.equals("enable")) { popup1.setPreferenceEnabled(CameraSettings.KEY_SCENE_MODE, false); @@ -788,7 +789,11 @@ public class PhotoMenu extends MenuController || (notSame(hdrPref, CameraSettings.KEY_CAMERA_HDR, mSettingOff))) { buttonSetEnabled(mFilterModeSwitcher, false); changeFilterModeControlIcon("none"); - } else { + } else if (same(scenePref, CameraSettings.KEY_SCENE_MODE, Parameters.SCENE_MODE_AUTO) + && (same(hdrPref, CameraSettings.KEY_CAMERA_HDR, mSettingOff) + || !hdrPref.getKey().equals(CameraSettings.KEY_CAMERA_HDR))) { + //mFilterModeSwitcher can be enabled only when scene mode is set to auto + // and HDR is set to off, buttonSetEnabled(mFilterModeSwitcher, true); } } @@ -820,7 +825,6 @@ public class PhotoMenu extends MenuController .findPreference(prefKey); if (pref == null) return; - if (prefKey.equals(CameraSettings.KEY_CAMERA_ID)) { // Hide the camera control while switching the camera. // The camera control will be added back when @@ -1457,6 +1461,18 @@ public class PhotoMenu extends MenuController } } + String chromaFlashOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_chromaflash_on); + if (notSame(pref, CameraSettings.KEY_SCENE_MODE, Parameters.SCENE_MODE_AUTO)) { + ListPreference lp = mPreferenceGroup + .findPreference(CameraSettings.KEY_ADVANCED_FEATURES); + if (lp != null && chromaFlashOn.equals(lp.getValue())) { + setPreference(CameraSettings.KEY_QC_CHROMA_FLASH, mSettingOff); + setPreference(CameraSettings.KEY_ADVANCED_FEATURES, + mActivity.getString(R.string.pref_camera_advanced_feature_default)); + } + } + if (notSame(pref, CameraSettings.KEY_SCENE_MODE, "auto")) { setPreference(CameraSettings.KEY_COLOR_EFFECT, mActivity.getString(R.string.pref_camera_coloreffect_default)); diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index 27ea62947..b4f8c3a74 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -2232,6 +2232,7 @@ public class PhotoModule public synchronized void onShutterButtonClick() { if ((mCameraDevice == null) || mPaused || mUI.collapseCameraControls() + || !mUI.mMenuInitialized || (mCameraState == SWITCHING_CAMERA) || (mCameraState == PREVIEW_STOPPED) || (mCameraState == LONGSHOT) diff --git a/src/com/android/camera/SDCard.java b/src/com/android/camera/SDCard.java index 8fda17c67..b88e32245 100644..100755 --- a/src/com/android/camera/SDCard.java +++ b/src/com/android/camera/SDCard.java @@ -28,8 +28,10 @@ package com.android.camera; +import android.content.BroadcastReceiver; import android.content.Context; -import android.os.UserHandle; +import android.content.Intent; +import android.content.IntentFilter; import android.os.Environment; import android.os.storage.StorageVolume; import android.os.storage.StorageManager; @@ -42,8 +44,8 @@ public class SDCard { private StorageManager mStorageManager = null; private StorageVolume mVolume = null; - private String path = null; - private String rawpath = null; + private String mPath = null; + private String mRawpath = null; private static SDCard sSDCard; public boolean isWriteable() { @@ -59,20 +61,20 @@ public class SDCard { if (mVolume == null) { return null; } - if (path == null) { - path = mVolume.getPath() + "/DCIM/Camera"; + if (mPath == null) { + mPath = mVolume.getPath() + "/DCIM/Camera"; } - return path; + return mPath; } public String getRawDirectory() { if (mVolume == null) { return null; } - if (rawpath == null) { - rawpath = mVolume.getPath() + "/DCIM/Camera/raw"; + if (mRawpath == null) { + mRawpath = mVolume.getPath() + "/DCIM/Camera/raw"; } - return rawpath; + return mRawpath; } public static void initialize(Context context) { @@ -92,13 +94,32 @@ public class SDCard { private SDCard(Context context) { try { mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); - final StorageVolume[] volumes = mStorageManager.getVolumeList(); - if (volumes.length > VOLUME_SDCARD_INDEX) { - mVolume = volumes[VOLUME_SDCARD_INDEX]; - } + initVolume(); + registerMediaBroadcastreceiver(context); } catch (Exception e) { Log.e(TAG, "couldn't talk to MountService", e); } } + private void initVolume() { + final StorageVolume[] volumes = mStorageManager.getVolumeList(); + mVolume = (volumes.length > VOLUME_SDCARD_INDEX) ? + volumes[VOLUME_SDCARD_INDEX] : null; + mPath = null; + mRawpath = null; + } + + private void registerMediaBroadcastreceiver(Context context) { + IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); + filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); + filter.addDataScheme("file"); + context.registerReceiver(mMediaBroadcastReceiver , filter); + } + + private BroadcastReceiver mMediaBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + initVolume(); + } + }; } diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java index 90f426090..7e2e3bf6a 100644 --- a/src/com/android/camera/SettingsManager.java +++ b/src/com/android/camera/SettingsManager.java @@ -88,6 +88,7 @@ public class SettingsManager implements ListMenu.SettingsListener { public static final String KEY_MONO_ONLY = "pref_camera2_mono_only_key"; public static final String KEY_MONO_PREVIEW = "pref_camera2_mono_preview_key"; public static final String KEY_CLEARSIGHT = "pref_camera2_clearsight_key"; + public static final String KEY_MPO = "pref_camera2_mpo_key"; public static final String KEY_FILTER_MODE = "pref_camera2_filter_mode_key"; public static final String KEY_COLOR_EFFECT = "pref_camera2_coloreffect_key"; public static final String KEY_SCENE_MODE = "pref_camera2_scenemode_key"; @@ -490,6 +491,7 @@ public class SettingsManager implements ListMenu.SettingsListener { ListPreference clearsight = mPreferenceGroup.findPreference(KEY_CLEARSIGHT); ListPreference monoPreview = mPreferenceGroup.findPreference(KEY_MONO_PREVIEW); ListPreference monoOnly = mPreferenceGroup.findPreference(KEY_MONO_ONLY); + ListPreference mpo = mPreferenceGroup.findPreference(KEY_MPO); ListPreference redeyeReduction = mPreferenceGroup.findPreference(KEY_REDEYE_REDUCTION); ListPreference videoQuality = mPreferenceGroup.findPreference(KEY_VIDEO_QUALITY); ListPreference videoEncoder = mPreferenceGroup.findPreference(KEY_VIDEO_ENCODER); @@ -543,6 +545,7 @@ public class SettingsManager implements ListMenu.SettingsListener { if (clearsight != null) removePreference(mPreferenceGroup, KEY_CLEARSIGHT); if (monoPreview != null) removePreference(mPreferenceGroup, KEY_MONO_PREVIEW); if (monoOnly != null) removePreference(mPreferenceGroup, KEY_MONO_ONLY); + if (mpo != null) removePreference(mPreferenceGroup, KEY_MPO); } if (redeyeReduction != null) { diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java index 6b26a9c88..a93cff611 100755 --- a/src/com/android/camera/VideoModule.java +++ b/src/com/android/camera/VideoModule.java @@ -220,6 +220,9 @@ public class VideoModule implements CameraModule, private static final boolean PERSIST_4K_NO_LIMIT = android.os.SystemProperties.getBoolean("persist.camcorder.4k.nolimit", false); + private static final int PERSIST_EIS_MAX_FPS = + android.os.SystemProperties.getInt("persist.camcorder.eis.maxfps", 30); + private final MediaSaveService.OnMediaSavedListener mOnVideoSavedListener = new MediaSaveService.OnMediaSavedListener() { @Override @@ -1807,7 +1810,11 @@ public class VideoModule implements CameraModule, mUI.cancelAnimations(); mUI.setSwipingEnabled(false); mUI.hideUIwhileRecording(); - + // When recording request is sent before starting preview, onPreviewFrame() + // callback doesn't happen so removing preview cover here, instead. + if (mUI.isPreviewCoverVisible()) { + mUI.hidePreviewCover(); + } mActivity.updateStorageSpaceAndHint(); if (mActivity.getStorageSpaceBytes() <= Storage.LOW_STORAGE_THRESHOLD_BYTES) { Log.v(TAG, "Storage issue, ignore the start request"); @@ -2523,8 +2530,14 @@ public class VideoModule implements CameraModule, CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL, mActivity.getString(R.string.pref_video_time_lapse_frame_interval_default)); int timeLapseInterval = Integer.parseInt(frameIntervalStr); + int rate = 0; + if (!hfr.equals("off")) + rate = Integer.parseInt(hfr); + else + rate = Integer.parseInt(hsr); + Log.v(TAG, "rate = "+rate); if ( (timeLapseInterval != 0) || - (disMode.equals("enable")) || + (disMode.equals("enable") && (rate > PERSIST_EIS_MAX_FPS)) || ((hdr != null) && (!hdr.equals("off"))) ) { Log.v(TAG,"HDR/DIS/Time Lapse ON for HFR/HSR selection, turning HFR/HSR off"); mParameters.setVideoHighFrameRate("off"); diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java index 5203d9e35..cf93feeac 100644 --- a/src/com/android/camera/VideoUI.java +++ b/src/com/android/camera/VideoUI.java @@ -145,6 +145,15 @@ public class VideoUI implements PieRenderer.PieListener, } } + public boolean isPreviewCoverVisible() { + if ((mPreviewCover != null) && + (mPreviewCover.getVisibility() == View.VISIBLE)) { + return true; + } else { + return false; + } + } + private class SettingsPopup extends PopupWindow { public SettingsPopup(View popup) { super(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java index 5de05dca9..48a5492e3 100644 --- a/src/com/android/camera/ui/CameraControls.java +++ b/src/com/android/camera/ui/CameraControls.java @@ -87,7 +87,6 @@ public class CameraControls extends RotatableLayout { private static final int ANIME_DURATION = 300; private float[][] mLocX = new float[4][11]; private float[][] mLocY = new float[4][11]; - private boolean[] mTempEnabled = new boolean[11]; private boolean mLocSet = false; private boolean mHideRemainingPhoto = false; private LinearLayout mRemainingPhotos; @@ -223,10 +222,9 @@ public class CameraControls extends RotatableLayout { mHdrSwitcher.setPressed(false); } mSceneModeSwitcher.setPressed(false); - mFilterModeSwitcher.setPressed(false); - } else { - mTempEnabled[FILTER_MODE_INDEX] = mFilterModeSwitcher.isEnabled(); } + + ((ShutterButton) mShutter).enableTouch(enable); mVideoShutter.setClickable(enable); ((ModuleSwitcher) mSwitcher).enableTouch(enable); @@ -240,7 +238,7 @@ public class CameraControls extends RotatableLayout { } mSceneModeSwitcher.setEnabled(enable); mPreview.setEnabled(enable); - mFilterModeSwitcher.setEnabled(enable && mTempEnabled[FILTER_MODE_INDEX]); + } private void markVisibility() { diff --git a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java index c64a0de2a..3a94baec9 100644 --- a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java +++ b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java @@ -29,6 +29,7 @@ package org.codeaurora.snapcam.filter; +import java.io.IOException; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.util.ArrayDeque; @@ -65,6 +66,8 @@ import android.util.Log; import android.view.Surface; import com.android.camera.CaptureModule; +import com.android.camera.Exif; +import com.android.camera.exif.ExifInterface; import com.android.camera.MediaSaveService; import com.android.camera.MediaSaveService.OnMediaSavedListener; import com.android.camera.PhotoModule.NamedImages; @@ -529,6 +532,13 @@ public class ClearSightImageProcessor { .createReprocessCaptureRequest(reprocImg.mCaptureResult); reprocRequest.addTarget(mImageReader[camId] .getSurface()); + reprocRequest.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, + CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY); + reprocRequest.set(CaptureRequest.EDGE_MODE, + CaptureRequest.EDGE_MODE_HIGH_QUALITY); + reprocRequest.set(CaptureRequest.NOISE_REDUCTION_MODE, + CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY); + if(reprocRequests.size() == 0) { reprocRequest.setTag(new Object()); } @@ -814,11 +824,15 @@ public class ClearSightImageProcessor { height = mClearSightImage.getHeight(); } + byte[] bayerBytes = getJpegData(mBayerImage); + ExifInterface exif = Exif.getExif(bayerBytes); + int orientation = Exif.getOrientation(exif); + mMediaSaveService.addMpoImage( getJpegData(mClearSightImage), - getJpegData(mBayerImage), + bayerBytes, getJpegData(mMonoImage), width, height, title, - date, null, 0, mMediaSavedListener, + date, null, orientation, mMediaSavedListener, mMediaSaveService.getContentResolver(), "jpeg"); mBayerImage.close(); diff --git a/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java b/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java index f2793c822..18e7671b9 100644 --- a/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java +++ b/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java @@ -35,6 +35,7 @@ import java.util.ArrayList; import java.util.List; import android.graphics.Rect; +import android.hardware.camera2.CaptureResult; import android.hardware.camera2.TotalCaptureResult; import android.media.Image; import android.media.Image.Plane; @@ -256,13 +257,20 @@ public class ClearSightNativeEngine { Log.d(TAG, "processImage - dst size - y: " + dstY.capacity() + " vu: " + dstVU.capacity()); + int iso = mRefMonoResult.get(CaptureResult.SENSOR_SENSITIVITY); + long exposure = mRefMonoResult.get(CaptureResult.SENSOR_EXPOSURE_TIME); + // capture result stores exposure time in NS and we need MS. + exposure /= 100000; + + Log.d(TAG, "processImage - iso: " + iso + " exposure ms: " + exposure); boolean result = nativeClearSightProcess(numImages, srcColorY, srcColorVU, metadataColor, mRefColorImage.getWidth(), mRefColorImage.getHeight(), colorPlanes[Y_PLANE].getRowStride(), colorPlanes[VU_PLANE].getRowStride(), srcMonoY, metadataMono, mRefMonoImage.getWidth(), mRefMonoImage.getHeight(), - monoPlanes[Y_PLANE].getRowStride(), mOtpCalibData, dstY, dstVU, + monoPlanes[Y_PLANE].getRowStride(), mOtpCalibData, + (int)exposure, iso, dstY, dstVU, colorPlanes[Y_PLANE].getRowStride(), colorPlanes[VU_PLANE].getRowStride(), roiRect); @@ -287,8 +295,8 @@ public class ClearSightNativeEngine { int[][] metadataColor, int srcColorWidth, int srcColorHeight, int srcColorStrideY, int srcColorStrideVU, ByteBuffer[] srcMonoY, int[][] metadataMono, int srcMonoWidth, int srcMonoHeight, - int srcMonoStrideY, byte[] otp, ByteBuffer dstY, ByteBuffer dstVU, - int dstStrideY, int dstStrideVU, int[] roiRect); + int srcMonoStrideY, byte[] otp, int exposureMs, int iso, + ByteBuffer dstY, ByteBuffer dstVU, int dstStrideY, int dstStrideVU, int[] roiRect); private class SourceImage { ByteBuffer mY; diff --git a/src_pd/com/android/camera/util/IntentHelper.java b/src_pd/com/android/camera/util/IntentHelper.java index 6f17a624b..7949eca2a 100644..100755 --- a/src_pd/com/android/camera/util/IntentHelper.java +++ b/src_pd/com/android/camera/util/IntentHelper.java @@ -17,21 +17,38 @@ package com.android.camera.util; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.net.Uri; public class IntentHelper { private static final String GALLERY_PACKAGE_NAME = "com.android.gallery3d"; + private static final String SNAPDRAGON_GALLERY_PACKAGE_NAME = "org.codeaurora.gallery"; private static final String GALLERY_ACTIVITY_CLASS = - "com.android.gallery3d.app.GalleryActivity"; + "com.android.gallery3d.app.GalleryActivity"; public static Intent getGalleryIntent(Context context) { + String packageName = packageExist(context, SNAPDRAGON_GALLERY_PACKAGE_NAME) ? + SNAPDRAGON_GALLERY_PACKAGE_NAME : GALLERY_PACKAGE_NAME; return new Intent(Intent.ACTION_MAIN) - .setClassName(GALLERY_PACKAGE_NAME, GALLERY_ACTIVITY_CLASS); + .setClassName(packageName, GALLERY_ACTIVITY_CLASS); } public static Intent getVideoPlayerIntent(Context context, Uri uri) { return new Intent(Intent.ACTION_VIEW) - .setDataAndType(uri, "video/*"); + .setDataAndType(uri, "video/*"); + } + + private static boolean packageExist(Context context, String packageName) { + if (packageName == null || "".equals(packageName)) { + return false; + } + try { + context.getPackageManager().getApplicationInfo(packageName, 0); + return true; + } catch (PackageManager.NameNotFoundException e) { + return false; + } } } |