summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk9
-rw-r--r--jni/Android.mk10
-rw-r--r--jni/image_util_jni.cpp153
-rw-r--r--proguard.flags12
-rw-r--r--res/layout/capture_module.xml3
-rw-r--r--res/layout/video_module.xml4
-rw-r--r--res/values/attrs.xml1
-rw-r--r--res/values/camera2arrays.xml574
-rw-r--r--res/values/qcomarrays.xml48
-rw-r--r--res/values/qcomstrings.xml63
-rw-r--r--res/values/styles.xml2
-rw-r--r--res/xml/camera_preferences.xml32
-rw-r--r--res/xml/capture_preferences.xml193
-rw-r--r--rs/YuvToRgb.rs58
-rw-r--r--rs/rotator.rs51
-rw-r--r--src/com/android/camera/CameraActivity.java28
-rw-r--r--src/com/android/camera/CameraSettings.java32
-rw-r--r--src/com/android/camera/CaptureMenu.java571
-rw-r--r--src/com/android/camera/CaptureModule.java1555
-rw-r--r--src/com/android/camera/CaptureUI.java1426
-rw-r--r--src/com/android/camera/ComboPreferences.java8
-rw-r--r--src/com/android/camera/ListPreference.java17
-rw-r--r--src/com/android/camera/PhotoMenu.java18
-rw-r--r--src/com/android/camera/PhotoModule.java65
-rw-r--r--src/com/android/camera/PhotoUI.java7
-rw-r--r--src/com/android/camera/PreviewGestures.java29
-rw-r--r--src/com/android/camera/RecordLocationPreference.java5
-rw-r--r--src/com/android/camera/SettingsManager.java813
-rw-r--r--src/com/android/camera/VideoModule.java18
-rw-r--r--src/com/android/camera/VideoUI.java3
-rw-r--r--src/com/android/camera/WideAnglePanoramaModule.java4
-rw-r--r--src/com/android/camera/exif/ExifInterface.java16
-rw-r--r--src/com/android/camera/imageprocessor/FrameProcessor.java335
-rw-r--r--src/com/android/camera/imageprocessor/PostProcessor.java448
-rw-r--r--src/com/android/camera/imageprocessor/filter/BeautificationFilter.java134
-rw-r--r--src/com/android/camera/imageprocessor/filter/ImageFilter.java74
-rw-r--r--src/com/android/camera/imageprocessor/filter/OptizoomFilter.java148
-rw-r--r--src/com/android/camera/ui/FilmStripView.java32
-rw-r--r--src/com/android/camera/ui/ListMenu.java61
-rw-r--r--src/com/android/camera/ui/ListMenuItem.java22
-rw-r--r--src/com/android/camera/ui/ListSubMenu.java3
-rw-r--r--src/com/android/camera/util/CameraUtil.java29
-rw-r--r--src/com/android/camera/util/PersistUtil.java51
43 files changed, 5454 insertions, 1711 deletions
diff --git a/Android.mk b/Android.mk
index f230c0742..de980e692 100644
--- a/Android.mk
+++ b/Android.mk
@@ -7,15 +7,13 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13
LOCAL_STATIC_JAVA_LIBRARIES += xmp_toolkit
-
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SRC_FILES += $(call all-java-files-under, src_pd)
LOCAL_SRC_FILES += $(call all-java-files-under, src_pd_gcam)
+LOCAL_SRC_FILES += $(call all-renderscript-files-under, rs)
LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res
-LOCAL_CERTIFICATE := platform
-
include $(LOCAL_PATH)/version.mk
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
@@ -25,6 +23,7 @@ LOCAL_AAPT_FLAGS := \
LOCAL_PACKAGE_NAME := SnapdragonCamera
#LOCAL_SDK_VERSION := current
+LOCAL_RENDERSCRIPT_TARGET_API := 23
LOCAL_OVERRIDES_PACKAGES := Camera2
@@ -34,9 +33,9 @@ LOCAL_PROGUARD_FLAG_FILES := proguard.flags
# the libraries in the APK, otherwise just put them in /system/lib and
# leave them out of the APK
ifneq (,$(TARGET_BUILD_APPS))
- LOCAL_JNI_SHARED_LIBRARIES := libjni_snapcammosaic libjni_snapcamtinyplanet
+ LOCAL_JNI_SHARED_LIBRARIES := libjni_snapcammosaic libjni_snapcamtinyplanet libjni_imageutil
else
- LOCAL_REQUIRED_MODULES := libjni_snapcammosaic libjni_snapcamtinyplanet
+ LOCAL_REQUIRED_MODULES := libjni_snapcammosaic libjni_snapcamtinyplanet libjni_imageutil
endif
include $(BUILD_PACKAGE)
diff --git a/jni/Android.mk b/jni/Android.mk
index c94a8075d..de2abb6b8 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -63,3 +63,13 @@ LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
+# ImageUtilForCamera2 with beautification
+include $(CLEAR_VARS)
+LOCAL_LDFLAGS := -llog
+LOCAL_SDK_VERSION := 9
+LOCAL_MODULE := libjni_imageutil
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := image_util_jni.cpp
+LOCAL_CFLAGS += -ffast-math -O3 -funroll-loops
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/jni/image_util_jni.cpp b/jni/image_util_jni.cpp
new file mode 100644
index 000000000..2297f9164
--- /dev/null
+++ b/jni/image_util_jni.cpp
@@ -0,0 +1,153 @@
+/*
+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.
+*/
+
+#include <jni.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#ifdef __ANDROID__
+#include "android/log.h"
+#define printf(...) __android_log_print( ANDROID_LOG_ERROR, "ImageUtil", __VA_ARGS__ )
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+JNIEXPORT jint JNICALL Java_com_android_camera_imageprocessor_FrameProcessor_nativeRotateNV21
+ (JNIEnv* env, jobject thiz, jobjectArray inBuf,
+ jint imageWidth, jint imageHeight, jint degree, jobjectArray outBuf);
+JNIEXPORT jint JNICALL Java_com_android_camera_imageprocessor_FrameProcessor_nativeNV21toRgb(
+ JNIEnv *env, jobject thiz, jobjectArray yvuBuf, jobjectArray rgbBuf, jint width, jint height);
+#ifdef __cplusplus
+}
+#endif
+
+typedef unsigned char uint8_t;
+
+void rotateBufAndMerge(uint8_t *in_buf, jint imageWidth, jint imageHeight, jint degree, uint8_t *out_buf)
+{
+ if(degree == 90) {
+ int i = 0;
+ for (int x = 0; x < imageWidth; x++) {
+ for (int y = imageHeight - 1; y >= 0; y--) {
+ int offset = y * imageWidth + x;
+ out_buf[i] = in_buf[offset];
+ i++;
+ }
+ }
+ i = imageWidth * imageHeight;
+ for (int x = 0; x < imageWidth; x += 2) {
+ for (int y = imageHeight / 2 - 1; y >= 0; y--) {
+ int offset = imageWidth*imageHeight + y * imageWidth + x;
+ out_buf[i] = in_buf[offset];
+ i++;
+ out_buf[i] = in_buf[offset + 1];
+ i++;
+ }
+ }
+ } else if(degree == 270) {
+ int i = 0;
+ for (int x = imageWidth - 1; x >= 0; x--) {
+ for (int y = 0; y < imageHeight; y++) {
+ int offset = y * imageWidth + x;
+ out_buf[i] = in_buf[offset];
+ i++;
+ }
+ }
+ i = imageWidth * imageHeight;
+ for (int x = imageWidth - 2; x >= 0; x-=2) {
+ for (int y = 0; y < imageHeight/2; y++) {
+ int offset = imageWidth*imageHeight + y * imageWidth + x;
+ out_buf[i] = in_buf[offset];
+ i++;
+ out_buf[i] = in_buf[offset + 1];
+ i++;
+ }
+ }
+ } else if(degree == 180) {
+ int i = 0;
+ for (int y = imageHeight - 1; y >= 0; y--) {
+ for (int x = imageWidth - 1; x >= 0 ; x--) {
+ int offset = y * imageWidth + x;
+ out_buf[i] = in_buf[offset];
+ i++;
+ }
+ }
+ i = imageWidth * imageHeight;
+ for (int y = imageHeight/2 - 1; y >= 0; y--) {
+ for (int x = imageWidth - 2; x >= 0 ; x-=2) {
+ int offset = imageWidth*imageHeight + y * imageWidth + x;
+ out_buf[i] = in_buf[offset];
+ i++;
+ out_buf[i] = in_buf[offset + 1];
+ i++;
+ }
+ }
+ }
+}
+
+jint JNICALL Java_com_android_camera_imageprocessor_FrameProcessor_nativeRotateNV21(
+ JNIEnv* env, jobject thiz, jobjectArray inBuf,
+ jint imageWidth, jint imageHeight, jint degree, jobjectArray outBuf)
+{
+ uint8_t *in_buf = (uint8_t *)env->GetDirectBufferAddress(inBuf);
+ uint8_t *out_buf = (uint8_t *)env->GetDirectBufferAddress(outBuf);
+ rotateBufAndMerge(in_buf, imageWidth, imageHeight, degree, out_buf);
+
+ return 0;
+}
+
+jint JNICALL Java_com_android_camera_imageprocessor_FrameProcessor_nativeNV21toRgb(
+ JNIEnv* env, jobject thiz, jobjectArray yvuBuf, jobjectArray rgbBuf, jint width, jint height)
+{
+ uint8_t *in_buf = (uint8_t *)env->GetDirectBufferAddress(yvuBuf);
+ uint8_t *rgb_buf = (uint8_t *)env->GetDirectBufferAddress(rgbBuf);
+ int ysize = width * height;
+ int y_value;
+ int i, v, u, r, g, b;
+ for(int x=0; x < width; x++) {
+ for(int y=0; y < height; y++) {
+ y_value = (in_buf[y*width+x] & 0xFF);
+ i = ysize + (x/2*2) + ((y/2) * width);
+ v = (in_buf[i] & 0xFF) - 128;
+ u = (in_buf[i + 1] & 0xFF) - 128;
+ r = (int)(1.164f * y_value + 1.596f * v);
+ g = (int)(1.164f * y_value - 0.813f * v - 0.391f * u);
+ b = (int)(1.164f * y_value + 2.018f * u);
+ r = r > 255 ? 255 : r < 0 ? 0 : r;
+ g = g > 255 ? 255 : g < 0 ? 0 : g;
+ b = b > 255 ? 255 : b < 0 ? 0 : b;
+ rgb_buf[(y*width + x) * 4 + 3] = (uint8_t)(0xFF);
+ rgb_buf[(y*width + x) * 4 + 2] = (uint8_t)(b & 0xFF);
+ rgb_buf[(y*width + x) * 4 + 1] = (uint8_t)(g & 0xFF);
+ rgb_buf[(y*width + x) * 4 + 0] = (uint8_t)(r & 0xFF);
+ }
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/proguard.flags b/proguard.flags
index 10fd77b6b..9d477262a 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -45,3 +45,15 @@
*** closeSilently(...);
}
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keep class * {
+ public <methods>;
+ public <fields>;
+ private <methods>;
+ private <fields>;
+}
+
+-keep class android.renderscript.** { *; }
diff --git a/res/layout/capture_module.xml b/res/layout/capture_module.xml
index a68af5e08..d91b49a97 100644
--- a/res/layout/capture_module.xml
+++ b/res/layout/capture_module.xml
@@ -36,7 +36,8 @@
<com.android.camera.ui.AutoFitSurfaceView
android:id="@+id/mdp_preview_content"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ android:layout_gravity="center" />
<com.android.camera.ui.AutoFitSurfaceView
android:id="@+id/mdp_preview_content2"
diff --git a/res/layout/video_module.xml b/res/layout/video_module.xml
index 20d7be1d2..2456caf82 100644
--- a/res/layout/video_module.xml
+++ b/res/layout/video_module.xml
@@ -70,8 +70,8 @@
<com.android.camera.PauseButton android:id="@+id/video_pause"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_marginLeft="70dp"
- android:padding="23dp"
+ android:layout_marginLeft="50dp"
+ android:padding="38dp"
android:src="@drawable/btn_pause_recording"/>
<include layout="@layout/viewfinder_labels_video"
android:id="@+id/labels" />
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index b9c04f290..a243e5fa6 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -30,6 +30,7 @@
<attr name="entryValues" format="reference" />
<attr name="entries" format="reference" />
<attr name="labelList" format="reference" />
+ <attr name="dependencyList" format="reference" />
</declare-styleable>
<declare-styleable name="IconIndicator">
<attr name="icons" format="reference" />
diff --git a/res/values/camera2arrays.xml b/res/values/camera2arrays.xml
new file mode 100644
index 000000000..49f37e139
--- /dev/null
+++ b/res/values/camera2arrays.xml
@@ -0,0 +1,574 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <string-array name="pref_camera2_camera2_entries" translatable="true">
+ <item>@string/pref_camera2_camera2_entry_disable</item>
+ <item>@string/pref_camera2_camera2_entry_enable</item>
+ </string-array>
+
+ <string-array name="pref_camera2_camera2_entryvalues" translatable="false">
+ <item>@string/pref_camera2_camera2_value_disable</item>
+ <item>@string/pref_camera2_camera2_value_enable</item>
+ </string-array>
+
+ <string-array name="pref_camera2_mono_only_entries" translatable="true">
+ <item>On</item>
+ <item>Off</item>
+ </string-array>
+
+ <string-array name="pref_camera2_mono_only_entryvalues" translatable="false">
+ <item>on</item>
+ <item>off</item>
+ </string-array>
+
+ <string-array name="pref_camera2_initial_camera_entries" translatable="true">
+ <item>Bayer</item>
+ <item>Mono</item>
+ <item>Front</item>
+ </string-array>
+
+ <string-array name="pref_camera2_initial_camera_entryvalues" translatable="false">
+ <item>bayer</item>
+ <item>mono</item>
+ <item>front</item>
+ </string-array>
+
+ <string-array name="pref_camera2_makeup_entries" translatable="true">
+ <item>On</item>
+ <item>Off</item>
+ </string-array>
+
+ <string-array name="pref_camera2_makeup_entryvalues" translatable="false">
+ <item>on</item>
+ <item>off</item>
+ </string-array>
+
+ <string-array name="pref_camera2_mono_preview_entries" translatable="true">
+ <item>@string/pref_camera2_mono_preview_entry_on</item>
+ <item>@string/pref_camera2_mono_preview_entry_off</item>
+ </string-array>
+
+ <string-array name="pref_camera2_mono_preview_entryvalues" translatable="false">
+ <item>@string/pref_camera2_mono_preview_value_on</item>
+ <item>@string/pref_camera2_mono_preview_value_off</item>
+ </string-array>
+
+ <string-array name="pref_camera2_clearsight_entries" translatable="true">
+ <item>@string/pref_camera2_clearsight_entry_off</item>
+ <item>@string/pref_camera2_clearsight_entry_on</item>
+ </string-array>
+
+ <string-array name="pref_camera2_clearsight_entryvalues" translatable="false">
+ <item>@string/pref_camera2_clearsight_value_off</item>
+ <item>@string/pref_camera2_clearsight_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)
+ 100 is for dual mode (Custom-Scenemodes start from 100)
+ -->
+ <string-array name="pref_camera2_scenemode_entryvalues" translatable="false">
+ <item>0</item>
+ <item>100</item>
+ <item>18</item>
+ <item>-1</item>
+ <item>101</item>
+ <item>3</item>
+ <item>4</item>
+ <item>13</item>
+ <item>-1</item>
+ <item>-1</item>
+ <item>15</item>
+ <item>10</item>
+ <item>5</item>
+ <item>8</item>
+ <item>9</item>
+ <item>-1</item>
+ </string-array>
+
+ <!-- Camera Preferences Scene Mode dialog box entries -->
+ <string-array name="pref_camera2_scenemode_entries" translatable="false">
+ <item>@string/pref_camera_scenemode_entry_auto</item>
+ <item>Dual</item>
+ <item>@string/pref_camera_scenemode_entry_hdr</item>
+ <item>@string/pref_camera_scenemode_entry_refocus</item>
+ <item>@string/pref_camera_scenemode_entry_optizoom</item>
+ <item>@string/pref_camera_scenemode_entry_portrait</item>
+ <item>@string/pref_camera_scenemode_entry_landscape</item>
+ <item>@string/pref_camera_scenemode_entry_sports</item>
+ <item>@string/pref_camera_scenemode_entry_flowers</item>
+ <item>@string/pref_camera_scenemode_entry_backlight</item>
+ <item>@string/pref_camera_scenemode_entry_candlelight</item>
+ <item>@string/pref_camera_scenemode_entry_sunset</item>
+ <item>@string/pref_camera_scenemode_entry_night</item>
+ <item>@string/pref_camera_scenemode_entry_beach</item>
+ <item>@string/pref_camera_scenemode_entry_snow</item>
+ <item>@string/pref_camera_scenemode_entry_asd</item>
+ </string-array>
+
+ <array name="pref_camera2_scenemode_thumbnails" translatable="false">
+ <item>@drawable/ic_scene_mode_auto</item>
+ <item>@drawable/ic_scene_mode_hdr</item>
+ <item>@drawable/ic_scene_mode_hdr</item>
+ <item>@drawable/ic_scene_mode_refocus</item>
+ <item>@drawable/ic_scene_mode_optizoom</item>
+ <item>@drawable/ic_scene_mode_portrait</item>
+ <item>@drawable/ic_scene_mode_landscape</item>
+ <item>@drawable/ic_scene_mode_sports</item>
+ <item>@drawable/ic_scene_mode_flower</item>
+ <item>@drawable/ic_scene_mode_backlight</item>
+ <item>@drawable/ic_scene_mode_candlelight</item>
+ <item>@drawable/ic_scene_mode_sunset</item>
+ <item>@drawable/ic_scene_mode_night</item>
+ <item>@drawable/ic_scene_mode_beach</item>
+ <item>@drawable/ic_scene_mode_snow</item>
+ <item>@drawable/ic_scene_mode_smartauto</item>
+ </array>
+
+ <string-array name="pref_camera2_whitebalance_entryvalues" translatable="false">
+ <item>1</item>
+ <item>2</item>
+ <item>4</item>
+ <item>5</item>
+ <item>6</item>
+ </string-array>
+
+ <!-- Camera Preferences White Balance dialog box entries -->
+ <string-array name="pref_camera2_whitebalance_entries" translatable="false">
+ <item>@string/pref_camera_whitebalance_entry_auto</item>
+ <item>@string/pref_camera_whitebalance_entry_incandescent</item>
+ <item>@string/pref_camera_whitebalance_entry_fluorescent</item>
+ <item>@string/pref_camera_whitebalance_entry_daylight</item>
+ <item>@string/pref_camera_whitebalance_entry_cloudy</item>
+ </string-array>
+
+ <string-array name="pref_camera2_whitebalance_labels" translatable="false">
+ <item>@string/pref_camera_whitebalance_label_auto</item>
+ <item>@string/pref_camera_whitebalance_label_incandescent</item>
+ <item>@string/pref_camera_whitebalance_label_fluorescent</item>
+ <item>@string/pref_camera_whitebalance_label_daylight</item>
+ <item>@string/pref_camera_whitebalance_label_cloudy</item>
+ </string-array>
+
+ <array name="pref_camera2_whitebalance_icons" translatable="false">
+ <item>@drawable/ic_wb_auto</item>
+ <item>@drawable/ic_wb_incandescent</item>
+ <item>@drawable/ic_wb_fluorescent</item>
+ <item>@drawable/ic_wb_sunlight</item>
+ <item>@drawable/ic_wb_cloudy</item>
+ </array>
+
+ <array name="pref_camera2_whitebalance_largeicons" translatable="false">
+ <item>@drawable/ic_wb_incandescent</item>
+ <item>@drawable/ic_wb_fluorescent</item>
+ <item>@drawable/ic_wb_auto</item>
+ <item>@drawable/ic_wb_sunlight</item>
+ <item>@drawable/ic_wb_cloudy</item>
+ </array>
+
+ <!-- Refer to CONTROL_EFFECT_MODE of Camera2 API for values
+ -1 refers to ones not supported in Camera2 API
+ -->
+ <string-array name="pref_camera2_coloreffect_entryvalues" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ <item>4</item>
+ <item>2</item>
+ <item>3</item>
+ <item>5</item>
+ <item>8</item>
+ <item>-1</item>
+ <item>-1</item>
+ <item>-1</item>
+ <item>-1</item>
+ <item>-1</item>
+ <item>-1</item>
+ <item>-1</item>
+ <item>-1</item>
+ </string-array>
+
+ <string-array name="pref_camera2_coloreffect_icons" translatable="false">
+ <item>@drawable/ic_settings_filter</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ </string-array>
+
+ <!-- Camera Preferences Color effect dialog box entries -->
+ <string-array name="pref_camera2_coloreffect_entries" translatable="false">
+ <item>@string/pref_camera_coloreffect_entry_none</item>
+ <item>@string/pref_camera_coloreffect_entry_mono</item>
+ <item>@string/pref_camera_coloreffect_entry_sepia</item>
+ <item>@string/pref_camera_coloreffect_entry_negative</item>
+ <item>@string/pref_camera_coloreffect_entry_solarize</item>
+ <item>@string/pref_camera_coloreffect_entry_posterize</item>
+ <item>@string/pref_camera_coloreffect_entry_aqua</item>
+ <item>@string/pref_camera_coloreffect_entry_emboss</item>
+ <item>@string/pref_camera_coloreffect_entry_sketch</item>
+ <item>@string/pref_camera_coloreffect_entry_neon</item>
+ <item>@string/pref_camera_coloreffect_entry_pastel</item>
+ <item>@string/pref_camera_coloreffect_entry_mosaic</item>
+ <item>@string/pref_camera_coloreffect_entry_redtint</item>
+ <item>@string/pref_camera_coloreffect_entry_bluetint</item>
+ <item>@string/pref_camera_coloreffect_entry_greentint</item>
+ </string-array>
+
+ <array name="pref_camera2_coloreffect_thumbnails" translatable="false">
+ <item>@drawable/thumb_filter_nofilter</item>
+ <item>@drawable/thumb_filter_monochrome</item>
+ <item>@drawable/thumb_filter_sepia</item>
+ <item>@drawable/thumb_filter_negative</item>
+ <item>@drawable/thumb_filter_solarize</item>
+ <item>@drawable/thumb_filter_posterize</item>
+ <item>@drawable/thumb_filter_aqua</item>
+ <item>@drawable/thumb_filter_emboss</item>
+ <item>@drawable/thumb_filter_sketch</item>
+ <item>@drawable/thumb_filter_neon</item>
+ <item>0</item>
+ <item>0</item>
+ <item>0</item>
+ <item>0</item>
+ <item>0</item>
+ </array>
+
+ <!-- Camera Preferences flash mode dialog box entries -->
+ <string-array name="pref_camera2_flashmode_entries" translatable="false">
+ <item>@string/pref_camera_flashmode_entry_off</item>
+ <item>@string/pref_camera_flashmode_entry_auto</item>
+ <item>@string/pref_camera_flashmode_entry_on</item>
+ </string-array>
+
+ <string-array name="pref_camera2_flashmode_labels" translatable="false">
+ <item>@string/pref_camera_flashmode_label_off</item>
+ <item>@string/pref_camera_flashmode_label_auto</item>
+ <item>@string/pref_camera_flashmode_label_on</item>
+ </string-array>
+
+ <string-array name="pref_camera2_flashmode_entryvalues" translatable="false">
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+
+ <array name="pref_camera2_flashmode_icons" translatable="false">
+ <item>@drawable/ic_flash_off_holo_light</item>
+ <item>@drawable/ic_flash_auto_holo_light</item>
+ <item>@drawable/ic_flash_on_holo_light</item>
+ </array>
+
+ <array name="pref_camera2_flashmode_largeicons" translatable="false">
+ <item>@drawable/ic_flash_off_holo_light</item>
+ <item>@drawable/ic_flash_auto_holo_light</item>
+ <item>@drawable/ic_flash_on_holo_light</item>
+ </array>
+
+ <!-- Camera Preference save path entries -->
+ <string-array name="pref_camera2_savepath_entries" translatable="false">
+ <item>@string/pref_camera_savepath_entry_0</item>
+ <item>@string/pref_camera_savepath_entry_1</item>
+ </string-array>
+
+ <string-array name="pref_camera2_savepath_entryvalues" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ </string-array>
+
+ <!-- Camera Preferences Picture size dialog box entries -->
+ <string-array name="pref_camera2_picturesize_entries" translatable="false">
+ <item>@string/pref_camera_picturesize_entry_24mp</item>
+ <item>@string/pref_camera_picturesize_entry_21mp</item>
+ <item>@string/pref_camera_picturesize_entry_16mp</item>
+ <item>@string/pref_camera_picturesize_entry_16mp_wide</item>
+ <item>@string/pref_camera_picturesize_entry_13mp</item>
+ <item>@string/pref_camera_picturesize_entry_12mp</item>
+ <item>@string/pref_camera_picturesize_entry_8mp</item>
+ <item>@string/pref_camera_picturesize_entry_8mp</item>
+ <item>@string/pref_camera_picturesize_entry_square</item>
+ <item>@string/pref_camera_picturesize_entry_5mp</item>
+ <item>@string/pref_camera_picturesize_entry_5mp</item>
+ <item>@string/pref_camera_picturesize_entry_5mp</item>
+ <item>@string/pref_camera_picturesize_entry_4mp_wide</item>
+ <item>@string/pref_camera_picturesize_entry_3mp</item>
+ <item>@string/pref_camera_picturesize_entry_3mp</item>
+ <item>@string/pref_camera_picturesize_entry_1920x1080</item>
+ <item>@string/pref_camera_picturesize_entry_2mp</item>
+ <item>@string/pref_camera_picturesize_entry_2mp_wide</item>
+ <item>@string/pref_camera_picturesize_entry_1_5mp</item>
+ <item>@string/pref_camera_picturesize_entry_1_3mp</item>
+ <item>@string/pref_camera_picturesize_entry_1280x768</item>
+ <item>@string/pref_camera_picturesize_entry_1280x720</item>
+ <item>@string/pref_camera_picturesize_entry_1mp</item>
+ <item>@string/pref_camera_picturesize_entry_800x600</item>
+ <item>@string/pref_camera_picturesize_entry_800x480</item>
+ <item>@string/pref_camera_picturesize_entry_960x720</item>
+ <item>@string/pref_camera_picturesize_entry_720x480</item>
+ <item>@string/pref_camera_picturesize_entry_vga</item>
+ <item>@string/pref_camera_picturesize_entry_352x288</item>
+ <item>@string/pref_camera_picturesize_entry_qvga</item>
+ <item>@string/pref_camera_picturesize_entry_176x144</item>
+ </string-array>
+ <!-- When launching the camera app first time, we will set the picture
+ size to the first one in the list that is also supported by the
+ driver -->
+ <string-array name="pref_camera2_picturesize_entryvalues" translatable="false">
+ <item>5656x4242</item>
+ <item>5344x4008</item>
+ <item>4608x3456</item>
+ <item>5312x2988</item>
+ <item>4160x3120</item>
+ <item>4000x3000</item>
+ <item>3840x2160</item>
+ <item>3264x2448</item>
+ <item>2976x2976</item>
+ <item>2592x1944</item>
+ <item>2592x1936</item>
+ <item>2560x1920</item>
+ <item>2688x1512</item>
+ <item>2048x1536</item>
+ <item>2048x1520</item>
+ <item>1920x1080</item>
+ <item>1600x1200</item>
+ <item>1920x1088</item>
+ <item>1440x1080</item>
+ <item>1280x960</item>
+ <item>1280x768</item>
+ <item>1280x720</item>
+ <item>1024x768</item>
+ <item>800x600</item>
+ <item>800x480</item>
+ <item>960x720</item>
+ <item>720x480</item>
+ <item>640x480</item>
+ <item>352x288</item>
+ <item>320x240</item>
+ <item>176x144</item>
+ </string-array>
+
+ <!-- Camera Preferences focus mode dialog box entries -->
+ <string-array name="pref_camera2_focusmode_entries" translatable="false">
+ <item>@string/pref_camera_focusmode_entry_auto</item>
+ <item>@string/pref_camera_focusmode_entry_infinity</item>
+ <item>@string/pref_camera_focusmode_entry_macro</item>
+ <item>@string/pref_camera_focusmode_entry_normal</item>
+ <item>@string/pref_camera_focusmode_entry_continuous</item>
+ </string-array>
+
+ <string-array name="pref_camera2_focusmode_entryvalues" translatable="false">
+ <item>auto</item>
+ <item>infinity</item>
+ <item>macro</item>
+ <item>normal</item>
+ <item>continuous-picture</item>
+ </string-array>
+
+ <string-array name="pref_camera2_focusmode_labels" translatable="false">
+ <item>@string/pref_camera_focusmode_label_auto</item>
+ <item>@string/pref_camera_focusmode_label_infinity</item>
+ <item>@string/pref_camera_focusmode_label_macro</item>
+ </string-array>
+
+ <string-array name="pref_camera2_recordlocation_entryvalues" translatable="false">
+ <item>off</item>
+ <item>on</item>
+ </string-array>
+
+ <array name="pref_camera2_recordlocation_entries" translatable="false">
+ <item>@string/setting_off</item>
+ <item>@string/setting_on</item>
+ </array>
+
+ <array name="pref_camera2_recordlocation_labels" translatable="false">
+ <item>@string/pref_camera_location_label</item>
+ <item>@string/pref_camera_location_label</item>
+ </array>
+
+ <array name="pref_camera2_recordlocation_icons" translatable="false">
+ <item>@drawable/ic_location_off</item>
+ <item>@drawable/ic_location</item>
+ </array>
+
+ <array name="pref_camera2_recordlocation_largeicons" translatable="false">
+ <item>@drawable/ic_location_off</item>
+ <item>@drawable/ic_location</item>
+ </array>
+
+ <array name="pref_camera2_id_entries" translatable="false">
+ <item>@string/pref_camera_id_entry_back</item>
+ <item>@string/pref_camera_id_entry_front</item>
+ </array>
+
+ <array name="pref_camera2_id_labels" translatable="false">
+ <item>@string/pref_camera_id_label_back</item>
+ <item>@string/pref_camera_id_label_front</item>
+ </array>
+
+ <array name="pref_camera2_id_icons" translatable="false">
+ <item>@drawable/ic_switch_back</item>
+ <item>@drawable/ic_switch_front</item>
+ </array>
+
+ <array name="pref_camera2_id_largeicons" translatable="false">
+ <item>@drawable/ic_switch_back</item>
+ <item>@drawable/ic_switch_front</item>
+ </array>
+
+ <string-array name="pref_camera2_timer_sound_entries" translatable="false">
+ <item>@string/setting_off</item>
+ <item>@string/setting_on</item>
+ </string-array>
+
+ <string-array name="pref_camera2_timer_sound_entryvalues" translatable="false">
+ <item>@string/setting_off_value</item>
+ <item>@string/setting_on_value</item>
+ </string-array>
+
+ <!-- Icons for exposure compensation -->
+ <array name="pref_camera2_exposure_icons" translatable="false">
+ <item>@drawable/ic_exposure_n3</item>
+ <item>@drawable/ic_exposure_n2</item>
+ <item>@drawable/ic_exposure_n1</item>
+ <item>@drawable/ic_exposure_0</item>
+ <item>@drawable/ic_exposure_p1</item>
+ <item>@drawable/ic_exposure_p2</item>
+ <item>@drawable/ic_exposure_p3</item>
+ </array>
+
+ <!-- Labels for Countdown timer -->
+ <string-array name="pref_camera2_countdown_labels">
+ <item>@string/pref_camera_countdown_label_off</item>
+ <item>@string/pref_camera_countdown_label_one</item>
+ <item>@string/pref_camera_countdown_label_three</item>
+ <item>@string/pref_camera_countdown_label_ten</item>
+ <item>@string/pref_camera_countdown_label_fifteen</item>
+ </string-array>
+
+ <!-- Camera Preferences JPEG quality dialog box entries -->
+ <string-array name="pref_camera2_jpegquality_entries" translatable="false">
+ <item>@string/pref_camera_jpegquality_entry_0</item>
+ <item>@string/pref_camera_jpegquality_entry_1</item>
+ <item>@string/pref_camera_jpegquality_entry_2</item>
+ </string-array>
+
+ <string-array name="pref_camera2_jpegquality_entryvalues" translatable="false">
+ <item>55</item>
+ <item>85</item>
+ <item>100</item>
+ </string-array>
+
+ <!-- Rough estimates of jpeg compression ratio corresponding to qualities defined above. -->
+ <integer-array name="pref_camera2_jpegquality_compression_ratio">
+ <item>48</item>
+ <item>20</item>
+ <item>6</item>
+ </integer-array>
+
+ <!-- Camera Preferences ISO dialog box entries -->
+ <string-array name="pref_camera2_iso_entries">
+ <item>@string/pref_camera_iso_entry_auto</item>
+ <item>@string/pref_camera_iso_entry_iso100</item>
+ <item>@string/pref_camera_iso_entry_iso200</item>
+ <item>@string/pref_camera_iso_entry_iso400</item>
+ <item>@string/pref_camera_iso_entry_iso800</item>
+ <item>@string/pref_camera_iso_entry_iso1600</item>
+ </string-array>
+
+ <!-- Do not localize entryvalues -->
+ <string-array name="pref_camera2_iso_entryvalues">
+ <item>auto</item>
+ <item>100</item>
+ <item>200</item>
+ <item>400</item>
+ <item>800</item>
+ <item>1600</item>
+ </string-array>
+
+ <!-- Camera Preferences Auto Exposure dialog box entries -->
+ <string-array name="pref_camera2_autoexposure_entries">
+ <item>@string/pref_camera_autoexposure_entry_frameaverage</item>
+ <item>@string/pref_camera_autoexposure_entry_centerweighted</item>
+ <item>@string/pref_camera_autoexposure_entry_spotmetering</item>
+ </string-array>
+
+ <!-- Do not localize entryvalues -->
+ <string-array name="pref_camera2_autoexposure_entryvalues">
+ <item>@string/pref_camera_autoexposure_value_frameaverage</item>
+ <item>@string/pref_camera_autoexposure_value_centerweighted</item>
+ <item>@string/pref_camera_autoexposure_value_spotmetering</item>
+ </string-array>
+
+ <!-- Camera Preferences Redeye Reduction dialog box entries -->
+ <string-array name="pref_camera2_redeyereduction_entries" translatable="false">
+ <item>@string/pref_camera_redeyereduction_entry_disable</item>
+ <item>@string/pref_camera_redeyereduction_entry_enable</item>
+ </string-array>
+
+ <string-array name="pref_camera2_redeyereduction_entryvalues" translatable="false">
+ <item>disable</item>
+ <item>enable</item>
+ </string-array>
+
+ <!-- Camera Preferences Long Shot dialog box entries -->
+ <string-array name="pref_camera2_longshot_entries" translatable="false">
+ <item>@string/setting_off</item>
+ <item>@string/setting_on</item>
+ </string-array>
+
+ <string-array name="pref_camera2_longshot_entryvalues" translatable="false">
+ <item>@string/setting_off_value</item>
+ <item>@string/setting_on_value</item>
+ </string-array>
+
+ <string-array name="pref_camera2_filter_mode_entries" translatable="false">
+ <item>@string/pref_camera_filter_mode_entry_off</item>
+ <item>@string/pref_camera_filter_mode_entry_on</item>
+ </string-array>
+ <string-array name="pref_camera2_filter_mode_entryvalues" translatable="false">
+ <item>Off</item>
+ <item>On</item>
+ </string-array>
+
+ <string-array name="pref_camera2_filter_mode_icons" translatable="false">
+ <item>@drawable/ic_settings_filter</item>
+ <item>@drawable/ic_settings_filter_on</item>
+ </string-array>
+
+</resources>
diff --git a/res/values/qcomarrays.xml b/res/values/qcomarrays.xml
index d3218bdaf..7574992b9 100644
--- a/res/values/qcomarrays.xml
+++ b/res/values/qcomarrays.xml
@@ -833,55 +833,15 @@
</string-array>
<string-array name="pref_camera_instant_capture_entries" translatable="true">
- <item>@string/pref_camera_instant_capture_entry_enable</item>
+ <item>@string/pref_camera_instant_capture_entry_aggressive_aec</item>
+ <item>@string/pref_camera_instant_capture_entry_fast_aec</item>
<item>@string/pref_camera_instant_capture_entry_disable</item>
</string-array>
<string-array name="pref_camera_instant_capture_entry_values" translatable="false">
- <item>@string/pref_camera_instant_capture_value_enable</item>
+ <item>@string/pref_camera_instant_capture_value_aggressive_aec</item>
+ <item>@string/pref_camera_instant_capture_value_fast_aec</item>
<item>@string/pref_camera_instant_capture_value_disable</item>
</string-array>
-
- <string-array name="pref_camera_camera2_entries" translatable="true">
- <item>@string/pref_camera_camera2_entry_enable</item>
- <item>@string/pref_camera_camera2_entry_disable</item>
- </string-array>
-
- <string-array name="pref_camera_camera2_entryvalues" translatable="false">
- <item>@string/pref_camera_camera2_value_enable</item>
- <item>@string/pref_camera_camera2_value_disable</item>
- </string-array>
-
- <string-array name="pref_camera_dual_camera_entries" translatable="true">
- <item>@string/pref_camera_dual_camera_entry_dual</item>
- <item>@string/pref_camera_dual_camera_entry_bayer</item>
- <item>@string/pref_camera_dual_camera_entry_mono</item>
- </string-array>
-
- <string-array name="pref_camera_dual_camera_entryvalues" translatable="false">
- <item>@string/pref_camera_dual_camera_value_dual</item>
- <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>
-
- <string-array name="pref_camera_clearsight_entries" translatable="true">
- <item>@string/pref_camera_clearsight_entry_on</item>
- <item>@string/pref_camera_clearsight_entry_off</item>
- </string-array>
-
- <string-array name="pref_camera_clearsight_entryvalues" translatable="false">
- <item>@string/pref_camera_clearsight_value_on</item>
- <item>@string/pref_camera_clearsight_value_off</item>
- </string-array>
</resources>
diff --git a/res/values/qcomstrings.xml b/res/values/qcomstrings.xml
index ea90cf72a..a808ba354 100644
--- a/res/values/qcomstrings.xml
+++ b/res/values/qcomstrings.xml
@@ -202,12 +202,14 @@
<!-- Instant Capture entry -->
<string name="pref_camera_instant_capture_title" translatable="true">Instant Capture</string>
- <string name="pref_camera_instant_capture_entry_enable" translatable="true">Enable</string>
+ <string name="pref_camera_instant_capture_entry_aggressive_aec" translatable="true">Aggressive AEC</string>
+ <string name="pref_camera_instant_capture_entry_fast_aec" translatable="true">Fast AEC</string>
<string name="pref_camera_instant_capture_entry_disable" translatable="true">Disable</string>
<!-- Instant Capture entry values -->
<string name="pref_camera_instant_capture_default" translatable="false">0</string>
- <string name="pref_camera_instant_capture_value_enable" translatable="false">1</string>
+ <string name="pref_camera_instant_capture_value_aggressive_aec" translatable="false">1</string>
+ <string name="pref_camera_instant_capture_value_fast_aec" translatable="false">2</string>
<string name="pref_camera_instant_capture_value_disable" translatable="false">0</string>
<!-- Settings screen, ZSL location dialog choices -->
@@ -773,6 +775,8 @@
<string name="pref_camera_picturesize_entry_1280x720">HD720</string>
<string name="pref_camera_picturesize_entry_800x600">SVGA</string>
<string name="pref_camera_picturesize_entry_800x480">WVGA</string>
+ <string name="pref_camera_picturesize_entry_960x720">960 x 720</string>
+ <string name="pref_camera_picturesize_entry_720x480">720 x 480</string>
<string name="pref_camera_picturesize_entry_352x288">CIF</string>
<string name="pref_camera_picturesize_entry_176x144">QCIF</string>
@@ -945,41 +949,38 @@
<string name="help_menu_switcher_2" translatable="true">between</string>
<string name="help_menu_switcher_3" translatable="true">camera, video, and panorama</string>
- <string name="pref_camera_camera2_title">Camera2 Mode</string>
- <string name="pref_camera_camera2_default">disable</string>
- <string name="pref_camera_camera2_entry_enable">Enable</string>
- <string name="pref_camera_camera2_entry_disable">Disable</string>
+ <string name="pref_camera2_camera2_title" translatable="true">Camera2 Mode</string>
+ <string name="pref_camera2_camera2_entry_enable" translatable="true">Enable</string>
+ <string name="pref_camera2_camera2_entry_disable" translatable="true">Disable</string>
+ <string name="pref_camera2_camera2_default" translatable="false">disable</string>
+ <string name="pref_camera2_camera2_value_enable" translatable="false">enable</string>
+ <string name="pref_camera2_camera2_value_disable" translatable="false">disable</string>
- <string name="pref_camera_camera2_value_enable">enable</string>
- <string name="pref_camera_camera2_value_disable">disable</string>
+ <string name="pref_camera2_mono_only_title" translatable="true">Mono Only</string>
+ <string name="pref_camera2_mono_only_default" translatable="false">off</string>
- <string name="pref_camera_dual_camera_title">Dual Camera Mode</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>
+ <string name="pref_camera2_mono_preview_title" translatable="true">Mono Preview</string>
+ <string name="pref_camera2_mono_preview_entry_on" translatable="true">On</string>
+ <string name="pref_camera2_mono_preview_entry_off" translatable="true">Off</string>
+ <string name="pref_camera2_mono_preview_default" translatable="false">off</string>
+ <string name="pref_camera2_mono_preview_value_on" translatable="false">on</string>
+ <string name="pref_camera2_mono_preview_value_off" translatable="false">off</string>
- <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_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_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>
-
- <string name="pref_camera_clearsight_title">ClearSight</string>
- <string name="pref_camera_clearsight_default" translatable="false">off</string>
- <string name="pref_camera_clearsight_entry_on">On</string>
- <string name="pref_camera_clearsight_entry_off">Off</string>
-
- <string name="pref_camera_clearsight_value_on" translatable="false">on</string>
- <string name="pref_camera_clearsight_value_off" translatable="false">off</string>
+ <string name="pref_camera2_clearsight_value_on" translatable="false">on</string>
+ <string name="pref_camera2_clearsight_value_off" translatable="false">off</string>
<string name="clearsight_capture_success">ClearSight capture successful</string>
<string name="clearsight_capture_fail">ClearSight capture failed</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>
+ <string name="pref_camera2_flashmode_default" translatable="false">2</string>
+ <string name="pref_camera2_makeup_title" translatable="true">Makeup</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index bb13cc5c8..4a7284874 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -129,7 +129,7 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:singleLine">true</item>
- <item name="android:layout_marginTop">23dp</item>
+ <item name="android:layout_marginTop">38dp</item>
<item name="android:paddingLeft">15dp</item>
<item name="android:paddingRight">15dp</item>
<item name="android:paddingTop">3dp</item>
diff --git a/res/xml/camera_preferences.xml b/res/xml/camera_preferences.xml
index 5fafb855b..7e024b298 100644
--- a/res/xml/camera_preferences.xml
+++ b/res/xml/camera_preferences.xml
@@ -367,31 +367,9 @@
camera:entryValues="@array/pref_camera_instant_capture_entry_values" />
<ListPreference
- camera:key="pref_camera_camera2_key"
- camera:defaultValue="@string/pref_camera_camera2_default"
- camera:title="@string/pref_camera_camera2_title"
- camera:entries="@array/pref_camera_camera2_entries"
- camera:entryValues="@array/pref_camera_camera2_entryvalues" />
-
- <ListPreference
- camera:key="pref_camera_dual_camera_key"
- camera:defaultValue="@string/pref_camera_dual_camera_default"
- 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:defaultValue="@string/pref_camera_mono_preview_default"
- camera:entries="@array/pref_camera_mono_preview_entries"
- camera:entryValues="@array/pref_camera_mono_preview_entryvalues"
- camera:key="pref_camera_mono_preview_key"
- camera:title="@string/pref_camera_mono_preview_title" />
-
- <ListPreference
- camera:defaultValue="@string/pref_camera_clearsight_default"
- camera:entries="@array/pref_camera_clearsight_entries"
- camera:entryValues="@array/pref_camera_clearsight_entryvalues"
- camera:key="pref_camera_clearsight_key"
- camera:title="@string/pref_camera_clearsight_title" />
-
+ camera:key="pref_camera2_camera2_key"
+ camera:defaultValue="@string/pref_camera2_camera2_default"
+ camera:title="@string/pref_camera2_camera2_title"
+ camera:entries="@array/pref_camera2_camera2_entries"
+ camera:entryValues="@array/pref_camera2_camera2_entryvalues" />
</PreferenceGroup>
diff --git a/res/xml/capture_preferences.xml b/res/xml/capture_preferences.xml
new file mode 100644
index 000000000..5e9235e34
--- /dev/null
+++ b/res/xml/capture_preferences.xml
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceGroup
+ xmlns:camera="http://schemas.android.com/apk/res/org.codeaurora.snapcam"
+ camera:title="@string/pref_camera_settings_category">
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera2_flashmode_default"
+ camera:entries="@array/pref_camera2_flashmode_entries"
+ camera:entryValues="@array/pref_camera2_flashmode_entryvalues"
+ camera:icons="@array/pref_camera2_flashmode_icons"
+ camera:key="pref_camera2_flashmode_key"
+ camera:labelList="@array/pref_camera2_flashmode_labels"
+ camera:largeIcons="@array/pref_camera2_flashmode_largeicons"
+ camera:singleIcon="@drawable/ic_settings_flash"
+ camera:title="@string/pref_camera_flashmode_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera2_whitebalance_default"
+ camera:entries="@array/pref_camera2_whitebalance_entries"
+ camera:entryValues="@array/pref_camera2_whitebalance_entryvalues"
+ camera:icons="@array/pref_camera2_whitebalance_icons"
+ camera:key="pref_camera2_whitebalance_key"
+ camera:labelList="@array/pref_camera2_whitebalance_labels"
+ camera:largeIcons="@array/pref_camera2_whitebalance_largeicons"
+ camera:singleIcon="@drawable/ic_settings_lightsource"
+ camera:title="@string/pref_camera_whitebalance_title"/>
+
+ <RecordLocationPreference
+ camera:defaultValue="@string/pref_camera_recordlocation_default"
+ camera:entries="@array/pref_camera2_recordlocation_entries"
+ camera:entryValues="@array/pref_camera2_recordlocation_entryvalues"
+ camera:icons="@array/pref_camera2_recordlocation_icons"
+ camera:key="pref_camera2_recordlocation_key"
+ camera:labelList="@array/pref_camera2_recordlocation_labels"
+ camera:largeIcons="@array/pref_camera2_recordlocation_largeicons"
+ camera:singleIcon="@drawable/ic_settings_location"
+ camera:title="@string/pref_camera_recordlocation_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera_jpegquality_default"
+ camera:entries="@array/pref_camera2_jpegquality_entries"
+ camera:entryValues="@array/pref_camera2_jpegquality_entryvalues"
+ camera:key="pref_camera2_jpegquality_key"
+ camera:singleIcon="@drawable/ic_settings_quality"
+ camera:title="@string/pref_camera_jpegquality_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera_savepath_default"
+ camera:entries="@array/pref_camera2_savepath_entries"
+ camera:entryValues="@array/pref_camera2_savepath_entryvalues"
+ camera:key="pref_camera2_savepath_key"
+ camera:singleIcon="@drawable/ic_settings_storage"
+ camera:title="@string/pref_camera_savepath_title"/>
+
+ <ListPreference
+ camera:defaultValue="@string/pref_camera2_camera2_default"
+ camera:entries="@array/pref_camera2_camera2_entries"
+ camera:entryValues="@array/pref_camera2_camera2_entryvalues"
+ camera:key="pref_camera2_camera2_key"
+ camera:title="@string/pref_camera2_camera2_title"/>
+
+ <ListPreference
+ camera:defaultValue="@string/pref_camera2_mono_only_default"
+ camera:entries="@array/pref_camera2_mono_only_entries"
+ camera:entryValues="@array/pref_camera2_mono_only_entryvalues"
+ camera:key="pref_camera2_mono_only_key"
+ camera:title="@string/pref_camera2_mono_only_title"/>
+
+ <ListPreference
+ camera:defaultValue="@string/pref_camera2_mono_preview_default"
+ camera:entries="@array/pref_camera2_mono_preview_entries"
+ camera:entryValues="@array/pref_camera2_mono_preview_entryvalues"
+ camera:key="pref_camera2_mono_preview_key"
+ camera:title="@string/pref_camera2_mono_preview_title"/>
+
+ <ListPreference
+ camera:defaultValue="@string/pref_camera2_clearsight_default"
+ camera:entries="@array/pref_camera2_clearsight_entries"
+ camera:entryValues="@array/pref_camera2_clearsight_entryvalues"
+ camera:key="pref_camera2_clearsight_key"
+ camera:title="@string/pref_camera2_clearsight_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera2_coloreffect_default"
+ camera:entries="@array/pref_camera2_coloreffect_entries"
+ camera:entryValues="@array/pref_camera2_coloreffect_entryvalues"
+ camera:key="pref_camera2_coloreffect_key"
+ camera:largeIcons="@array/pref_camera2_coloreffect_icons"
+ camera:singleIcon="@drawable/ic_settings_filter"
+ camera:thumbnails="@array/pref_camera2_coloreffect_thumbnails"
+ camera:title="@string/pref_camera_coloreffect_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera2_scenemode_default"
+ camera:entries="@array/pref_camera2_scenemode_entries"
+ camera:entryValues="@array/pref_camera2_scenemode_entryvalues"
+ camera:key="pref_camera2_scenemode_key"
+ camera:singleIcon="@drawable/ic_settings_scenemode"
+ camera:thumbnails="@array/pref_camera2_scenemode_thumbnails"
+ camera:title="@string/pref_camera_scenemode_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera_redeyereduction_default"
+ camera:entries="@array/pref_camera2_redeyereduction_entries"
+ camera:entryValues="@array/pref_camera2_redeyereduction_entryvalues"
+ camera:key="pref_camera2_redeyereduction_key"
+ camera:singleIcon="@drawable/ic_settings_redeye"
+ camera:title="@string/pref_camera_redeyereduction_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera_id_default"
+ camera:entries="@array/pref_camera2_id_entries"
+ camera:icons="@array/pref_camera2_id_icons"
+ camera:key="pref_camera2_id_key"
+ camera:labelList="@array/pref_camera2_id_labels"
+ camera:largeIcons="@array/pref_camera2_id_largeicons"
+ camera:title="@string/pref_camera_id_title"/>
+
+ <IconListPreference
+ camera:entries="@array/pref_camera2_picturesize_entries"
+ camera:entryValues="@array/pref_camera2_picturesize_entryvalues"
+ camera:key="pref_camera2_picturesize_key"
+ camera:singleIcon="@drawable/ic_settings_picturesize"
+ camera:title="@string/pref_camera_picturesize_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_exposure_default"
+ camera:key="pref_camera2_exposure_key"
+ camera:singleIcon="@drawable/ic_settings_exposure"
+ camera:title="@string/pref_exposure_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera_iso_default"
+ camera:entries="@array/pref_camera2_iso_entries"
+ camera:entryValues="@array/pref_camera2_iso_entryvalues"
+ camera:key="pref_camera2_iso_key"
+ camera:singleIcon="@drawable/ic_settings_iso"
+ camera:title="@string/pref_camera_iso_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera_longshot_default"
+ camera:entries="@array/pref_camera2_longshot_entries"
+ camera:entryValues="@array/pref_camera2_longshot_entryvalues"
+ camera:key="pref_camera2_longshot_key"
+ camera:singleIcon="@drawable/ic_settings_continuous"
+ camera:title="@string/pref_camera_longshot_title"/>
+
+ <CountDownTimerPreference
+ camera:defaultValue="@string/pref_camera_timer_default"
+ camera:key="pref_camera2_timer_key"
+ camera:singleIcon="@drawable/ic_settings_countdowntimer"
+ camera:title="@string/pref_camera_timer_title"/>
+
+ <ListPreference
+ camera:defaultValue="0"
+ camera:key="pref_camera2_initial_camera_key"
+ camera:entries="@array/pref_camera2_initial_camera_entries"
+ camera:entryValues="@array/pref_camera2_initial_camera_entryvalues"/>
+
+ <ListPreference
+ camera:defaultValue="off"
+ camera:key="pref_camera2_makeup_key"
+ camera:entries="@array/pref_camera2_makeup_entries"
+ camera:entryValues="@array/pref_camera2_makeup_entryvalues"
+ camera:title="@string/pref_camera2_makeup_title"/>
+</PreferenceGroup>
diff --git a/rs/YuvToRgb.rs b/rs/YuvToRgb.rs
new file mode 100644
index 000000000..25771c5c7
--- /dev/null
+++ b/rs/YuvToRgb.rs
@@ -0,0 +1,58 @@
+/*
+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.
+*/
+#pragma version(1)
+#pragma rs java_package_name(com.android.camera.imageprocessor)
+#pragma rs_fp_relaxed
+
+rs_allocation gIn;
+uint32_t width;
+uint32_t height;
+
+uchar4 __attribute__((kernel)) nv21ToRgb(uint32_t x, uint32_t y) {
+ uint32_t ySize = width*height;
+ uint32_t index = ySize + (x/2*2) + ((y/2) * width);
+ int yV = (int)(rsGetElementAt_uchar(gIn, x + y*width) & 0xFF);
+ int vV = (int)(rsGetElementAt_uchar(gIn, index) & 0xFF ) -128;
+ int uV = (int)(rsGetElementAt_uchar(gIn, index+1) & 0xFF ) -128;
+
+ int r = (int) (1.164f * yV + 1.596f * vV );
+ int g = (int) (1.164f * yV - 0.813f * vV - 0.391f * uV);
+ int b = (int) (1.164f * yV + 2.018f * uV );
+
+ r = r>255? 255 : r<0 ? 0 : r;
+ g = g>255? 255 : g<0 ? 0 : g;
+ b = b>255? 255 : b<0 ? 0 : b;
+ uchar4 res4;
+ res4.r = (uchar)(r & 0xFF);
+ res4.g = (uchar)(g & 0xFF);
+ res4.b = (uchar)(b & 0xFF);
+ res4.a = 0xFF;
+
+ return res4;
+} \ No newline at end of file
diff --git a/rs/rotator.rs b/rs/rotator.rs
new file mode 100644
index 000000000..cd9da4396
--- /dev/null
+++ b/rs/rotator.rs
@@ -0,0 +1,51 @@
+/*
+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.
+*/
+#pragma version(1)
+#pragma rs java_package_name(com.android.camera.imageprocessor)
+#pragma rs_fp_relaxed
+
+rs_allocation gOut;
+rs_allocation gIn;
+uint32_t width;
+uint32_t height;
+
+uchar __attribute__((kernel)) rotate90andMerge(uint32_t x, uint32_t y) {
+ uchar yValue = rsGetElementAt_uchar(gIn, x + y*width);
+ rsSetElementAt_uchar(gOut, yValue, x*height + height - 1 - y);
+
+ if(x%2 == 0 && y%2==1) {
+ uint32_t ySize = width*height;
+ uint32_t index = ySize + x + ((y/2) * width);
+ uchar vValue = rsGetElementAt_uchar(gIn, index);
+ uchar uValue = rsGetElementAt_uchar(gIn, index + 1);
+ rsSetElementAt_uchar(gOut, vValue, ySize + x/2*height + height - 1 - y);
+ rsSetElementAt_uchar(gOut, uValue, ySize + x/2*height + height - 1 - y - 1);
+ }
+ return (uchar)0;
+} \ No newline at end of file
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index f6e832e45..74bcf5d3d 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -161,8 +161,6 @@ public class CameraActivity extends Activity
/** Whether onResume should reset the view to the preview. */
private boolean mResetToPreviewOnResume = true;
- public static boolean CAMERA_2_ON = false;
-
// Supported operations at FilmStripView. Different data has different
// set of supported operations.
private static final int SUPPORT_DELETE = 1 << 0;
@@ -243,6 +241,7 @@ public class CameraActivity extends Activity
public static int SETTING_LIST_WIDTH_2 = 250;
private ImageView mThumbnail;
+ private UpdateThumbnailTask mUpdateThumbnailTask;
private CircularDrawable mThumbnailDrawable;
// FilmStripView.setDataAdapter fires 2 onDataLoaded calls before any data is actually loaded
// Keep track of data request here to avoid creating useless UpdateThumbnailTask.
@@ -708,7 +707,9 @@ public class CameraActivity extends Activity
}
public void updateThumbnail(final byte[] jpegData) {
- (new UpdateThumbnailTask(jpegData, false)).execute();
+ if (mUpdateThumbnailTask != null) mUpdateThumbnailTask.cancel(true);
+ mUpdateThumbnailTask = new UpdateThumbnailTask(jpegData, false);
+ mUpdateThumbnailTask.execute();
}
public void updateThumbnail(final Bitmap bitmap) {
@@ -1417,6 +1418,8 @@ public class CameraActivity extends Activity
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
+ SettingsManager.createInstance(this);
+
LayoutInflater inflater = getLayoutInflater();
View rootLayout = inflater.inflate(R.layout.camera, null, false);
mCameraRootFrame = (FrameLayout)rootLayout.findViewById(R.id.camera_root_frame);
@@ -1451,16 +1454,15 @@ public class CameraActivity extends Activity
moduleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
}
}
- SharedPreferences pref = PreferenceManager
- .getDefaultSharedPreferences(this);
- CAMERA_2_ON = pref.getBoolean(CameraSettings.KEY_CAMERA2, false);
- if (CAMERA_2_ON && moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX)
+
+ boolean cam2on = SettingsManager.getInstance().isCamera2On();
+ if (cam2on && moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX)
moduleIndex = ModuleSwitcher.CAPTURE_MODULE_INDEX;
mOrientationListener = new MyOrientationEventListener(this);
- setModuleFromIndex(moduleIndex);
-
setContentView(R.layout.camera_filmstrip);
+ mFilmStripView = (FilmStripView) findViewById(R.id.filmstrip_view);
+ setModuleFromIndex(moduleIndex);
mActionBar = getActionBar();
mActionBar.addOnMenuVisibilityListener(this);
@@ -1490,7 +1492,7 @@ public class CameraActivity extends Activity
new CameraDataAdapter(new ColorDrawable(
getResources().getColor(R.color.photo_placeholder))),
mCameraPreviewData);
- mFilmStripView = (FilmStripView) findViewById(R.id.filmstrip_view);
+
mFilmStripView.setViewGap(
getResources().getDimensionPixelSize(R.dimen.camera_film_strip_gap));
mPanoramaViewHelper = new PanoramaViewHelper(this);
@@ -1864,7 +1866,9 @@ public class CameraActivity extends Activity
@Override
public void onModuleSelected(int moduleIndex) {
- if (moduleIndex == 0 && CAMERA_2_ON) moduleIndex = ModuleSwitcher.CAPTURE_MODULE_INDEX;
+ boolean cam2on = SettingsManager.getInstance().isCamera2On();
+ if (cam2on && moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX)
+ moduleIndex = ModuleSwitcher.CAPTURE_MODULE_INDEX;
if (mCurrentModuleIndex == moduleIndex) {
if (mCurrentModuleIndex != ModuleSwitcher.CAPTURE_MODULE_INDEX) {
return;
@@ -1932,6 +1936,8 @@ public class CameraActivity extends Activity
if(mCaptureModule == null) {
mCaptureModule = new CaptureModule();
mCaptureModule.init(this, mCameraCaptureModuleRootView);
+ } else {
+ mCaptureModule.reinit();
}
mCurrentModule = mCaptureModule;
mCameraCaptureModuleRootView.setVisibility(View.VISIBLE);
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 4393c6225..7a1cf8d74 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -167,6 +167,7 @@ public class CameraSettings {
public static final String KEY_QC_SEE_MORE_MODE = "see-more";
public static final String KEY_QC_NOISE_REDUCTION_MODE = "noise-reduction-mode";
public static final String KEY_QC_INSTANT_CAPTURE = "instant-capture";
+ public static final String KEY_QC_INSTANT_CAPTURE_VALUES = "instant-capture-values";
public static final String KEY_INTERNAL_PREVIEW_RESTART = "internal-restart";
public static final String KEY_QC_ZSL_HDR_SUPPORTED = "zsl-hdr-supported";
@@ -246,11 +247,6 @@ public class CameraSettings {
public static final String KEY_TS_MAKEUP_LEVEL_WHITEN = "pref_camera_tsmakeup_whiten";
public static final String KEY_TS_MAKEUP_LEVEL_CLEAN = "pref_camera_tsmakeup_clean";
- 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_CLEARSIGHT = "pref_camera_clearsight_key";
-
public static final String KEY_REFOCUS_PROMPT = "refocus-prompt";
public static final String KEY_SHOW_MENU_HELP = "help_menu";
@@ -284,7 +280,13 @@ public class CameraSettings {
//video encoders
VIDEO_ENCODER_TABLE.put(MediaRecorder.VideoEncoder.H263, "h263");
VIDEO_ENCODER_TABLE.put(MediaRecorder.VideoEncoder.H264, "h264");
- VIDEO_ENCODER_TABLE.put(MediaRecorder.VideoEncoder.HEVC, "h265");
+ int h265 = ApiHelper.getIntFieldIfExists(MediaRecorder.VideoEncoder.class,
+ "HEVC", null, MediaRecorder.VideoEncoder.DEFAULT);
+ if (h265 == MediaRecorder.VideoEncoder.DEFAULT) {
+ h265 = ApiHelper.getIntFieldIfExists(MediaRecorder.VideoEncoder.class,
+ "H265", null, MediaRecorder.VideoEncoder.DEFAULT);
+ }
+ VIDEO_ENCODER_TABLE.put(h265, "h265");
VIDEO_ENCODER_TABLE.put(MediaRecorder.VideoEncoder.MPEG_4_SP, "m4v");
//video qualities
@@ -1037,7 +1039,7 @@ public class CameraSettings {
return false;
}
- private void filterUnsupportedOptions(PreferenceGroup group,
+ public static void filterUnsupportedOptions(PreferenceGroup group,
ListPreference pref, List<String> supported) {
// Remove the preference if the parameter is not supported or there is
@@ -1066,7 +1068,7 @@ public class CameraSettings {
resetIfInvalid(pref);
}
- private void resetIfInvalid(ListPreference pref) {
+ private static void resetIfInvalid(ListPreference pref) {
// Set the value to the first entry if it is invalid.
String value = pref.getValue();
if (pref.findIndexOfValue(value) == NOT_FOUND) {
@@ -1173,6 +1175,11 @@ public class CameraSettings {
return Integer.parseInt(pref.getString(KEY_CAMERA_ID, rearCameraId));
}
+ public static int getInitialCameraId(SharedPreferences pref) {
+ String value = pref.getString(SettingsManager.KEY_INITIAL_CAMERA, "0");
+ return Integer.parseInt(value);
+ }
+
public static void writePreferredCameraId(SharedPreferences pref,
int cameraId) {
Editor editor = pref.edit();
@@ -1404,14 +1411,11 @@ public class CameraSettings {
public static boolean isInstantCaptureSupported(Parameters params) {
boolean ret = false;
if (null != params) {
- // TODO: need to uncomment this code once get parameter
- // is supported
- //String val = params.get(KEY_QC_INSTANT_CAPTURE);
- //if (null != val) {
+ String val = params.get(KEY_QC_INSTANT_CAPTURE_VALUES);
+ if (null != val) {
ret = true;
- //}
+ }
}
return ret;
}
-
}
diff --git a/src/com/android/camera/CaptureMenu.java b/src/com/android/camera/CaptureMenu.java
deleted file mode 100644
index 8b8f5c357..000000000
--- a/src/com/android/camera/CaptureMenu.java
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
- * Not a Contribution.
- *
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.content.Context;
-import android.content.SharedPreferences;
-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;
-import android.view.View.OnClickListener;
-import android.view.ViewPropertyAnimator;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.Toast;
-
-import com.android.camera.ui.CameraControls;
-import com.android.camera.ui.CountdownTimerPopup;
-import com.android.camera.ui.ListMenu;
-import com.android.camera.ui.ListSubMenu;
-import com.android.camera.ui.ModuleSwitcher;
-import com.android.camera.ui.RotateTextToast;
-
-import org.codeaurora.snapcam.R;
-
-import java.util.Locale;
-
-public class CaptureMenu extends MenuController
- implements ListMenu.Listener,
- CountdownTimerPopup.Listener,
- ListSubMenu.Listener {
- private static final int POPUP_NONE = 0;
- private static final int POPUP_FIRST_LEVEL = 1;
- private static final int POPUP_SECOND_LEVEL = 2;
- private static final int POPUP_IN_ANIMATION_SLIDE = 3;
- private static final int POPUP_IN_ANIMATION_FADE = 4;
- private static final int DEVELOPER_MENU_TOUCH_COUNT = 10;
- private static final int ANIMATION_DURATION = 300;
- private static final String TAG = "SnapCam_CaptureMenu";
- private String[] mOtherKeys1;
- private String[] mOtherKeys2;
- private ListMenu mListMenu;
- private CaptureUI mUI;
- private int mPopupStatus;
- private ListSubMenu mListSubMenu;
- private CameraActivity mActivity;
- private int privateCounter = 0;
-
- public CaptureMenu(CameraActivity activity, CaptureUI ui) {
- super(activity);
- mUI = ui;
- mActivity = activity;
- }
-
- // Return true if the preference has the specified key but not the value.
- private static boolean notSame(ListPreference pref, String key, String value) {
- return (key.equals(pref.getKey()) && !value.equals(pref.getValue()));
- }
-
- // Return true if the preference has the specified key and the value.
- private static boolean same(ListPreference pref, String key, String value) {
- return (key.equals(pref.getKey()) && value.equals(pref.getValue()));
- }
-
- public void initialize(PreferenceGroup group) {
- super.initialize(group);
- mListSubMenu = null;
- mListMenu = null;
- mPopupStatus = POPUP_NONE;
-
- 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,
- CameraSettings.KEY_CLEARSIGHT
- };
-
- //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_CLEARSIGHT,
- CameraSettings.KEY_MONO_PREVIEW
- };
-
- }
-
- @Override
- // Hit when an item in a popup gets selected
- public void onListPrefChanged(ListPreference pref) {
- onSettingChanged(pref);
- closeView();
- }
-
- public boolean handleBackKey() {
- if (mPopupStatus == POPUP_NONE)
- return false;
- if (mPopupStatus == POPUP_FIRST_LEVEL) {
- animateSlideOut(mListMenu, 1);
- } else if (mPopupStatus == POPUP_SECOND_LEVEL) {
- animateFadeOut(mListSubMenu, 2);
- ((ListMenu) mListMenu).resetHighlight();
- }
- return true;
- }
-
- public void tryToCloseSubList() {
- if (mListMenu != null)
- ((ListMenu) mListMenu).resetHighlight();
-
- if (mPopupStatus == POPUP_SECOND_LEVEL) {
- mUI.dismissLevel2();
- mPopupStatus = POPUP_FIRST_LEVEL;
- }
- }
-
- private void animateFadeOut(final ListView v, final int level) {
- if (v == null || mPopupStatus == POPUP_IN_ANIMATION_FADE)
- return;
- mPopupStatus = POPUP_IN_ANIMATION_FADE;
-
- ViewPropertyAnimator vp = v.animate();
- vp.alpha(0f).setDuration(ANIMATION_DURATION);
- vp.setListener(new AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
-
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (level == 1) {
- mUI.dismissLevel1();
- initializePopup();
- mPopupStatus = POPUP_NONE;
- mUI.cleanupListview();
- } else if (level == 2) {
- mUI.dismissLevel2();
- mPopupStatus = POPUP_FIRST_LEVEL;
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- if (level == 1) {
- mUI.dismissLevel1();
- initializePopup();
- mPopupStatus = POPUP_NONE;
- mUI.cleanupListview();
- } else if (level == 2) {
- mUI.dismissLevel2();
- mPopupStatus = POPUP_FIRST_LEVEL;
- }
-
- }
- });
- vp.start();
- }
-
- private void animateSlideOut(final ListView v, final int level) {
- if (v == null || mPopupStatus == POPUP_IN_ANIMATION_SLIDE)
- return;
- mPopupStatus = POPUP_IN_ANIMATION_SLIDE;
-
- ViewPropertyAnimator vp = v.animate();
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
- switch (mUI.getOrientation()) {
- case 0:
- vp.translationXBy(v.getWidth());
- break;
- case 90:
- vp.translationYBy(-2 * v.getHeight());
- break;
- case 180:
- vp.translationXBy(-2 * v.getWidth());
- break;
- case 270:
- vp.translationYBy(v.getHeight());
- break;
- }
- } else {
- switch (mUI.getOrientation()) {
- case 0:
- vp.translationXBy(-v.getWidth());
- break;
- case 90:
- vp.translationYBy(2 * v.getHeight());
- break;
- case 180:
- vp.translationXBy(2 * v.getWidth());
- break;
- case 270:
- vp.translationYBy(-v.getHeight());
- break;
- }
- }
- vp.setListener(new AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
-
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (level == 1) {
- mUI.dismissLevel1();
- initializePopup();
- mPopupStatus = POPUP_NONE;
- mUI.cleanupListview();
- } else if (level == 2) {
- mUI.dismissLevel2();
- mPopupStatus = POPUP_FIRST_LEVEL;
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- if (level == 1) {
- mUI.dismissLevel1();
- initializePopup();
- mPopupStatus = POPUP_NONE;
- mUI.cleanupListview();
- } else if (level == 2) {
- mUI.dismissLevel2();
- mPopupStatus = POPUP_FIRST_LEVEL;
- }
-
- }
- });
- vp.setDuration(ANIMATION_DURATION).start();
- }
-
- public void animateFadeIn(final ListView v) {
- ViewPropertyAnimator vp = v.animate();
- vp.alpha(0.85f).setDuration(ANIMATION_DURATION);
- vp.start();
- }
-
- public void animateSlideIn(final View v, int delta, boolean forcePortrait) {
- int orientation = mUI.getOrientation();
- if (!forcePortrait)
- orientation = 0;
-
- ViewPropertyAnimator vp = v.animate();
- float dest;
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
- switch (orientation) {
- case 0:
- dest = v.getX();
- v.setX(-(dest - delta));
- vp.translationX(dest);
- break;
- case 90:
- dest = v.getY();
- v.setY(-(dest + delta));
- vp.translationY(dest);
- break;
- case 180:
- dest = v.getX();
- v.setX(-(dest + delta));
- vp.translationX(dest);
- break;
- case 270:
- dest = v.getY();
- v.setY(-(dest - delta));
- vp.translationY(dest);
- break;
- }
- } else {
- switch (orientation) {
- case 0:
- dest = v.getX();
- v.setX(dest - delta);
- vp.translationX(dest);
- break;
- case 90:
- dest = v.getY();
- v.setY(dest + delta);
- vp.translationY(dest);
- break;
- case 180:
- dest = v.getX();
- v.setX(dest + delta);
- vp.translationX(dest);
- break;
- case 270:
- dest = v.getY();
- v.setY(dest - delta);
- vp.translationY(dest);
- break;
- }
- }
- vp.setDuration(ANIMATION_DURATION).start();
- }
-
- public boolean isOverMenu(MotionEvent ev) {
- if (mPopupStatus == POPUP_NONE
- || mPopupStatus == POPUP_IN_ANIMATION_SLIDE
- || mPopupStatus == POPUP_IN_ANIMATION_FADE)
- return false;
- if (mUI.getMenuLayout() == null)
- return false;
- Rect rec = new Rect();
- mUI.getMenuLayout().getChildAt(0).getHitRect(rec);
- return rec.contains((int) ev.getX(), (int) ev.getY());
- }
-
- public boolean isOverPreviewMenu(MotionEvent ev) {
- return false;
- }
-
- public boolean isMenuBeingShown() {
- return mPopupStatus != POPUP_NONE;
- }
-
- public boolean isMenuBeingAnimated() {
- return mPopupStatus == POPUP_IN_ANIMATION_SLIDE || mPopupStatus == POPUP_IN_ANIMATION_FADE;
- }
-
- public boolean isPreviewMenuBeingShown() {
- return false;
- }
-
- public boolean isPreviewMenuBeingAnimated() {
- return false;
- }
-
- public boolean sendTouchToPreviewMenu(MotionEvent ev) {
- return mUI.sendTouchToPreviewMenu(ev);
- }
-
- public boolean sendTouchToMenu(MotionEvent ev) {
- return mUI.sendTouchToMenu(ev);
- }
-
- @Override
- public void overrideSettings(final String... keyvalues) {
- super.overrideSettings(keyvalues);
- if ((mListMenu == null))
- initializePopup();
- mListMenu.overrideSettings(keyvalues);
- }
-
- protected void initializePopup() {
- LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- ListMenu listMenu = (ListMenu) inflater.inflate(
- R.layout.list_menu, null, false);
-
- listMenu.setSettingChangedListener(this);
-
- String[] keys = mOtherKeys1;
- if (mActivity.isDeveloperMenuEnabled())
- keys = mOtherKeys2;
- 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);
- setPreference(CameraSettings.KEY_CLEARSIGHT, "off");
- mListMenu.setPreferenceEnabled(CameraSettings.KEY_CLEARSIGHT, false);
- }
-
- if (mListener != null) {
- mListener.onSharedPreferenceChanged();
- }
- }
-
- public void initSwitchItem(final String prefKey, View switcher) {
- final IconListPreference pref =
- (IconListPreference) mPreferenceGroup.findPreference(prefKey);
- if (pref == null)
- return;
-
- int[] iconIds = pref.getLargeIconIds();
- int resid = -1;
- int index = pref.findIndexOfValue(pref.getValue());
- if (!pref.getUseSingleIcon() && iconIds != null) {
- // Each entry has a corresponding icon.
- resid = iconIds[index];
- } else {
- // The preference only has a single icon to represent it.
- resid = pref.getSingleIcon();
- }
- ((ImageView) switcher).setImageResource(resid);
- switcher.setVisibility(View.VISIBLE);
- mPreferences.add(pref);
- mPreferenceMap.put(pref, switcher);
- switcher.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- IconListPreference pref = (IconListPreference) mPreferenceGroup
- .findPreference(prefKey);
- if (pref == null)
- return;
- int index = pref.findIndexOfValue(pref.getValue());
- CharSequence[] values = pref.getEntryValues();
- index = (index + 1) % values.length;
- pref.setValueIndex(index);
- ((ImageView) v).setImageResource(
- ((IconListPreference) pref).getLargeIconIds()[index]);
- if (prefKey.equals(CameraSettings.KEY_CAMERA_ID))
- mListener.onCameraPickerClicked(index);
- reloadPreference(pref);
- onSettingChanged(pref);
- }
- });
- }
-
- public void openFirstLevel() {
- if (isMenuBeingShown() || CameraControls.isAnimating()) {
- return;
- }
- if (mListMenu == null || mPopupStatus != POPUP_FIRST_LEVEL) {
- initializePopup();
- mPopupStatus = POPUP_FIRST_LEVEL;
- }
- mUI.showPopup(mListMenu, 1, true);
- }
-
- @Override
- // Hit when an item in the first-level popup gets selected, then bring up
- // the second-level popup
- public void onPreferenceClicked(ListPreference pref) {
- onPreferenceClicked(pref, 0);
- }
-
- public void onPreferenceClicked(ListPreference pref, int y) {
- if (!mActivity.isDeveloperMenuEnabled()) {
- if (pref.getKey().equals(CameraSettings.KEY_REDEYE_REDUCTION)) {
- privateCounter++;
- if (privateCounter >= DEVELOPER_MENU_TOUCH_COUNT) {
- mActivity.enableDeveloperMenu();
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(mActivity);
- prefs.edit().putBoolean(CameraSettings.KEY_DEVELOPER_MENU, true).apply();
- RotateTextToast.makeText(mActivity,
- "Camera developer option is enabled now", Toast.LENGTH_SHORT).show();
- }
- } else {
- privateCounter = 0;
- }
- }
-
- LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- ListSubMenu basic = (ListSubMenu) inflater.inflate(
- R.layout.list_sub_menu, null, false);
- basic.initialize(pref, y);
- basic.setSettingChangedListener(this);
- basic.setAlpha(0f);
- mListSubMenu = basic;
- mUI.removeLevel2();
- if (mPopupStatus == POPUP_SECOND_LEVEL) {
- mUI.showPopup(mListSubMenu, 2, false);
- } else {
- mUI.showPopup(mListSubMenu, 2, true);
- }
- mPopupStatus = POPUP_SECOND_LEVEL;
- }
-
- public void onListMenuTouched() {
- mUI.removeLevel2();
- }
-
- public void removeAllView() {
- if (mUI != null)
- mUI.removeLevel2();
-
- if (mListMenu != null) {
- mUI.dismissLevel1();
- mPopupStatus = POPUP_NONE;
- }
- mUI.cleanupListview();
- }
-
- public void closeView() {
- if (mUI != null)
- mUI.removeLevel2();
-
- if (mListMenu != null && mPopupStatus != POPUP_NONE)
- animateSlideOut(mListMenu, 1);
- }
-
- public void setPreference(String key, String value) {
- ListPreference pref = mPreferenceGroup.findPreference(key);
- if (pref != null && !value.equals(pref.getValue())) {
- pref.setValue(value);
- reloadPreferences();
- }
- }
-
- @Override
- public void onSettingChanged(ListPreference pref) {
- super.onSettingChanged(pref);
- 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);
- 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")) {
- }
- } else if (key.equals(CameraSettings.KEY_CLEARSIGHT)) {
- // restart module to re-create sessions and callbacks
- mActivity.onModuleSelected(ModuleSwitcher.CAPTURE_MODULE_INDEX);
- }
- }
-
- public int getOrientation() {
- return mUI == null ? 0 : mUI.getOrientation();
- }
-}
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 90e1794ac..0f65f21c3 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -19,30 +19,17 @@
package com.android.camera;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-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;
-
-import org.codeaurora.snapcam.R;
-import org.codeaurora.snapcam.filter.ClearSightImageProcessor;
-import org.codeaurora.snapcam.filter.ClearSightNativeEngine.ClearsightImage;
-
+import android.app.ActivityManager;
+import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
+import android.graphics.Camera;
import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.YuvImage;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
@@ -53,12 +40,14 @@ import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.Face;
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.Debug;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -66,6 +55,7 @@ import android.os.Message;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
+import android.view.Display;
import android.view.KeyEvent;
import android.view.OrientationEventListener;
import android.view.Surface;
@@ -73,16 +63,42 @@ import android.view.SurfaceHolder;
import android.view.View;
import android.widget.Toast;
+import com.android.camera.imageprocessor.filter.ImageFilter;
+import com.android.camera.imageprocessor.PostProcessor;
+import com.android.camera.imageprocessor.FrameProcessor;
import com.android.camera.PhotoModule.NamedImages;
import com.android.camera.PhotoModule.NamedImages.NamedEntity;
+import com.android.camera.ui.CountDownView;
+import com.android.camera.ui.ModuleSwitcher;
import com.android.camera.ui.RotateTextToast;
import com.android.camera.util.CameraUtil;
+import com.android.camera.util.PersistUtil;
+import com.android.internal.util.MemInfoReader;
+
+import org.codeaurora.snapcam.R;
+import org.codeaurora.snapcam.filter.ClearSightImageProcessor;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
public class CaptureModule implements CameraModule, PhotoController,
- MediaSaveService.Listener, ClearSightImageProcessor.Callback {
+ MediaSaveService.Listener, ClearSightImageProcessor.Callback,
+ SettingsManager.Listener, CountDownView.OnCountDownFinishedListener {
public static final int DUAL_MODE = 0;
public static final int BAYER_MODE = 1;
public static final int MONO_MODE = 2;
+ public static final int BAYER_ID = 0;
+ public static int MONO_ID = 1;
+ public static int FRONT_ID = 1;
+ private static final int BACK_MODE = 0;
+ private static final int FRONT_MODE = 1;
private static final int CANCEL_TOUCH_FOCUS_DELAY = 3000;
private static final int OPEN_CAMERA = 0;
private static final int CANCEL_TOUCH_FOCUS = 1;
@@ -117,11 +133,12 @@ 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;
- //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;
+
+ // Used for check memory status for longshot mode
+ // Currently, this cancel threshold selection is based on test experiments,
+ // we can change it based on memory status or other requirements.
+ private static final int LONGSHOT_CANCEL_THRESHOLD = 40 * 1024 * 1024;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
@@ -129,6 +146,7 @@ public class CaptureModule implements CameraModule, PhotoController,
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
+ private static final int MAX_IMAGE_NUM = 8;
MeteringRectangle[][] mAFRegions = new MeteringRectangle[MAX_NUM_CAM][];
CaptureRequest.Key<Byte> BayerMonoLinkEnableKey =
@@ -140,7 +158,9 @@ public class CaptureModule implements CameraModule, PhotoController,
CaptureRequest.Key<Integer> BayerMonoLinkSessionIdKey =
new CaptureRequest.Key<>("org.codeaurora.qcamera3.dualcam_link_meta_data" +
".related_camera_id", Integer.class);
-
+ public static CameraCharacteristics.Key<Byte> MetaDataMonoOnlyKey =
+ new CameraCharacteristics.Key<>("org.codeaurora.qcamera3.sensor_meta_data.is_mono_only",
+ Byte.class);
private boolean[] mTakingPicture = new boolean[MAX_NUM_CAM];
private int mControlAFMode = CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
private int mLastResultAFState = -1;
@@ -149,7 +169,6 @@ public class CaptureModule implements CameraModule, PhotoController,
// 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;
@@ -161,13 +180,14 @@ public class CaptureModule implements CameraModule, PhotoController,
private String[] mCameraId = new String[MAX_NUM_CAM];
private CaptureUI mUI;
private CameraActivity mActivity;
- private PreferenceGroup mPreferenceGroup;
- private ComboPreferences mPreferences;
- private CameraCharacteristics[] mCharacteristics = new CameraCharacteristics[MAX_NUM_CAM];
- private List<Integer> mCharacteristicsIndex;
+ private List<Integer> mCameraIdList;
private float mZoomValue = 1f;
private FocusStateListener mFocusStateListener;
private LocationManager mLocationManager;
+ private SettingsManager mSettingsManager;
+ private long SECONDARY_SERVER_MEM;
+ private boolean mLongshotActive = false;
+
/**
* A {@link CameraCaptureSession } for camera preview.
*/
@@ -182,6 +202,12 @@ public class CaptureModule implements CameraModule, PhotoController,
/**
* A {@link Handler} for running tasks in the background.
*/
+ private PostProcessor mPostProcessor;
+ private FrameProcessor mFrameProcessor;
+ private Size mFrameProcPreviewOutputSize;
+ private Face[] mPreviewFaces = null;
+ private Face[] mStickyFaces = null;
+ private Rect mBayerCameraRegion;
private Handler mCameraHandler;
private Handler mImageAvailableHandler;
private Handler mCaptureCallbackHandler;
@@ -192,16 +218,70 @@ public class CaptureModule implements CameraModule, PhotoController,
private ImageReader[] mImageReader = new ImageReader[MAX_NUM_CAM];
private NamedImages mNamedImages;
private ContentResolver mContentResolver;
+ private byte[] mLastJpegData;
+ private int mJpegFileSizeEstimation;
+ private boolean mFirstPreviewLoaded;
+ private int[] mPrecaptureRequestHashCode = new int[MAX_NUM_CAM];
+ private int[] mLockRequestHashCode = new int[MAX_NUM_CAM];
+
+ private class MediaSaveNotifyThread extends Thread {
+ private Uri uri;
+
+ public MediaSaveNotifyThread(Uri uri) {
+ this.uri = uri;
+ }
+
+ public void setUri(Uri uri) {
+ this.uri = uri;
+ }
+
+ public void run() {
+ while (mLongshotActive) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ }
+ }
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ if (uri != null)
+ mActivity.notifyNewMedia(uri);
+ mActivity.updateStorageSpaceAndHint();
+ if (mLastJpegData != null) mActivity.updateThumbnail(mLastJpegData);
+ }
+ });
+ mediaSaveNotifyThread = null;
+ }
+ }
+
+ public void updateThumbnailJpegData(byte[] jpegData) {
+ mLastJpegData = jpegData;
+ }
+
+ private MediaSaveNotifyThread mediaSaveNotifyThread;
private MediaSaveService.OnMediaSavedListener mOnMediaSavedListener =
new MediaSaveService.OnMediaSavedListener() {
@Override
public void onMediaSaved(Uri uri) {
- if (uri != null) {
- mActivity.notifyNewMedia(uri);
+ if (mLongshotActive) {
+ if (mediaSaveNotifyThread == null) {
+ mediaSaveNotifyThread = new MediaSaveNotifyThread(uri);
+ mediaSaveNotifyThread.start();
+ } else
+ mediaSaveNotifyThread.setUri(uri);
+ } else {
+ if (uri != null) {
+ mActivity.notifyNewMedia(uri);
+ }
+ if (mLastJpegData != null) mActivity.updateThumbnail(mLastJpegData);
}
}
};
+ public MediaSaveService.OnMediaSavedListener getMediaSavedListener() {
+ return mOnMediaSavedListener;
+ }
+
static abstract class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
int mCamId;
@@ -233,6 +313,20 @@ public class CaptureModule implements CameraModule, PhotoController,
* camera.
*/
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
+
+
+ public Face[] getPreviewFaces() {
+ return mPreviewFaces;
+ }
+
+ public Face[] getStickyFaces() {
+ return mStickyFaces;
+ }
+
+ public Rect getCameraRegion() {
+ return mBayerCameraRegion;
+ }
+
/**
* A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture.
*/
@@ -242,6 +336,22 @@ public class CaptureModule implements CameraModule, PhotoController,
private void process(CaptureResult result) {
int id = (int) result.getRequest().getTag();
+ if (!mFirstPreviewLoaded) {
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mUI.hidePreviewCover();
+ }
+ });
+ mFirstPreviewLoaded = true;
+ }
+
+ Face[] faces = result.get(CaptureResult.STATISTICS_FACES);
+ mPreviewFaces = faces;
+ if(faces != null && faces.length != 0) {
+ mStickyFaces = faces;
+ }
+
switch (mState[id]) {
case STATE_PREVIEW: {
break;
@@ -254,10 +364,12 @@ public class CaptureModule implements CameraModule, PhotoController,
if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState ||
- CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED == afState) {
+ CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED == afState ||
+ (mLockRequestHashCode[id] == result.getRequest().hashCode() &&
+ afState == CaptureResult.CONTROL_AF_STATE_INACTIVE)) {
// CONTROL_AE_STATE can be null on some devices
if (aeState == null || (aeState == CaptureResult
- .CONTROL_AE_STATE_CONVERGED) && isFlashOff()) {
+ .CONTROL_AE_STATE_CONVERGED) && isFlashOff(id)) {
mState[id] = STATE_PICTURE_TAKEN;
captureStillPicture(id);
} else {
@@ -274,7 +386,8 @@ public class CaptureModule implements CameraModule, PhotoController,
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
- mState[id] = STATE_WAITING_NON_PRECAPTURE;
+ if (mPrecaptureRequestHashCode[id] == result.getRequest().hashCode())
+ mState[id] = STATE_WAITING_NON_PRECAPTURE;
}
break;
}
@@ -311,52 +424,7 @@ public class CaptureModule implements CameraModule, PhotoController,
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
@@ -367,7 +435,7 @@ public class CaptureModule implements CameraModule, PhotoController,
if (mPaused) {
return;
}
- if (MODE == DUAL_MODE && id == BAYER_ID) {
+ if (isBackCamera() && getCameraMode() == DUAL_MODE && id == BAYER_ID) {
Message msg = mCameraHandler.obtainMessage(OPEN_CAMERA, MONO_ID);
mCameraHandler.sendMessage(msg);
}
@@ -376,8 +444,7 @@ public class CaptureModule implements CameraModule, PhotoController,
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
- mUI.onCameraOpened(mCharacteristics, mCharacteristicsIndex,
- mPreferenceGroup, prefListener);
+ mUI.onCameraOpened(mCameraIdList);
}
});
}
@@ -399,7 +466,7 @@ public class CaptureModule implements CameraModule, PhotoController,
@Override
public void onError(CameraDevice cameraDevice, int error) {
int id = Integer.parseInt(cameraDevice.getId());
- Log.d(TAG, "onError " + id + error);
+ Log.e(TAG, "onError " + id + " " + error);
cameraDevice.close();
mCameraDevice[id] = null;
mCameraOpenCloseLock.release();
@@ -418,23 +485,32 @@ public class CaptureModule implements CameraModule, PhotoController,
};
- public static boolean setMode(String value) {
- int mode = DUAL_MODE;
- switch (value) {
- case "dual":
- mode = DUAL_MODE;
+ private boolean isMonoPreviewOn() {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_MONO_PREVIEW);
+ if (value == null) return false;
+ if (value.equals("on")) return true;
+ else return false;
+ }
- break;
- case "bayer":
- mode = BAYER_MODE;
- break;
- case "mono":
- mode = MONO_MODE;
- break;
- }
- if (MODE == mode) return false;
- MODE = mode;
- return true;
+ private boolean isBackCamera() {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_CAMERA_ID);
+ if (value == null) return true;
+ if (Integer.parseInt(value) == BAYER_ID) return true;
+ return false;
+ }
+
+ private int getCameraMode() {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
+ if (value != null && value.equals(SettingsManager.SCENE_MODE_DUAL_STRING)) return DUAL_MODE;
+ value = mSettingsManager.getValue(SettingsManager.KEY_MONO_ONLY);
+ if (value == null || !value.equals("on")) return BAYER_MODE;
+ return MONO_MODE;
+ }
+
+ private boolean isClearSightOn() {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_CLEARSIGHT);
+ if (value == null) return false;
+ return isBackCamera() && getCameraMode() == DUAL_MODE && value.equals("on");
}
public static int getQualityNumber(String jpegQuality) {
@@ -471,8 +547,7 @@ public class CaptureModule implements CameraModule, PhotoController,
//Todo: test record location. Jack to provide instructions
// Initialize location service.
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
+ boolean recordLocation = getRecordLocation();
mLocationManager.recordLocation(recordLocation);
mUI.initializeFirstTime();
@@ -489,90 +564,113 @@ public class CaptureModule implements CameraModule, PhotoController,
private void initializeSecondTime() {
// Start location update if needed.
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
+ boolean recordLocation = getRecordLocation();
mLocationManager.recordLocation(recordLocation);
MediaSaveService s = mActivity.getMediaSaveService();
if (s != null) {
s.setListener(this);
}
mNamedImages = new NamedImages();
- mUI.initializeSecondTime();
+ }
+
+ public ArrayList<ImageFilter> getFrameFilters() {
+ if(mFrameProcessor == null) {
+ return new ArrayList<ImageFilter>();
+ } else {
+ return mFrameProcessor.getFrameFilters();
+ }
+ }
+
+ private void applyFaceDetect(CaptureRequest.Builder builder, int id) {
+ if(id == getMainCameraId()) {
+ builder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE,
+ CameraMetadata.STATISTICS_FACE_DETECT_MODE_SIMPLE);
+ }
}
private void createSession(final int id) {
if (mPaused || !mCameraOpened[id] || !mSurfaceReady) return;
+ Log.d(TAG, "createSession " + id);
List<Surface> list = new LinkedList<Surface>();
- mUI.hidePreviewCover();
try {
- Surface surface;
- if (id == BAYER_ID || (id == MONO_ID && MODE == MONO_MODE)) {
- SurfaceHolder sh = mUI.getSurfaceHolder();
- if (sh == null) {
- return;
- }
- surface = sh.getSurface();
- } else {
- SurfaceHolder sh = mUI.getSurfaceHolder2();
- if (sh == null) {
- return;
- }
- surface = sh.getSurface();
- }
+ Surface surface = getPreviewSurfaceForSession(id);
// 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);
CameraCaptureSession.StateCallback captureSessionCallback =
new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(CameraCaptureSession cameraCaptureSession) {
- // The camera is already closed
- if (mPaused || null == mCameraDevice[id]) {
- return;
- }
- // When the session is ready, we start displaying the preview.
- mCaptureSession[id] = cameraCaptureSession;
- initializePreviewConfiguration(id);
- try {
- if (MODE == DUAL_MODE) {
- linkBayerMono(id);
- mIsLinked = true;
+ @Override
+ public void onConfigured(CameraCaptureSession cameraCaptureSession) {
+ if (mPaused || null == mCameraDevice[id]) {
+ return;
+ }
+ // When the session is ready, we start displaying the preview.
+ mCaptureSession[id] = cameraCaptureSession;
+ initializePreviewConfiguration(id);
+ try {
+ if (isBackCamera() && getCameraMode() == DUAL_MODE) {
+ linkBayerMono(id);
+ mIsLinked = true;
+ }
+ // Finally, we start displaying the camera preview.
+ mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
+ .build(), mCaptureCallback, mCameraHandler);
+ if (isClearSightOn()) {
+ ClearSightImageProcessor.getInstance().onCaptureSessionConfigured(id == BAYER_ID, cameraCaptureSession);
+ }
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
}
- // Finally, we start displaying the camera preview.
- mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
- .build(), mCaptureCallback, mCameraHandler);
- ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CLEARSIGHT);
- if(pref.getValue().equals(mActivity.getString(R.string.pref_camera_clearsight_value_on))) {
- ClearSightImageProcessor.getInstance().onCaptureSessionConfigured(id == BAYER_ID, cameraCaptureSession);
+ @Override
+ public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
+ Log.e(TAG, "cameracapturesession - onConfigureFailed");
+ new AlertDialog.Builder(mActivity)
+ .setTitle("Camera Initialization Failed")
+ .setMessage("Closing SnapdragonCamera")
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ closeCamera();
+ mActivity.finish();
+ }
+ })
+ .setCancelable(false)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .show();
}
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
- Log.d(TAG, "cameracapturesession - onConfigureFailed");
- }
- @Override
- public void onClosed(CameraCaptureSession session) {
- Log.d(TAG, "cameracapturesession - onClosed");
- }
- };
-
- list.add(surface);
+ @Override
+ public void onClosed(CameraCaptureSession session) {
+ Log.d(TAG, "cameracapturesession - onClosed");
+ }
+ };
- ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CLEARSIGHT);
- if(pref.getValue().equals(mActivity.getString(R.string.pref_camera_clearsight_value_on))) {
+ if(isClearSightOn()) {
+ mPreviewRequestBuilder[id].addTarget(surface);
+ list.add(surface);
ClearSightImageProcessor.getInstance().createCaptureSession(
- id==BAYER_ID, mCameraDevice[id], list, captureSessionCallback);
+ id == BAYER_ID, mCameraDevice[id], list, captureSessionCallback);
+ } else if (id == getMainCameraId()) {
+ if(mFrameProcessor.isFrameFilterEnabled()) {
+ mFrameProcessor.init(mFrameProcPreviewOutputSize);
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mUI.getSurfaceHolder().setFixedSize(mFrameProcPreviewOutputSize.getHeight(), mFrameProcPreviewOutputSize.getWidth());
+ }
+ });
+ }
+ mFrameProcessor.setOutputSurface(surface);
+ mPreviewRequestBuilder[id].addTarget(mFrameProcessor.getInputSurface());
+ list.add(mFrameProcessor.getInputSurface());
+ list.add(mImageReader[id].getSurface());
+ mCameraDevice[id].createCaptureSession(list, captureSessionCallback, null);
} else {
+ mPreviewRequestBuilder[id].addTarget(surface);
+ list.add(surface);
list.add(mImageReader[id].getSurface());
// Here, we create a CameraCaptureSession for camera preview.
mCameraDevice[id].createCaptureSession(list, captureSessionCallback, null);
@@ -593,8 +691,24 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
+ public void reinit() {
+ setCurrentMode();
+ mSettingsManager.reinit(getMainCameraId());
+ }
+
+ public boolean getRecordLocation() {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_RECORD_LOCATION);
+ if (value == null) value = RecordLocationPreference.VALUE_NONE;
+ return RecordLocationPreference.VALUE_ON.equals(value);
+ }
+
@Override
public void init(CameraActivity activity, View parent) {
+ mActivity = activity;
+ mSettingsManager = SettingsManager.getInstance();
+ mSettingsManager.registerListener(this);
+ mSettingsManager.init();
+ mFirstPreviewLoaded = false;
Log.d(TAG, "init");
for (int i = 0; i < MAX_NUM_CAM; i++) {
mCameraOpened[i] = false;
@@ -602,32 +716,22 @@ public class CaptureModule implements CameraModule, PhotoController,
}
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, 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());
+ mPostProcessor = new PostProcessor(mActivity, this);
+ mFrameProcessor = new FrameProcessor(mActivity, this);
+ setCurrentMode();
mContentResolver = mActivity.getContentResolver();
mUI = new CaptureUI(activity, this, parent);
mUI.initializeControlByIntent();
+
mFocusStateListener = new FocusStateListener(mUI);
mLocationManager = new LocationManager(mActivity, mUI);
- Storage.setSaveSDCard(
- mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1"));
+ Storage.setSaveSDCard(mSettingsManager.getValue(SettingsManager
+ .KEY_CAMERA_SAVEPATH).equals("1"));
}
/**
@@ -635,17 +739,22 @@ public class CaptureModule implements CameraModule, PhotoController,
*/
private void takePicture() {
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;
+ mUI.enableShutter(false);
+ if (isBackCamera()) {
+ switch (getCameraMode()) {
+ case DUAL_MODE:
+ lockFocus(BAYER_ID);
+ lockFocus(MONO_ID);
+ break;
+ case BAYER_MODE:
+ lockFocus(BAYER_ID);
+ break;
+ case MONO_MODE:
+ lockFocus(MONO_ID);
+ break;
+ }
+ } else {
+ lockFocus(FRONT_ID);
}
}
@@ -653,7 +762,12 @@ public class CaptureModule implements CameraModule, PhotoController,
* Lock the focus as the first step for a still image capture.
*/
private void lockFocus(int id) {
+ if (mActivity == null || mCameraDevice[id] == null) {
+ warningToast("Camera is not ready yet to take a picture.");
+ return;
+ }
Log.d(TAG, "lockFocus " + id);
+
mTakingPicture[id] = true;
if (mState[id] == STATE_WAITING_TOUCH_FOCUS) {
mCameraHandler.removeMessages(CANCEL_TOUCH_FOCUS, id);
@@ -667,14 +781,11 @@ public class CaptureModule implements CameraModule, PhotoController,
builder.setTag(id);
builder.addTarget(getPreviewSurface(id));
- builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
- builder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode);
- builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
- applyWhiteBalance(builder);
- applyZoom(builder, id);
- applyAFRegions(builder, id);
+ applySettingsForLockFocus(builder, id);
+ CaptureRequest request = builder.build();
+ mLockRequestHashCode[id] = request.hashCode();
mState[id] = STATE_WAITING_LOCK;
- mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler);
+ mCaptureSession[id].capture(request, mCaptureCallback, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
@@ -682,6 +793,10 @@ public class CaptureModule implements CameraModule, PhotoController,
private void autoFocusTrigger(int id) {
Log.d(TAG, "autoFocusTrigger " + id);
+ if (null == mActivity || null == mCameraDevice[id]) {
+ warningToast("Camera is not ready yet to take a picture.");
+ return;
+ }
try {
CaptureRequest.Builder builder = mCameraDevice[id].createCaptureRequest(CameraDevice
.TEMPLATE_PREVIEW);
@@ -689,14 +804,7 @@ public class CaptureModule implements CameraModule, PhotoController,
builder.addTarget(getPreviewSurface(id));
mControlAFMode = CaptureRequest.CONTROL_AF_MODE_AUTO;
- builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
- builder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode);
- builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest
- .CONTROL_AF_TRIGGER_START);
-
- applyWhiteBalance(builder);
- applyZoom(builder, id);
- applyAFRegions(builder, id);
+ applySettingsForAutoFocus(builder, id);
mState[id] = STATE_WAITING_TOUCH_FOCUS;
mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler);
setAFModeToPreview(id, mControlAFMode);
@@ -729,20 +837,15 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
- /**
- * 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[id]) {
+ warningToast("Camera is not ready yet to take a picture.");
return;
}
- ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CLEARSIGHT);
- final boolean csEnabled = pref.getValue().equals(
- mActivity.getString(R.string.pref_camera_clearsight_value_on));
+ final boolean csEnabled = isClearSightOn();
CaptureRequest.Builder captureBuilder;
if(csEnabled) {
@@ -754,32 +857,32 @@ public class CaptureModule implements CameraModule, PhotoController,
// Orientation
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
+ captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, CameraUtil.getJpegRotation(id, rotation));
captureBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
captureBuilder.addTarget(getPreviewSurface(id));
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode);
captureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
- applyCaptureSettings(captureBuilder, id);
+ applySettingsForCapture(captureBuilder, id);
if(csEnabled) {
ClearSightImageProcessor.getInstance().capture(
id==BAYER_ID, mCaptureSession[id], captureBuilder, mCaptureCallbackHandler);
- } else {
+ } else if(id == getMainCameraId() && mPostProcessor.isFilterOn()) {
captureBuilder.addTarget(mImageReader[id].getSurface());
-
- mCaptureSession[id].capture(captureBuilder.build(), new CameraCaptureSession.CaptureCallback() {
+ List<CaptureRequest> captureList = mPostProcessor.setRequiredImages(captureBuilder);
+ mCaptureSession[id].captureBurst(captureList, new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session,
- CaptureRequest request,
- TotalCaptureResult result) {
+ CaptureRequest request,
+ TotalCaptureResult result) {
Log.d(TAG, "captureStillPicture onCaptureCompleted: " + id);
}
@Override
public void onCaptureFailed(CameraCaptureSession session,
- CaptureRequest request,
- CaptureFailure result) {
+ CaptureRequest request,
+ CaptureFailure result) {
Log.d(TAG, "captureStillPicture onCaptureFailed: " + id);
}
@@ -790,6 +893,83 @@ public class CaptureModule implements CameraModule, PhotoController,
unlockFocus(id);
}
}, mCaptureCallbackHandler);
+ } else {
+ captureBuilder.addTarget(mImageReader[id].getSurface());
+ mCaptureSession[id].stopRepeating();
+
+ if (mLongshotActive) {
+ Log.d(TAG, "captureStillPicture capture longshot " + id);
+ List<CaptureRequest> burstList = new ArrayList<>();
+ for (int i = 0; i < PersistUtil.getLongshotShotLimit(); i++) {
+ burstList.add(captureBuilder.build());
+ }
+ mCaptureSession[id].captureBurst(burstList, new
+ CameraCaptureSession.CaptureCallback() {
+
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session,
+ CaptureRequest request,
+ TotalCaptureResult result) {
+ Log.d(TAG, "captureStillPicture Longshot onCaptureCompleted: " + id);
+ if (mLongshotActive) {
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mUI.doShutterAnimation();
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onCaptureFailed(CameraCaptureSession session,
+ CaptureRequest request,
+ CaptureFailure result) {
+ Log.d(TAG, "captureStillPicture Longshot onCaptureFailed: " + id);
+ if (mLongshotActive) {
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mUI.doShutterAnimation();
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onCaptureSequenceCompleted(CameraCaptureSession session, int
+ sequenceId, long frameNumber) {
+ Log.d(TAG, "captureStillPicture Longshot onCaptureSequenceCompleted: " + id);
+ mLongshotActive = false;
+ unlockFocus(id);
+ }
+ }, mCaptureCallbackHandler);
+ } else {
+ mCaptureSession[id].capture(captureBuilder.build(),
+ new CameraCaptureSession.CaptureCallback() {
+
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session,
+ CaptureRequest request,
+ TotalCaptureResult result) {
+ Log.d(TAG, "captureStillPicture onCaptureCompleted: " + id);
+ }
+
+ @Override
+ public void onCaptureFailed(CameraCaptureSession session,
+ CaptureRequest request,
+ CaptureFailure result) {
+ Log.d(TAG, "captureStillPicture onCaptureFailed: " + id);
+ }
+
+ @Override
+ public void onCaptureSequenceCompleted(CameraCaptureSession session, int
+ sequenceId, long frameNumber) {
+ Log.d(TAG, "captureStillPicture onCaptureSequenceCompleted: " + id);
+ unlockFocus(id);
+ }
+ }, mCaptureCallbackHandler);
+ }
}
} catch (CameraAccessException e) {
Log.d(TAG, "Capture still picture has failed");
@@ -808,92 +988,129 @@ public class CaptureModule implements CameraModule, PhotoController,
.TEMPLATE_PREVIEW);
builder.setTag(id);
builder.addTarget(getPreviewSurface(id));
- builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
- builder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode);
- builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
- CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
- // Applying flash only to capture does not work. Need to apply flash here.
- applyFlash(builder);
- applyWhiteBalance(builder);
- applyZoom(builder, id);
+ applySettingsForPrecapture(builder, id);
+ CaptureRequest request = builder.build();
+ mPrecaptureRequestHashCode[id] = request.hashCode();
mState[id] = STATE_WAITING_PRECAPTURE;
- mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler);
+ mCaptureSession[id].capture(request, mCaptureCallback, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
+ private void determineFrameProcPreviewOutputSize(List<Size> sizeList, float targetRatio) {
+ Display display = mActivity.getWindowManager().getDefaultDisplay();
+ Point ds = new Point();
+ display.getSize(ds);
+ int i=0, j=0, width, height;
+ float ratio;
+ for(; i < sizeList.size(); i++) {
+ width = sizeList.get(i).getHeight();
+ height = sizeList.get(i).getWidth();
+ ratio = (float)height/width;
+ if(ds.x >= width || ds.y >= height) {
+ if(j == 0) {
+ j = i;
+ }
+ if(ratio < targetRatio + 0.2f && ratio > targetRatio - 0.2f) {
+ break;
+ }
+ }
+ }
+ if(i == sizeList.size()) {
+ if(j != 0) {
+ mFrameProcPreviewOutputSize = sizeList.get(j);
+ } else {
+ mFrameProcPreviewOutputSize = sizeList.get(sizeList.size()-1);
+ }
+ } else {
+ mFrameProcPreviewOutputSize = sizeList.get(i);
+ }
+ }
/**
* Sets up member variables related to camera.
*
* @param width The width of available size for camera preview
* @param height The height of available size for camera preview
*/
- private void setUpCameraOutputs() {
+ private void setUpCameraOutputs(int imageFormat) {
+ Log.d(TAG, "setUpCameraOutputs");
CameraManager manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
try {
String[] cameraIdList = manager.getCameraIdList();
-
for (int i = 0; i < cameraIdList.length; i++) {
String cameraId = cameraIdList[i];
- CameraCharacteristics characteristics
- = manager.getCameraCharacteristics(cameraId);
- mCharacteristics[i] = characteristics;
- mCharacteristicsIndex.add(i);
+
+ CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
+ if (isInMode(i))
+ mCameraIdList.add(i);
+ if(i == getMainCameraId()) {
+ mBayerCameraRegion = characteristics.get(CameraCharacteristics
+ .SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ }
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));
mCameraId[i] = cameraId;
- ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CLEARSIGHT);
- if(pref.getValue().equals(mActivity.getString(R.string.pref_camera_clearsight_value_on))) {
- Size largest = Collections.max(
- Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)),
- new CompareSizesByArea());
- ClearSightImageProcessor.getInstance().init(
- largest.getWidth(), largest.getHeight(), mActivity, mOnMediaSavedListener);
+ String pictureSize = mSettingsManager.getValue(SettingsManager
+ .KEY_PICTURE_SIZE);
+
+ Size size = parsePictureSize(pictureSize);
+
+ if (i == getMainCameraId()) {
+ Point screenSize = new Point();
+ mActivity.getWindowManager().getDefaultDisplay().getSize(screenSize);
+ Size[] prevSizes = map.getOutputSizes(imageFormat);
+ mFrameProcPreviewOutputSize = getOptimalPreviewSize(size, prevSizes, screenSize.x,
+ screenSize.y);
+ mUI.setPreviewSize(mFrameProcPreviewOutputSize.getWidth(), mFrameProcPreviewOutputSize.getHeight());
+ }
+ if (isClearSightOn()) {
+ ClearSightImageProcessor.getInstance().init(size.getWidth(), size.getHeight(),
+ mActivity, mOnMediaSavedListener);
ClearSightImageProcessor.getInstance().setCallback(this);
} else {
// No Clearsight
- // 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, 3);
- mImageReader[i].setOnImageAvailableListener(new ImageAvailableListener(i) {
- @Override
- 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()];
- buffer.get(bytes);
-
- mActivity.getMediaSaveService().addImage(bytes, title, date,
- null, image.getWidth(), image.getHeight(), 0, null,
- mOnMediaSavedListener, mContentResolver, "jpeg");
- image.close();
- }
- }, mImageAvailableHandler);
+ mImageReader[i] = ImageReader.newInstance(size.getWidth(), size.getHeight(), imageFormat, MAX_IMAGE_NUM);
+ if(mPostProcessor.isFilterOn() && i == getMainCameraId()) {
+ mImageReader[i].setOnImageAvailableListener(mPostProcessor, mImageAvailableHandler);
+// if(mFrameProcessor.isFrameFilterEnabled()) {
+// determineFrameProcPreviewOutputSize(Arrays.asList(map.getOutputSizes(imageFormat)),
+// (float) size.getWidth() / (float) size.getHeight());
+// }
+ } else {
+ mImageReader[i].setOnImageAvailableListener(new ImageAvailableListener(i) {
+ @Override
+ 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();
+ }
+ }, mImageAvailableHandler);
+ }
}
+
}
- mAutoFocusSupported = CameraUtil.isAutoFocusSupported(mCharacteristics,
- mCharacteristicsIndex);
+ mAutoFocusSupported = mSettingsManager.isAutoFocusSupported(mCameraIdList);
} catch (CameraAccessException e) {
e.printStackTrace();
- } catch (NullPointerException e) {
}
}
@@ -909,14 +1126,7 @@ public class CaptureModule implements CameraModule, PhotoController,
builder.setTag(id);
builder.addTarget(getPreviewSurface(id));
- builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest
- .CONTROL_MODE_AUTO);
- builder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode);
- builder.set(CaptureRequest.CONTROL_AF_TRIGGER,
- CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
- //Todo: Create applyCommonSettings function for settings applied everytime
- applyWhiteBalance(builder);
- applyZoom(builder, id);
+ applySettingsForUnlockFocus(builder, id);
mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler);
mState[id] = STATE_PREVIEW;
mControlAFMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
@@ -924,11 +1134,24 @@ public class CaptureModule implements CameraModule, PhotoController,
mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(),
mCaptureCallback, mCameraHandler);
mTakingPicture[id] = false;
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mUI.enableShutter(true);
+ }
+ });
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
+ private Size parsePictureSize(String value) {
+ int indexX = value.indexOf('x');
+ int width = Integer.parseInt(value.substring(0, indexX));
+ int height = Integer.parseInt(value.substring(indexX + 1));
+ return new Size(width, height);
+ }
+
/**
* Closes the current {@link CameraDevice}.
*/
@@ -936,6 +1159,12 @@ public class CaptureModule implements CameraModule, PhotoController,
Log.d(TAG, "closeCamera");
try {
mCameraOpenCloseLock.acquire();
+ if(mPostProcessor != null) {
+ mPostProcessor.onClose();
+ }
+ if(mFrameProcessor != null) {
+ mFrameProcessor.onClose();
+ }
for (int i = 0; i < MAX_NUM_CAM; i++) {
if (null != mCaptureSession[i]) {
if (mIsLinked) {
@@ -947,7 +1176,6 @@ public class CaptureModule implements CameraModule, PhotoController,
e.printStackTrace();
}
}
-
mCaptureSession[i].close();
mCaptureSession[i] = null;
}
@@ -977,6 +1205,53 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
+ private void applySettingsForLockFocus(CaptureRequest.Builder builder, int id) {
+ builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
+ applyAFRegions(builder, id);
+ applyCommonSettings(builder, id);
+ applyFaceDetect(builder, id);
+ }
+
+ private void applySettingsForCapture(CaptureRequest.Builder builder, int id) {
+ builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
+ applyJpegQuality(builder);
+ applyCommonSettings(builder, id);
+ }
+
+ private void applySettingsForPrecapture(CaptureRequest.Builder builder, int id) {
+ builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+ CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
+ applyCommonSettings(builder, id);
+ applyFaceDetect(builder, id);
+ }
+
+ private void applySettingsForUnlockFocus(CaptureRequest.Builder builder, int id) {
+ builder.set(CaptureRequest.CONTROL_AF_TRIGGER,
+ CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
+ applyCommonSettings(builder, id);
+ applyFaceDetect(builder, id);
+ }
+
+ private void applySettingsForAutoFocus(CaptureRequest.Builder builder, int id) {
+ builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest
+ .CONTROL_AF_TRIGGER_START);
+ applyAFRegions(builder, id);
+ applyCommonSettings(builder, id);
+ applyFaceDetect(builder, id);
+ }
+
+ private void applyCommonSettings(CaptureRequest.Builder builder, int id) {
+ builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+ builder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode);
+ applyFlash(builder, id);
+ applyWhiteBalance(builder);
+ applyExposure(builder);
+ applyIso(builder);
+ applyColorEffect(builder);
+ applySceneMode(builder);
+ applyZoom(builder, id);
+ }
+
/**
* Starts a background thread and its {@link Handler}.
*/
@@ -1058,13 +1333,14 @@ public class CaptureModule implements CameraModule, PhotoController,
@Override
public void onPauseAfterSuper() {
Log.d(TAG, "onPause");
- mUI.showPreviewCover();
if (mLocationManager != null) mLocationManager.recordLocation(false);
- ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CLEARSIGHT);
- if(pref.getValue().equals(mActivity.getString(R.string.pref_camera_clearsight_value_on))) {
+ if(isClearSightOn()) {
ClearSightImageProcessor.getInstance().close();
}
closeCamera();
+ mUI.showPreviewCover();
+ mUI.hideSurfaceView();
+ mFirstPreviewLoaded = false;
stopBackgroundThread();
mUI.onPause();
}
@@ -1074,33 +1350,83 @@ public class CaptureModule implements CameraModule, PhotoController,
mPaused = false;
}
+ private void setCurrentMode() {
+ mCurrentMode = isBackCamera() ? getCameraMode() : FRONT_MODE;
+ }
+
+ private ArrayList<Integer> getFrameProcFilterId() {
+ String scene = mSettingsManager.getValue(SettingsManager.KEY_MAKEUP);
+ ArrayList<Integer> filters = new ArrayList<Integer>();
+ if(scene != null && scene.equalsIgnoreCase("on")) {
+ filters.add(FrameProcessor.FILTER_MAKEUP);
+ }
+
+ return filters;
+ }
+
+ private int getPostProcFilterId() {
+ String scene = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
+ if (scene != null) {
+ int mode = Integer.parseInt(scene);
+ if (mode == SettingsManager.SCENE_MODE_OPTIZOOM_INT)
+ return PostProcessor.FILTER_OPTIZOOM;
+ }
+ return PostProcessor.FILTER_NONE;
+ }
+
+ private boolean isPostProcFilter(String value) {
+ if(value.equalsIgnoreCase(SettingsManager.SCENE_MODE_OPTIZOOM_INT+"")) {
+ return true;
+ }
+ return false;
+ }
+
@Override
public void onResumeAfterSuper() {
- Log.d(TAG, "onResume " + MODE);
- mCharacteristicsIndex = new ArrayList<>();
+ Log.d(TAG, "onResume " + getCameraMode());
+ mUI.showSurfaceView();
+ mUI.setSwitcherIndex();
+ mCameraIdList = new ArrayList<>();
+ if(mPostProcessor != null) {
+ Log.d(TAG, "Chosen postproc filter id : "+getPostProcFilterId());
+ mPostProcessor.onOpen(getPostProcFilterId());
+ }
+ if(mFrameProcessor != null) {
+ mFrameProcessor.onOpen(getFrameProcFilterId());
+ }
+ if(mPostProcessor.isFilterOn()) {
+ setUpCameraOutputs(ImageFormat.YUV_420_888);
+ } else {
+ setUpCameraOutputs(ImageFormat.JPEG);
+ }
startBackgroundThread();
- setUpCameraOutputs();
- readInitialValues();
Message msg = Message.obtain();
msg.what = OPEN_CAMERA;
- switch (MODE) {
- case DUAL_MODE:
- case BAYER_MODE:
- msg.obj = BAYER_ID;
- mCameraHandler.sendMessage(msg);
- break;
- case MONO_MODE:
- msg.what = OPEN_CAMERA;
- msg.obj = MONO_ID;
- mCameraHandler.sendMessage(msg);
- break;
+ if (isBackCamera()) {
+ switch (getCameraMode()) {
+ case DUAL_MODE:
+ case BAYER_MODE:
+ msg.obj = BAYER_ID;
+ mCameraHandler.sendMessage(msg);
+ break;
+ case MONO_MODE:
+ msg.what = OPEN_CAMERA;
+ msg.obj = MONO_ID;
+ mCameraHandler.sendMessage(msg);
+ break;
+ }
+ } else {
+ msg.obj = FRONT_ID;
+ mCameraHandler.sendMessage(msg);
}
if (!mFirstTimeInitialized) {
initializeFirstTime();
} else {
initializeSecondTime();
}
- mUI.hidePreviewCover();
+ mUI.reInitUI();
+ mActivity.updateStorageSpaceAndHint();
+ estimateJpegFileSize();
mUI.enableShutter(true);
}
@@ -1148,18 +1474,38 @@ public class CaptureModule implements CameraModule, PhotoController,
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;
+ if (isBackCamera()) {
+ switch (getCameraMode()) {
+ case DUAL_MODE:
+ applyZoomAndUpdate(BAYER_ID);
+ applyZoomAndUpdate(MONO_ID);
+ break;
+ case BAYER_MODE:
+ applyZoomAndUpdate(BAYER_ID);
+ break;
+ case MONO_MODE:
+ applyZoomAndUpdate(MONO_ID);
+ break;
+ }
+ } else {
+ applyZoomAndUpdate(FRONT_ID);
+ }
+ }
+
+ private boolean isInMode(int cameraId) {
+ if (isBackCamera()) {
+ switch (getCameraMode()) {
+ case DUAL_MODE:
+ return cameraId == BAYER_ID || cameraId == MONO_ID;
+ case BAYER_MODE:
+ return cameraId == BAYER_ID;
+ case MONO_MODE:
+ return cameraId == MONO_ID;
+ }
+ } else {
+ return cameraId == FRONT_ID;
}
+ return false;
}
@Override
@@ -1211,41 +1557,64 @@ public class CaptureModule implements CameraModule, PhotoController,
Log.d(TAG, "onSingleTapUp " + x + " " + y);
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;
+ if (isBackCamera()) {
+ switch (getCameraMode()) {
+ 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;
+ }
+ } else {
+ triggerFocusAtPoint(x, y, FRONT_ID);
}
}
private int getMainCameraId() {
- switch (MODE) {
- case DUAL_MODE:
- case BAYER_MODE:
- return BAYER_ID;
- case MONO_MODE:
- return MONO_ID;
+ if (isBackCamera()) {
+ switch (getCameraMode()) {
+ case DUAL_MODE:
+ case BAYER_MODE:
+ return BAYER_ID;
+ case MONO_MODE:
+ return MONO_ID;
+ }
+ return 0;
+ } else {
+ return FRONT_ID;
}
- return 0;
}
- private boolean isTouchToFocusAllowed() {
+ public boolean isTakingPicture() {
for (int i = 0; i < mTakingPicture.length; i++) {
- if (mTakingPicture[i]) return false;
+ if (mTakingPicture[i]) return true;
}
+ return false;
+ }
+
+ private boolean isTouchToFocusAllowed() {
+ if (isTakingPicture() || isSceneModeOn()) return false;
return true;
}
+ private boolean isSceneModeOn() {
+ String scene = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
+ if (scene == null) return false;
+ int mode = Integer.parseInt(scene);
+ if (mode != SettingsManager.SCENE_MODE_DUAL_INT && mode != CaptureRequest
+ .CONTROL_SCENE_MODE_DISABLED) return true;
+ return false;
+ }
+
@Override
public void onCountDownFinished() {
-
+ mUI.showUIAfterCountDown();
+ takePicture();
}
@Override
@@ -1265,16 +1634,7 @@ public class CaptureModule implements CameraModule, PhotoController,
@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
@@ -1284,23 +1644,26 @@ public class CaptureModule implements CameraModule, PhotoController,
}
Log.d(TAG, "onPreviewUIReady");
mSurfaceReady = true;
- 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;
+ if (isBackCamera()) {
+ switch (getCameraMode()) {
+ case DUAL_MODE:
+ createSession(BAYER_ID);
+ createSession(MONO_ID);
+ break;
+ case BAYER_MODE:
+ createSession(BAYER_ID);
+ break;
+ case MONO_MODE:
+ createSession(MONO_ID);
+ break;
+ }
+ } else {
+ createSession(FRONT_ID);
}
}
@Override
public void onPreviewUIDestroyed() {
-
}
@Override
@@ -1332,6 +1695,7 @@ public class CaptureModule implements CameraModule, PhotoController,
int oldOrientation = mOrientation;
mOrientation = CameraUtil.roundOrientation(orientation, mOrientation);
if (oldOrientation != mOrientation) {
+ mUI.onOrientationChanged();
mUI.setOrientation(mOrientation, true);
}
}
@@ -1345,8 +1709,7 @@ public class CaptureModule implements CameraModule, PhotoController,
public void onMediaSaveServiceConnected(MediaSaveService s) {
if (mFirstTimeInitialized) {
s.setListener(this);
- ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CLEARSIGHT);
- if(pref.getValue().equals(mActivity.getString(R.string.pref_camera_clearsight_value_on))) {
+ if (isClearSightOn()) {
ClearSightImageProcessor.getInstance().setMediaSaveService(s);
}
}
@@ -1364,65 +1727,165 @@ public class CaptureModule implements CameraModule, PhotoController,
@Override
public void onSwitchSavePath() {
- if (mUI.mMenuInitialized) {
- mUI.setPreference(CameraSettings.KEY_CAMERA_SAVEPATH, "1");
- } else {
- mPreferences.edit()
- .putString(CameraSettings.KEY_CAMERA_SAVEPATH, "1")
- .apply();
- }
+ mSettingsManager.setValue(SettingsManager.KEY_CAMERA_SAVEPATH, "1");
RotateTextToast.makeText(mActivity, R.string.on_switch_save_path_to_sdcard,
Toast.LENGTH_SHORT).show();
}
@Override
public void onShutterButtonFocus(boolean pressed) {
-
+ if (!pressed && mLongshotActive) {
+ Log.d(TAG, "Longshot button up");
+ }
}
@Override
public void onShutterButtonClick() {
- takePicture();
+ String timer = mSettingsManager.getValue(SettingsManager.KEY_TIMER);
+
+ int seconds = Integer.parseInt(timer);
+ // When shutter button is pressed, check whether the previous countdown is
+ // finished. If not, cancel the previous countdown and start a new one.
+ if (mUI.isCountingDown()) {
+ mUI.cancelCountDown();
+ }
+ if (seconds > 0) {
+ mUI.startCountDown(seconds, true);
+ } else {
+ if(mPostProcessor.isFilterOn() && mPostProcessor.isItBusy()) {
+ warningToast("It's still busy processing previous scene mode request.");
+ return;
+ }
+ takePicture();
+ }
+ }
+
+ private void warningToast(final String msg) {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ RotateTextToast.makeText(mActivity, msg,
+ Toast.LENGTH_SHORT).show();
+ }
+ });
+
}
@Override
public void onShutterButtonLongClick() {
+ if (isBackCamera() && getCameraMode() == DUAL_MODE) return;
+
+ String longshot = mSettingsManager.getValue(SettingsManager.KEY_LONGSHOT);
+ if (longshot.equals("on")) {
+ //Cancel the previous countdown when long press shutter button for longshot.
+ if (mUI.isCountingDown()) {
+ mUI.cancelCountDown();
+ }
+ //check whether current memory is enough for longshot.
+ mActivity.updateStorageSpaceAndHint();
+
+ long storageSpace = mActivity.getStorageSpaceBytes();
+ int mLongShotCaptureCountLimit = PersistUtil.getLongshotShotLimit();
+ if (storageSpace <= Storage.LOW_STORAGE_THRESHOLD_BYTES + mLongShotCaptureCountLimit
+ * mJpegFileSizeEstimation) {
+ Log.i(TAG, "Not enough space or storage not ready. remaining=" + storageSpace);
+ return;
+ }
+
+ if (isLongshotNeedCancel()) {
+ mLongshotActive = false;
+ return;
+ }
+
+ Log.d(TAG, "Start Longshot");
+ mLongshotActive = true;
+ takePicture();
+ }
}
- private boolean isFlashOff() {
- return readSetting(CameraSettings.KEY_FLASH_MODE).equals("off");
+ private void estimateJpegFileSize() {
+ String quality = mSettingsManager.getValue(SettingsManager
+ .KEY_JPEG_QUALITY);
+ int[] ratios = mActivity.getResources().getIntArray(R.array.jpegquality_compression_ratio);
+ String[] qualities = mActivity.getResources().getStringArray(
+ R.array.pref_camera_jpegquality_entryvalues);
+ int ratio = 0;
+ for (int i = ratios.length - 1; i >= 0; --i) {
+ if (qualities[i].equals(quality)) {
+ ratio = ratios[i];
+ break;
+ }
+ }
+ String pictureSize = mSettingsManager.getValue(SettingsManager
+ .KEY_PICTURE_SIZE);
+
+ Size size = parsePictureSize(pictureSize);
+ if (ratio == 0) {
+ Log.d(TAG, "mJpegFileSizeEstimation 0");
+ } else {
+ mJpegFileSizeEstimation = size.getWidth() * size.getHeight() * 3 / ratio;
+ Log.d(TAG, "mJpegFileSizeEstimation " + mJpegFileSizeEstimation);
+ }
+
+ }
+
+ private boolean isLongshotNeedCancel() {
+ if (PersistUtil.getSkipMemoryCheck()) {
+ return false;
+ }
+
+ if (Storage.getAvailableSpace() <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
+ Log.w(TAG, "current storage is full");
+ return true;
+ }
+ if (SECONDARY_SERVER_MEM == 0) {
+ ActivityManager am = (ActivityManager) mActivity.getSystemService(
+ Context.ACTIVITY_SERVICE);
+ ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
+ am.getMemoryInfo(memInfo);
+ SECONDARY_SERVER_MEM = memInfo.secondaryServerThreshold;
+ }
+
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ long maxMemory = Runtime.getRuntime().maxMemory();
+ long remainMemory = maxMemory - totalMemory;
+
+ MemInfoReader reader = new MemInfoReader();
+ reader.readMemInfo();
+ long[] info = reader.getRawInfo();
+ long availMem = (info[Debug.MEMINFO_FREE] + info[Debug.MEMINFO_CACHED]) * 1024;
+
+ if (availMem <= SECONDARY_SERVER_MEM || remainMemory <= LONGSHOT_CANCEL_THRESHOLD) {
+ Log.e(TAG, "cancel longshot: free=" + info[Debug.MEMINFO_FREE] * 1024
+ + " cached=" + info[Debug.MEMINFO_CACHED] * 1024
+ + " threshold=" + SECONDARY_SERVER_MEM);
+ RotateTextToast.makeText(mActivity, R.string.msg_cancel_longshot_for_limited_memory,
+ Toast.LENGTH_SHORT).show();
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isFlashOff(int id) {
+ if (!mSettingsManager.isFlashSupported(id)) return true;
+ return mSettingsManager.getValue(SettingsManager.KEY_FLASH_MODE).equals("1");
}
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);
+ applyCommonSettings(mPreviewRequestBuilder[id], id);
+ applyFaceDetect(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());
- }
- }
+ public float getZoomValue() {
+ return mZoomValue;
}
public Rect cropRegionForZoom(int id) {
Log.d(TAG, "cropRegionForZoom " + id);
- Rect activeRegion = mCharacteristics[id].get(CameraCharacteristics
- .SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ Rect activeRegion = mSettingsManager.getSensorActiveArraySize(id);
Rect cropRegion = new Rect();
int xCenter = activeRegion.width() / 2;
@@ -1438,36 +1901,36 @@ public class CaptureModule implements CameraModule, PhotoController,
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) {
+ private boolean applyPreferenceToPreview(int cameraId, String key, String value) {
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:
+ case SettingsManager.KEY_WHITE_BALANCE:
updatePreview = true;
applyWhiteBalance(mPreviewRequestBuilder[cameraId]);
break;
+ case SettingsManager.KEY_COLOR_EFFECT:
+ updatePreview = true;
+ applyColorEffect(mPreviewRequestBuilder[cameraId]);
+ break;
+ case SettingsManager.KEY_SCENE_MODE:
+ updatePreview = true;
+ applySceneMode(mPreviewRequestBuilder[cameraId]);
+ break;
+ case SettingsManager.KEY_EXPOSURE:
+ updatePreview = true;
+ applyExposure(mPreviewRequestBuilder[cameraId]);
+ break;
+ case SettingsManager.KEY_FLASH_MODE:
+ updatePreview = true;
+ applyFlash(mPreviewRequestBuilder[cameraId], cameraId);
+ break;
+ case SettingsManager.KEY_ISO:
+ updatePreview = true;
+ applyIso(mPreviewRequestBuilder[cameraId]);
+ break;
}
- if (updatePreview) {
- try {
- mCaptureSession[cameraId].setRepeatingRequest(mPreviewRequestBuilder[cameraId]
- .build(), mCaptureCallback, mCameraHandler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
+ applyFaceDetect(mPreviewRequestBuilder[cameraId], cameraId);
+ return updatePreview;
}
private void applyZoomAndUpdate(int id) {
@@ -1480,14 +1943,6 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
- 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);
}
@@ -1500,64 +1955,101 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
- 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 void applySceneMode(CaptureRequest.Builder request) {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
+ if (value == null) return;
+ int mode = Integer.parseInt(value);
+ if (mode != CaptureRequest.CONTROL_SCENE_MODE_DISABLED && mode !=
+ SettingsManager.SCENE_MODE_DUAL_INT) {
+ request.set(CaptureRequest.CONTROL_SCENE_MODE, mode);
+ request.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_USE_SCENE_MODE);
+ } else {
+ request.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
}
}
- private Surface getPreviewSurface(int id) {
- if (MODE == DUAL_MODE && id == MONO_ID) {
- return mUI.getSurfaceHolder2().getSurface();
- } else {
- return mUI.getSurfaceHolder().getSurface();
- }
+ private void applyExposure(CaptureRequest.Builder request) {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_EXPOSURE);
+ if (value == null) return;
+ int intValue = Integer.parseInt(value);
+ request.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, intValue);
+ }
+
+ private void applyIso(CaptureRequest.Builder request) {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_ISO);
+ if (value == null) return;
+ if (value.equals("auto")) return;
+ int intValue = Integer.parseInt(value);
+ request.set(CaptureRequest.SENSOR_SENSITIVITY, intValue);
+ }
+
+ private void applyColorEffect(CaptureRequest.Builder request) {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_COLOR_EFFECT);
+ if (value == null) return;
+ int mode = Integer.parseInt(value);
+ request.set(CaptureRequest.CONTROL_EFFECT_MODE, mode);
+ }
+
+ private void applyWhiteBalance(CaptureRequest.Builder request) {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_WHITE_BALANCE);
+ if (value == null) return;
+ int mode = Integer.parseInt(value);
+ request.set(CaptureRequest.CONTROL_AWB_MODE, mode);
}
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);
+ int mode = Integer.parseInt(value);
+ String redeye = mSettingsManager.getValue(SettingsManager.KEY_REDEYE_REDUCTION);
+ request.set(CaptureRequest.CONTROL_AE_MODE, mode);
+ switch (mode) {
+ case 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);
+ case CaptureRequest.CONTROL_AE_MODE_ON:
request.set(CaptureRequest.FLASH_MODE, CaptureRequest
.FLASH_MODE_OFF);
break;
+ case CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH:
+ if (redeye.equals("disable")) {
+ request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest
+ .CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE);
+ }
+ break;
}
}
- private void applyFlash(CaptureRequest.Builder request) {
- String value = readSetting(CameraSettings.KEY_FLASH_MODE);
- applyFlash(request, value);
+ private void applyFlash(CaptureRequest.Builder request, int id) {
+ if (mSettingsManager.isFlashSupported(id)) {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_FLASH_MODE);
+ applyFlash(request, value);
+ } else {
+ request.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
+ }
+ }
+
+ private Surface getPreviewSurface(int id) {
+ if (isBackCamera()) {
+ if (getCameraMode() == DUAL_MODE && id == MONO_ID) {
+ return mUI.getSurfaceHolder2().getSurface();
+ } else {
+ return mFrameProcessor.getInputSurface();
+ }
+ } else {
+ return mFrameProcessor.getInputSurface();
+ }
+ }
+
+ private Surface getPreviewSurfaceForSession(int id) {
+ if (isBackCamera()) {
+ if (getCameraMode() == DUAL_MODE && id == MONO_ID) {
+ return mUI.getSurfaceHolder2().getSurface();
+ } else {
+ return mUI.getSurfaceHolder().getSurface();
+ }
+ } else {
+ return mUI.getSurfaceHolder().getSurface();
+ }
}
@Override
@@ -1572,12 +2064,7 @@ public class CaptureModule implements CameraModule, PhotoController,
public void triggerFocusAtPoint(float x, float y, int id) {
Log.d(TAG, "triggerFocusAtPoint " + x + " " + y + " " + id);
- Point p;
- if (id == getMainCameraId()) {
- p = mUI.getSurfaceViewSize();
- } else {
- p = mUI.getSurfaceView2Size();
- }
+ Point p = mUI.getSurfaceViewSize();
int width = p.x;
int height = p.y;
x = x / width;
@@ -1622,6 +2109,144 @@ public class CaptureModule implements CameraModule, PhotoController,
mLastResultAFState = resultAFState;
}
+ @Override
+ public void onSettingsChanged(List<SettingsManager.SettingState> settings) {
+ if (mPaused) return;
+ boolean updatePreviewBayer = false;
+ boolean updatePreviewMono = false;
+ boolean updatePreviewFront = false;
+ int count = 0;
+ for (SettingsManager.SettingState settingState : settings) {
+ String key = settingState.key;
+ SettingsManager.Values values = settingState.values;
+ String value;
+ if (values.overriddenValue != null) {
+ value = values.overriddenValue;
+ } else {
+ value = values.value;
+ }
+ switch (key) {
+ case SettingsManager.KEY_CAMERA_SAVEPATH:
+ Storage.setSaveSDCard(value.equals("1"));
+ mActivity.updateStorageSpaceAndHint();
+ continue;
+ case SettingsManager.KEY_JPEG_QUALITY:
+ mJpegQuality = getQualityNumber(value);
+ estimateJpegFileSize();
+ continue;
+ case SettingsManager.KEY_CAMERA2:
+ switchCameraMode(value);
+ return;
+ case SettingsManager.KEY_CAMERA_ID:
+ case SettingsManager.KEY_MONO_ONLY:
+ case SettingsManager.KEY_CLEARSIGHT:
+ case SettingsManager.KEY_PICTURE_SIZE:
+ case SettingsManager.KEY_MONO_PREVIEW:
+ if (count == 0) restart();
+ return;
+ case SettingsManager.KEY_MAKEUP:
+ restart();
+ return;
+ case SettingsManager.KEY_SCENE_MODE:
+ if (count == 0 && checkNeedToRestart(value)) {
+ restart();
+ return;
+ }
+ break;
+ }
+
+ if (isBackCamera()) {
+ switch (getCameraMode()) {
+ case BAYER_MODE:
+ updatePreviewBayer |= applyPreferenceToPreview(BAYER_ID, key, value);
+ break;
+ case MONO_MODE:
+ updatePreviewMono |= applyPreferenceToPreview(MONO_ID, key, value);
+ break;
+ case DUAL_MODE:
+ updatePreviewBayer |= applyPreferenceToPreview(BAYER_ID, key, value);
+ updatePreviewMono |= applyPreferenceToPreview(MONO_ID, key, value);
+ break;
+ }
+ } else {
+ updatePreviewFront |= applyPreferenceToPreview(FRONT_ID, key, value);
+ }
+ count++;
+ }
+ if (updatePreviewBayer) {
+ try {
+ mCaptureSession[BAYER_ID].setRepeatingRequest(mPreviewRequestBuilder[BAYER_ID]
+ .build(), mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ if (updatePreviewMono) {
+ try {
+ mCaptureSession[MONO_ID].setRepeatingRequest(mPreviewRequestBuilder[MONO_ID]
+ .build(), mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ if (updatePreviewFront) {
+ try {
+ mCaptureSession[FRONT_ID].setRepeatingRequest(mPreviewRequestBuilder[FRONT_ID]
+ .build(), mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private int mCurrentMode;
+
+ private boolean checkNeedToRestart(String value) {
+ mPostProcessor.setFilter(PostProcessor.FILTER_NONE);
+ if (isPostProcFilter(value))
+ return true;
+ if (value.equals(SettingsManager.SCENE_MODE_DUAL_STRING) && mCurrentMode != DUAL_MODE)
+ return true;
+ if (!value.equals(SettingsManager.SCENE_MODE_DUAL_STRING) && mCurrentMode == DUAL_MODE)
+ return true;
+ return false;
+ }
+
+ private void restart() {
+ reinit();
+ onPauseBeforeSuper();
+ onPauseAfterSuper();
+ onResumeBeforeSuper();
+ onResumeAfterSuper();
+ }
+
+ private void switchCameraMode(String value) {
+ if (value.equals("enable")) {
+ mActivity.onModuleSelected(ModuleSwitcher.CAPTURE_MODULE_INDEX);
+ } else {
+ mActivity.onModuleSelected(ModuleSwitcher.PHOTO_MODULE_INDEX);
+ }
+ }
+
+ private Size getOptimalPreviewSize(Size pictureSize, Size[] prevSizes, int screenW, int
+ screenH) {
+ Size optimal = prevSizes[0];
+ float ratio = (float) pictureSize.getWidth() / pictureSize.getHeight();
+ for (Size prevSize: prevSizes) {
+ float prevRatio = (float) prevSize.getWidth() / prevSize.getHeight();
+ if (Math.abs(prevRatio - ratio) < 0.01) {
+ // flip w and h
+ if (prevSize.getWidth() <= screenH && prevSize.getHeight() <= screenW &&
+ prevSize.getWidth() <= pictureSize.getWidth() && prevSize.getHeight() <= pictureSize.getHeight()) {
+ return prevSize;
+ } else {
+ optimal = prevSize;
+ }
+ }
+ }
+ return optimal;
+ }
+
/**
* Compares two {@code Size}s based on their areas.
*/
diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java
index a6accae7b..5b8ecad6e 100644
--- a/src/com/android/camera/CaptureUI.java
+++ b/src/com/android/camera/CaptureUI.java
@@ -19,37 +19,36 @@
package com.android.camera;
-import android.content.res.Configuration;
-import android.graphics.Matrix;
+import android.animation.Animator;
+import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Point;
-import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
import android.hardware.Camera.Face;
-import android.hardware.camera2.CameraCharacteristics;
+import android.text.TextUtils;
import android.util.Log;
+import android.view.Display;
import android.view.Gravity;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
-import android.view.SurfaceView;
import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
+import android.view.WindowManager;
import android.widget.FrameLayout;
-import android.widget.FrameLayout.LayoutParams;
+import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.PopupWindow;
+import android.widget.TextView;
-import com.android.camera.CameraPreference.OnPreferenceChangedListener;
-import com.android.camera.FocusOverlayManager.FocusUI;
+import com.android.camera.ui.AutoFitSurfaceView;
import com.android.camera.ui.CameraControls;
-import com.android.camera.ui.CameraRootView;
+import com.android.camera.ui.CountDownView;
import com.android.camera.ui.FocusIndicator;
+import com.android.camera.ui.ListMenu;
import com.android.camera.ui.ListSubMenu;
import com.android.camera.ui.ModuleSwitcher;
import com.android.camera.ui.PieRenderer;
-import com.android.camera.ui.PieRenderer.PieListener;
import com.android.camera.ui.RenderOverlay;
import com.android.camera.ui.RotateImageView;
import com.android.camera.ui.RotateLayout;
@@ -60,150 +59,165 @@ import com.android.camera.util.CameraUtil;
import org.codeaurora.snapcam.R;
import java.util.List;
+import java.util.Locale;
-public class CaptureUI implements PieListener,
+public class CaptureUI implements FocusOverlayManager.FocusUI,
PreviewGestures.SingleTapListener,
- FocusUI,
- SurfaceHolder.Callback,
LocationManager.Listener,
- CameraRootView.MyDisplayListener,
- CameraManager.CameraFaceDetectionCallback {
-
+ CameraManager.CameraFaceDetectionCallback,
+ SettingsManager.Listener,
+ ListMenu.Listener,
+ ListSubMenu.Listener {
+ private static final int HIGHLIGHT_COLOR = 0xff33b5e5;
private static final String TAG = "SnapCam_CaptureUI";
- public boolean mMenuInitialized = false;
- private boolean surface1created = false;
- private boolean surface2created = false;
+ private static final int SETTING_MENU_NONE = 0;
+ private static final int SETTING_MENU_IN_ANIMATION = 1;
+ private static final int SETTING_MENU_ON = 2;
+ private static final int SETTING_MENU_LEVEL_ONE = 0;
+ private static final int SETTING_MENU_LEVEL_TWO = 1;
+ private static final int SCENE_AND_FILTER_MENU_NONE = 0;
+ private static final int SCENE_AND_FILTER_MENU_IN_ANIMATION = 1;
+ private static final int SCENE_AND_FILTER_MENU_ON = 2;
+ private static final int MODE_FILTER = 0;
+ private static final int MODE_SCENE = 1;
+ private static final int ANIMATION_DURATION = 300;
+ private static final int CLICK_THRESHOLD = 200;
+ String[] mSettingKeys = new String[]{
+ SettingsManager.KEY_FLASH_MODE,
+ SettingsManager.KEY_RECORD_LOCATION,
+ SettingsManager.KEY_PICTURE_SIZE,
+ SettingsManager.KEY_JPEG_QUALITY,
+ SettingsManager.KEY_TIMER,
+ SettingsManager.KEY_CAMERA_SAVEPATH,
+ SettingsManager.KEY_LONGSHOT,
+ SettingsManager.KEY_EXPOSURE,
+ SettingsManager.KEY_WHITE_BALANCE,
+ SettingsManager.KEY_CAMERA2,
+ SettingsManager.KEY_MAKEUP
+ };
+ String[] mDeveloperKeys = new String[]{
+ SettingsManager.KEY_MONO_ONLY,
+ SettingsManager.KEY_CLEARSIGHT,
+ SettingsManager.KEY_MONO_PREVIEW
+ };
private CameraActivity mActivity;
- private PhotoController mController;
- private PreviewGestures mGestures;
-
private View mRootView;
+ private View mPreviewCover;
+ private CaptureModule mModule;
+ private AutoFitSurfaceView mSurfaceView;
+ private AutoFitSurfaceView mSurfaceView2;
private SurfaceHolder mSurfaceHolder;
private SurfaceHolder mSurfaceHolder2;
+ private int mOrientation;
+ private RotateLayout mMenuLayout;
+ private RotateLayout mSubMenuLayout;
+ private int mSettingMenuState;
+ private int mSettingMenuLevel;
+ private int mSceneAndFilterMenuStatus;
+ private int mSceneAndFilterMenuMode;
+ private ListMenu mSettingMenu;
+ private ListSubMenu mSettingSubMenu;
+ private PreviewGestures mGestures;
+ private boolean mUIhidden = false;
+ private SettingsManager mSettingsManager;
+
+ private ImageView mThumbnail;
+
private SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
// SurfaceHolder callbacks
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ Log.v(TAG, "surfaceChanged: width =" + width + ", height = " + height);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
- mSurfaceHolder2 = holder;
- if (surface1created) mController.onPreviewUIReady();
- surface2created = true;
+ Log.v(TAG, "surfaceCreated");
+ mSurfaceHolder = holder;
+ mModule.onPreviewUIReady();
+ mActivity.updateThumbnail(mThumbnail);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
- mSurfaceHolder2 = null;
- surface2created = false;
+ Log.v(TAG, "surfaceDestroyed");
+ mSurfaceHolder = null;
+ mModule.onPreviewUIDestroyed();
}
};
- private PopupWindow mPopup;
+
private ShutterButton mShutterButton;
private RenderOverlay mRenderOverlay;
private View mMenuButton;
- private CaptureMenu mMenu;
private ModuleSwitcher mSwitcher;
+ private CountDownView mCountDownView;
private CameraControls mCameraControls;
- // Small indicators which show the camera settings in the viewfinder.
- private OnScreenIndicators mOnScreenIndicators;
private PieRenderer mPieRenderer;
private ZoomRenderer mZoomRenderer;
- private int mPreviewWidth = 0;
- private int mPreviewHeight = 0;
- private int mOriginalPreviewWidth = 0;
- private int mOriginalPreviewHeight = 0;
- private float mSurfaceTextureUncroppedWidth;
- private float mSurfaceTextureUncroppedHeight;
-
- private SurfaceView mSurfaceView = null;
- private SurfaceView mSurfaceView2 = null;
- private Matrix mMatrix = null;
- private boolean mAspectRatioResize;
-
- private boolean mOrientationResize;
- private boolean mPrevOrientationResize;
- private View mPreviewCover;
- private RotateLayout mMenuLayout;
- private RotateLayout mSubMenuLayout;
- private LinearLayout mPreviewMenuLayout;
- private boolean mUIhidden = false;
- private int mPreviewOrientation = -1;
private int mScreenRatio = CameraUtil.RATIO_UNKNOWN;
private int mTopMargin = 0;
private int mBottomMargin = 0;
+ private LinearLayout mSceneAndFilterLayout;
+ private int mSceneAndFilterMenuSize;
- private int mOrientation;
- private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() {
+ private View mFilterModeSwitcher;
+ private View mSceneModeSwitcher;
+ private View mFrontBackSwitcher;
+
+ private SurfaceHolder.Callback callback2 = new SurfaceHolder.Callback() {
+
+ // SurfaceHolder callbacks
@Override
- public void onLayoutChange(View v, int left, int top, int right,
- int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
- int width = right - left;
- int height = bottom - top;
-
- int orientation = mActivity.getResources().getConfiguration().orientation;
- if ((orientation == Configuration.ORIENTATION_PORTRAIT && width > height)
- || (orientation == Configuration.ORIENTATION_LANDSCAPE && width < height)) {
- // The screen has rotated; swap SurfaceView width & height
- // to ensure correct preview
- int oldWidth = width;
- width = height;
- height = oldWidth;
- Log.d(TAG, "Swapping SurfaceView width & height dimensions");
- if (mOriginalPreviewWidth != 0 && mOriginalPreviewHeight != 0) {
- int temp = mOriginalPreviewWidth;
- mOriginalPreviewWidth = mOriginalPreviewHeight;
- mOriginalPreviewHeight = temp;
- }
- }
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ }
- if (mPreviewWidth != width || mPreviewHeight != height
- || (mOrientationResize != mPrevOrientationResize)
- || mAspectRatioResize) {
- if (mOriginalPreviewWidth == 0) mOriginalPreviewWidth = width;
- if (mOriginalPreviewHeight == 0) mOriginalPreviewHeight = height;
- mPreviewWidth = width;
- mPreviewHeight = height;
- setTransformMatrix(mPreviewWidth, mPreviewHeight);
- mController.onScreenSizeChanged((int) mSurfaceTextureUncroppedWidth,
- (int) mSurfaceTextureUncroppedHeight);
- mAspectRatioResize = false;
- }
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ mSurfaceHolder2 = holder;
+ }
- if (mMenu != null)
- mMenu.tryToCloseSubList();
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ mSurfaceHolder2 = null;
}
};
- public CaptureUI(CameraActivity activity, PhotoController controller, View parent) {
+ public CaptureUI(CameraActivity activity, CaptureModule module, View parent) {
mActivity = activity;
- mController = controller;
+ mModule = module;
mRootView = parent;
+ mSettingsManager = SettingsManager.getInstance();
+ mSettingsManager.registerListener(this);
mActivity.getLayoutInflater().inflate(R.layout.capture_module,
(ViewGroup) mRootView, true);
mPreviewCover = mRootView.findViewById(R.id.preview_cover);
// display the view
- mSurfaceView = (SurfaceView) mRootView.findViewById(R.id.mdp_preview_content);
- mSurfaceView2 = (SurfaceView) mRootView.findViewById(R.id.mdp_preview_content2);
+ mSurfaceView = (AutoFitSurfaceView) mRootView.findViewById(R.id.mdp_preview_content);
+ mSurfaceView2 = (AutoFitSurfaceView) mRootView.findViewById(R.id.mdp_preview_content2);
mSurfaceView2.setZOrderMediaOverlay(true);
mSurfaceHolder = mSurfaceView.getHolder();
- mSurfaceHolder.addCallback(this);
+ mSurfaceHolder.addCallback(callback);
mSurfaceHolder2 = mSurfaceView2.getHolder();
- mSurfaceHolder2.addCallback(callback);
- Log.v(TAG, "Using mdp_preview_content (MDP path)");
+ mSurfaceHolder2.addCallback(callback2);
mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay);
mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
+ mFilterModeSwitcher = mRootView.findViewById(R.id.filter_mode_switcher);
+ mSceneModeSwitcher = mRootView.findViewById(R.id.scene_mode_switcher);
+ mFrontBackSwitcher = mRootView.findViewById(R.id.front_back_switcher);
+ initFilterModeButton();
+ initSceneModeButton();
+ initSwitchCamera();
+
mSwitcher = (ModuleSwitcher) mRootView.findViewById(R.id.camera_switcher);
mSwitcher.setCurrentIndex(ModuleSwitcher.PHOTO_MODULE_INDEX);
mSwitcher.setSwitchListener(mActivity);
- mSwitcher.setOnClickListener(new OnClickListener() {
+ mSwitcher.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (mController.getCameraState() == PhotoController.LONGSHOT) {
+ if (mModule.getCameraState() == PhotoController.LONGSHOT) {
return;
}
mSwitcher.showPopup();
@@ -217,10 +231,6 @@ public class CaptureUI implements PieListener,
mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
- initIndicators();
- mOrientationResize = false;
- mPrevOrientationResize = false;
-
Point size = new Point();
mActivity.getWindowManager().getDefaultDisplay().getSize(size);
mScreenRatio = CameraUtil.determineRatio(size.x, size.y);
@@ -232,68 +242,12 @@ public class CaptureUI implements PieListener,
mBottomMargin = l / 4 - mTopMargin;
}
mCameraControls.setMargins(mTopMargin, mBottomMargin);
- }
-
- private void setTransformMatrix(int width, int height) {
- mMatrix = mSurfaceView.getMatrix();
-
- // Calculate the new preview rectangle.
- RectF previewRect = new RectF(0, 0, width, height);
- mMatrix.mapRect(previewRect);
- mController.onPreviewRectChanged(CameraUtil.rectFToRect(previewRect));
- }
-
- // SurfaceHolder callbacks
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- Log.v(TAG, "surfaceChanged: width =" + width + ", height = " + height);
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- Log.v(TAG, "surfaceCreated");
- mSurfaceHolder = holder;
- if (surface2created) mController.onPreviewUIReady();
- surface1created = true;
- if (mPreviewWidth != 0 && mPreviewHeight != 0) {
- // Re-apply transform matrix for new surface texture
- setTransformMatrix(mPreviewWidth, mPreviewHeight);
- }
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- Log.v(TAG, "surfaceDestroyed");
- mSurfaceHolder = null;
- surface1created = false;
- mController.onPreviewUIDestroyed();
- }
-
- public View getRootView() {
- return mRootView;
- }
-
- private void initIndicators() {
- mOnScreenIndicators = new OnScreenIndicators(mActivity,
- mRootView.findViewById(R.id.on_screen_indicators));
- }
-
- 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);
- }
- mMenu.initialize(prefGroup);
- mMenuInitialized = true;
-
if (mZoomRenderer == null) {
mZoomRenderer = new ZoomRenderer(mActivity);
mRenderOverlay.addRenderer(mZoomRenderer);
@@ -304,209 +258,686 @@ public class CaptureUI implements PieListener,
mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer);
mRenderOverlay.setGestures(mGestures);
}
- mGestures.setCaptureMenu(mMenu);
- mGestures.setZoomEnabled(CameraUtil.isZoomSupported(characteristics, characteristicsIndex));
mGestures.setRenderOverlay(mRenderOverlay);
mRenderOverlay.requestLayout();
- initializeZoom(characteristics, characteristicsIndex);
mActivity.setPreviewGestures(mGestures);
}
- public void initializeControlByIntent() {
- mMenuButton = mRootView.findViewById(R.id.menu);
- mMenuButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mMenu != null) {
- mMenu.openFirstLevel();
- }
- }
- });
- }
-
- public void hideUI() {
- mSwitcher.closePopup();
- if (mUIhidden)
- return;
- mUIhidden = true;
- mCameraControls.hideUI();
+ public void onCameraOpened(List<Integer> cameraIds) {
+ mGestures.setCaptureUI(this);
+ mGestures.setZoomEnabled(mSettingsManager.isZoomSupported(cameraIds));
+ initializeZoom(cameraIds);
}
- public void showUI() {
- if (!mUIhidden || (mMenu != null && mMenu.isMenuBeingShown()))
- return;
- mUIhidden = false;
- mCameraControls.showUI();
+ public ViewGroup getSceneAndFilterLayout() {
+ return mSceneAndFilterLayout;
}
- public boolean arePreviewControlsVisible() {
- return !mUIhidden;
+ public void reInitUI() {
+ initializeSettingMenu();
+ initSceneModeButton();
+ initFilterModeButton();
}
// called from onResume but only the first time
public void initializeFirstTime() {
// Initialize shutter button.
mShutterButton.setImageResource(R.drawable.shutter_button_anim);
- mShutterButton.setOnClickListener(new OnClickListener() {
+ mShutterButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!CameraControls.isAnimating())
doShutterAnimation();
}
});
- mShutterButton.setOnShutterButtonListener(mController);
+ mShutterButton.setOnShutterButtonListener(mModule);
mShutterButton.setVisibility(View.VISIBLE);
}
- // called from onResume every other time
- public void initializeSecondTime() {
- if (mMenu != null) {
- mMenu.reloadPreferences();
+ public void initializeZoom(List<Integer> ids) {
+ if (!mSettingsManager.isZoomSupported(ids) || (mZoomRenderer == null))
+ return;
+
+ Float zoomMax = mSettingsManager.getMaxZoom(ids);
+ mZoomRenderer.setZoomMax(zoomMax);
+ mZoomRenderer.setZoom(1f);
+ mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener());
+ }
+
+ public void enableGestures(boolean enable) {
+ if (mGestures != null) {
+ mGestures.setEnabled(enable);
}
}
- public void doShutterAnimation() {
- AnimationDrawable frameAnimation = (AnimationDrawable) mShutterButton.getDrawable();
- frameAnimation.stop();
- frameAnimation.start();
+ public boolean isPreviewMenuBeingShown() {
+ return mSceneAndFilterMenuStatus == SCENE_AND_FILTER_MENU_ON;
}
- public void initializeZoom(CameraCharacteristics[] characteristics,
- List<Integer> characteristicsIndex) {
- if ((characteristics == null) || !CameraUtil.isZoomSupported(characteristics,
- characteristicsIndex) || (mZoomRenderer == null))
- return;
- if (mZoomRenderer != null) {
- 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);
+ public void removeSceneAndFilterMenu(boolean animate) {
+ if (animate) {
+ animateSlideOut(mSceneAndFilterLayout);
+ } else {
+ mSceneAndFilterMenuStatus = SCENE_AND_FILTER_MENU_NONE;
+ if (mSceneAndFilterLayout != null) {
+ ((ViewGroup) mRootView).removeView(mSceneAndFilterLayout);
+ mSceneAndFilterLayout = null;
}
- mZoomRenderer.setZoomMax(zoomMax);
- mZoomRenderer.setZoom(1f);
- mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener());
}
}
- @Override
- public void showGpsOnScreenIndicator(boolean hasSignal) {
+ public void initSwitchCamera() {
+ mFrontBackSwitcher.setVisibility(View.INVISIBLE);
+ String value = mSettingsManager.getValue(SettingsManager.KEY_CAMERA_ID);
+ if (value == null)
+ return;
+
+ int[] largeIcons = mSettingsManager.getResource(SettingsManager.KEY_CAMERA_ID,
+ SettingsManager.RESOURCE_TYPE_LARGEICON);
+ ((ImageView) mFrontBackSwitcher).setImageResource(largeIcons[mSettingsManager
+ .getValueIndex(SettingsManager.KEY_CAMERA_ID)]);
+ mFrontBackSwitcher.setVisibility(View.VISIBLE);
+ mFrontBackSwitcher.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_CAMERA_ID);
+ if (value == null)
+ return;
+
+ int index = mSettingsManager.getValueIndex(SettingsManager.KEY_CAMERA_ID);
+ CharSequence[] entries = mSettingsManager.getEntries(SettingsManager.KEY_CAMERA_ID);
+ index = (index + 1) % entries.length;
+ mSettingsManager.setValueIndex(SettingsManager.KEY_CAMERA_ID, index);
+ int[] largeIcons = mSettingsManager.getResource(SettingsManager.KEY_CAMERA_ID,
+ SettingsManager.RESOURCE_TYPE_LARGEICON);
+ ((ImageView) v).setImageResource(largeIcons[index]);
+ }
+ });
}
- @Override
- public void hideGpsOnScreenIndicator() {
+ public void initSceneModeButton() {
+ mSceneModeSwitcher.setVisibility(View.INVISIBLE);
+ String value = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
+ if (value == null) return;
+ updateSceneModeIcon();
+ mSceneModeSwitcher.setVisibility(View.VISIBLE);
+ mSceneModeSwitcher.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ addSceneMode();
+ ViewGroup menuLayout = getSceneAndFilterLayout();
+ if (menuLayout != null) {
+ View view = menuLayout.getChildAt(0);
+ adjustOrientation();
+ animateSlideIn(view, mSceneAndFilterMenuSize, false);
+ }
+ }
+ });
}
- public void overrideSettings(final String... keyvalues) {
- if (mMenu == null)
- return;
- mMenu.overrideSettings(keyvalues);
+ public void initFilterModeButton() {
+ mFilterModeSwitcher.setVisibility(View.INVISIBLE);
+ String value = mSettingsManager.getValue(SettingsManager.KEY_COLOR_EFFECT);
+ if (value == null) return;
+ changeFilterModeControlIcon(value);
+
+ updateFilterModeIcon(!mSettingsManager.isOverriden(SettingsManager.KEY_COLOR_EFFECT));
+ mFilterModeSwitcher.setVisibility(View.VISIBLE);
+ mFilterModeSwitcher.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ addFilterMode();
+ ViewGroup menuLayout = getSceneAndFilterLayout();
+ if (menuLayout != null) {
+ View view = getSceneAndFilterLayout().getChildAt(0);
+ adjustOrientation();
+ animateSlideIn(view, mSceneAndFilterMenuSize, false);
+ }
+ }
+ });
}
- public void enableGestures(boolean enable) {
- if (mGestures != null) {
- mGestures.setEnabled(enable);
+ public void setSwitcherIndex() {
+ mSwitcher.setCurrentIndex(ModuleSwitcher.PHOTO_MODULE_INDEX);
+ }
+
+ public void addSceneMode() {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
+ if (value == null) return;
+
+ int rotation = CameraUtil.getDisplayRotation(mActivity);
+ boolean mIsDefaultToPortrait = CameraUtil.isDefaultToPortrait(mActivity);
+ if (!mIsDefaultToPortrait) {
+ rotation = (rotation + 90) % 360;
+ }
+ WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+
+ CharSequence[] entries = mSettingsManager.getEntries(SettingsManager.KEY_SCENE_MODE);
+
+ int[] thumbnails = mSettingsManager.getResource(SettingsManager.KEY_SCENE_MODE,
+ SettingsManager.RESOURCE_TYPE_THUMBNAIL);
+ Resources r = mActivity.getResources();
+ int height = (int) (r.getDimension(R.dimen.scene_mode_height) + 2
+ * r.getDimension(R.dimen.scene_mode_padding) + 1);
+ int width = (int) (r.getDimension(R.dimen.scene_mode_width) + 2
+ * r.getDimension(R.dimen.scene_mode_padding) + 1);
+
+ int gridRes;
+ boolean portrait = (rotation == 0) || (rotation == 180);
+ int size = height;
+ if (portrait) {
+ gridRes = R.layout.vertical_grid;
+ size = width;
+ } else {
+ gridRes = R.layout.horiz_grid;
+ }
+ mSceneAndFilterMenuSize = size;
+ hideUI();
+
+ LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ FrameLayout gridOuterLayout = (FrameLayout) inflater.inflate(
+ gridRes, null, false);
+
+ removeSceneAndFilterMenu(false);
+ mSceneAndFilterMenuStatus = SCENE_AND_FILTER_MENU_ON;
+ mSceneAndFilterMenuMode = MODE_SCENE;
+ mSceneAndFilterLayout = new LinearLayout(mActivity);
+ ViewGroup.LayoutParams params = null;
+ if (portrait) {
+ params = new ViewGroup.LayoutParams(size, FrameLayout.LayoutParams.MATCH_PARENT);
+ mSceneAndFilterLayout.setLayoutParams(params);
+ ((ViewGroup) mRootView).addView(mSceneAndFilterLayout);
+ } else {
+ params = new ViewGroup.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, size);
+ mSceneAndFilterLayout.setLayoutParams(params);
+ ((ViewGroup) mRootView).addView(mSceneAndFilterLayout);
+ mSceneAndFilterLayout.setY(display.getHeight() - size);
+ }
+ gridOuterLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams
+ .MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
+ LinearLayout gridLayout = (LinearLayout) gridOuterLayout.findViewById(R.id.layout);
+
+ final View[] views = new View[entries.length];
+ int init = mSettingsManager.getValueIndex(SettingsManager.KEY_SCENE_MODE);
+ for (int i = 0; i < entries.length; i++) {
+ RotateLayout sceneBox = (RotateLayout) inflater.inflate(
+ R.layout.scene_mode_view, null, false);
+
+ ImageView imageView = (ImageView) sceneBox.findViewById(R.id.image);
+ TextView label = (TextView) sceneBox.findViewById(R.id.label);
+ final int j = i;
+
+ sceneBox.setOnTouchListener(new View.OnTouchListener() {
+ private long startTime;
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ startTime = System.currentTimeMillis();
+ } else if (event.getAction() == MotionEvent.ACTION_UP) {
+ if (System.currentTimeMillis() - startTime < CLICK_THRESHOLD) {
+ for (View v1 : views) {
+ v1.setBackgroundResource(R.drawable.scene_mode_view_border);
+ }
+ View border = v.findViewById(R.id.border);
+ border.setBackgroundResource(R.drawable.scene_mode_view_border_selected);
+ updateSceneModeIcon(j);
+ mSettingsManager.setValueIndex(SettingsManager.KEY_SCENE_MODE, j);
+ removeSceneAndFilterMenu(true);
+ }
+ }
+ return true;
+ }
+ });
+
+ View border = sceneBox.findViewById(R.id.border);
+ views[j] = border;
+ if (i == init)
+ border.setBackgroundResource(R.drawable.scene_mode_view_border_selected);
+
+ imageView.setImageResource(thumbnails[i]);
+ label.setText(entries[i]);
+ gridLayout.addView(sceneBox);
}
+ mSceneAndFilterLayout.addView(gridOuterLayout);
}
- // forward from preview gestures to controller
- @Override
- public void onSingleTapUp(View view, int x, int y) {
- mController.onSingleTapUp(view, x, y);
+ public void updateSceneModeIcon() {
+ int[] thumbnails = mSettingsManager.getResource(SettingsManager.KEY_SCENE_MODE,
+ SettingsManager.RESOURCE_TYPE_THUMBNAIL);
+ int thumbnail = thumbnails[mSettingsManager.getValueIndex(SettingsManager
+ .KEY_SCENE_MODE)];
+ if (thumbnail == -1)
+ thumbnail = 0;
+ ((ImageView) mSceneModeSwitcher).setImageResource(thumbnail);
}
- public boolean onBackPressed() {
- if (mMenu != null && mMenu.handleBackKey()) {
- return true;
+ public void updateSceneModeIcon(int idx) {
+ int[] thumbnails = mSettingsManager.getResource(SettingsManager.KEY_SCENE_MODE,
+ SettingsManager.RESOURCE_TYPE_THUMBNAIL);
+ int thumbnail = thumbnails[idx];
+ if (thumbnail == -1)
+ thumbnail = 0;
+ ((ImageView) mSceneModeSwitcher).setImageResource(thumbnail);
+ }
+
+ public void addFilterMode() {
+ if (mSettingsManager.getValue(SettingsManager.KEY_COLOR_EFFECT) == null)
+ return;
+
+ int rotation = CameraUtil.getDisplayRotation(mActivity);
+ boolean mIsDefaultToPortrait = CameraUtil.isDefaultToPortrait(mActivity);
+ if (!mIsDefaultToPortrait) {
+ rotation = (rotation + 90) % 360;
}
+ WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ CharSequence[] entries = mSettingsManager.getEntries(SettingsManager.KEY_COLOR_EFFECT);
+
+ Resources r = mActivity.getResources();
+ int height = (int) (r.getDimension(R.dimen.filter_mode_height) + 2
+ * r.getDimension(R.dimen.filter_mode_padding) + 1);
+ int width = (int) (r.getDimension(R.dimen.filter_mode_width) + 2
+ * r.getDimension(R.dimen.filter_mode_padding) + 1);
+
+ int gridRes;
+ boolean portrait = (rotation == 0) || (rotation == 180);
+ int size = height;
+ if (portrait) {
+ gridRes = R.layout.vertical_grid;
+ size = width;
+ } else {
+ gridRes = R.layout.horiz_grid;
+ }
+ mSceneAndFilterMenuSize = size;
+ hideUI();
- if (mPieRenderer != null && mPieRenderer.showsItems()) {
- mPieRenderer.hide();
- return true;
+ int[] thumbnails = mSettingsManager.getResource(SettingsManager.KEY_COLOR_EFFECT,
+ SettingsManager.RESOURCE_TYPE_THUMBNAIL);
+ LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ FrameLayout gridOuterLayout = (FrameLayout) inflater.inflate(
+ gridRes, null, false);
+
+ removeSceneAndFilterMenu(false);
+ mSceneAndFilterMenuStatus = SCENE_AND_FILTER_MENU_ON;
+ mSceneAndFilterMenuMode = MODE_FILTER;
+ mSceneAndFilterLayout = new LinearLayout(mActivity);
+
+ ViewGroup.LayoutParams params = null;
+ if (portrait) {
+ params = new ViewGroup.LayoutParams(size, FrameLayout.LayoutParams.MATCH_PARENT);
+ mSceneAndFilterLayout.setLayoutParams(params);
+ ((ViewGroup) mRootView).addView(mSceneAndFilterLayout);
+ } else {
+ params = new ViewGroup.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, size);
+ mSceneAndFilterLayout.setLayoutParams(params);
+ ((ViewGroup) mRootView).addView(mSceneAndFilterLayout);
+ mSceneAndFilterLayout.setY(display.getHeight() - size);
}
- // In image capture mode, back button should:
- // 1) if there is any popup, dismiss them, 2) otherwise, get out of
- // image capture
- if (mController.isImageCaptureIntent()) {
- mController.onCaptureCancelled();
- return true;
- } else if (!mController.isCameraIdle()) {
- // ignore backs while we're taking a picture
- return true;
+ gridOuterLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams
+ .MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
+ LinearLayout gridLayout = (LinearLayout) gridOuterLayout.findViewById(R.id.layout);
+ final View[] views = new View[entries.length];
+
+ int init = mSettingsManager.getValueIndex(SettingsManager.KEY_COLOR_EFFECT);
+ for (int i = 0; i < entries.length; i++) {
+ RotateLayout filterBox = (RotateLayout) inflater.inflate(
+ R.layout.filter_mode_view, null, false);
+ ImageView imageView = (ImageView) filterBox.findViewById(R.id.image);
+ final int j = i;
+
+ filterBox.setOnTouchListener(new View.OnTouchListener() {
+ private long startTime;
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ startTime = System.currentTimeMillis();
+ } else if (event.getAction() == MotionEvent.ACTION_UP) {
+ if (System.currentTimeMillis() - startTime < CLICK_THRESHOLD) {
+ mSettingsManager.setValueIndex(SettingsManager
+ .KEY_COLOR_EFFECT, j);
+ for (View v1 : views) {
+ v1.setBackground(null);
+ }
+ ImageView image = (ImageView) v.findViewById(R.id.image);
+ image.setBackgroundColor(HIGHLIGHT_COLOR);
+ }
+ }
+ return true;
+ }
+ });
+
+ views[j] = imageView;
+ if (i == init)
+ imageView.setBackgroundColor(HIGHLIGHT_COLOR);
+ TextView label = (TextView) filterBox.findViewById(R.id.label);
+
+ imageView.setImageResource(thumbnails[i]);
+ label.setText(entries[i]);
+ gridLayout.addView(filterBox);
}
- if (mSwitcher != null && mSwitcher.showsPopup()) {
- mSwitcher.closePopup();
- return true;
+ mSceneAndFilterLayout.addView(gridOuterLayout);
+ }
+
+ private void changeFilterModeControlIcon(String value) {
+ int index;
+ if (value.equals("0")) {
+ index = 0;
} else {
- return false;
+ index = 1;
}
+ ImageView iv = (ImageView) mFilterModeSwitcher;
+ iv.setImageResource(mSettingsManager.getResource(SettingsManager
+ .KEY_COLOR_EFFECT, SettingsManager.RESOURCE_TYPE_LARGEICON)[index]);
}
- public void onPreviewFocusChanged(boolean previewFocused) {
- if (previewFocused) {
- showUI();
+ private void updateFilterModeIcon(boolean enable) {
+ buttonSetEnabled(mFilterModeSwitcher, enable);
+ }
+
+ private void buttonSetEnabled(View v, boolean enable) {
+ v.setEnabled(enable);
+ if (v instanceof ViewGroup) {
+ View v2 = ((ViewGroup) v).getChildAt(0);
+ if (v2 != null)
+ v2.setEnabled(enable);
+ }
+ }
+
+ private void animateFadeOut(final View v, final int level) {
+ if (v == null || mSettingMenuState == SETTING_MENU_IN_ANIMATION)
+ return;
+ mSettingMenuState = SETTING_MENU_IN_ANIMATION;
+
+ ViewPropertyAnimator vp = v.animate();
+ vp.alpha(0f).setDuration(ANIMATION_DURATION);
+ vp.setListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finishSettingMenuAnimateOut(level);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ finishSettingMenuAnimateOut(level);
+ }
+ });
+ vp.start();
+ }
+
+ private void animateSlideOut(final View v, final int level) {
+ if (v == null || mSettingMenuState == SETTING_MENU_IN_ANIMATION)
+ return;
+ mSettingMenuState = SETTING_MENU_IN_ANIMATION;
+ ViewPropertyAnimator vp = v.animate();
+ if (View.LAYOUT_DIRECTION_RTL == TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault())) {
+ switch (getOrientation()) {
+ case 0:
+ vp.translationXBy(v.getWidth());
+ break;
+ case 90:
+ vp.translationYBy(-2 * v.getHeight());
+ break;
+ case 180:
+ vp.translationXBy(-2 * v.getWidth());
+ break;
+ case 270:
+ vp.translationYBy(v.getHeight());
+ break;
+ }
} else {
- hideUI();
+ switch (getOrientation()) {
+ case 0:
+ vp.translationXBy(-v.getWidth());
+ break;
+ case 90:
+ vp.translationYBy(2 * v.getHeight());
+ break;
+ case 180:
+ vp.translationXBy(2 * v.getWidth());
+ break;
+ case 270:
+ vp.translationYBy(-v.getHeight());
+ break;
+ }
}
- if (mGestures != null) {
- mGestures.setEnabled(previewFocused);
+ vp.setListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finishSettingMenuAnimateOut(level);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ finishSettingMenuAnimateOut(level);
+ }
+ });
+ vp.setDuration(ANIMATION_DURATION).start();
+ }
+
+ private void finishSettingMenuAnimateOut(int level) {
+ if (level == SETTING_MENU_LEVEL_ONE) {
+ mSettingMenuState = SETTING_MENU_ON;
+ removeSettingMenu(level, false);
+ cleanUpMenus();
+ } else if (level == SETTING_MENU_LEVEL_TWO) {
+ mSettingMenuState = SETTING_MENU_ON;
+ removeSettingMenu(level, false);
}
- if (mRenderOverlay != null) {
- // this can not happen in capture mode
- mRenderOverlay.setVisibility(previewFocused ? View.VISIBLE : View.GONE);
+ }
+
+ private void finishScenceAndFilterMenuAnimateOut() {
+ removeSceneAndFilterMenu(false);
+ cleanUpMenus();
+ }
+
+ public void animateFadeIn(View v) {
+ ViewPropertyAnimator vp = v.animate();
+ vp.alpha(0.85f).setDuration(ANIMATION_DURATION);
+ vp.start();
+ }
+
+ private void animateSlideOut(final View v) {
+ if (v == null || mSceneAndFilterMenuStatus == SCENE_AND_FILTER_MENU_IN_ANIMATION)
+ return;
+ mSceneAndFilterMenuStatus = SCENE_AND_FILTER_MENU_IN_ANIMATION;
+
+ ViewPropertyAnimator vp = v.animate();
+ if (View.LAYOUT_DIRECTION_RTL == TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault())) {
+ vp.translationXBy(v.getWidth()).setDuration(ANIMATION_DURATION);
+ } else {
+ vp.translationXBy(-v.getWidth()).setDuration(ANIMATION_DURATION);
}
- if (mPieRenderer != null) {
- mPieRenderer.setBlockFocus(!previewFocused);
+ vp.setListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finishScenceAndFilterMenuAnimateOut();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ finishScenceAndFilterMenuAnimateOut();
+ }
+ });
+ vp.start();
+ }
+
+ public void animateSlideIn(View v, int delta, boolean forcePortrait) {
+ int orientation = getOrientation();
+ if (!forcePortrait)
+ orientation = 0;
+
+ ViewPropertyAnimator vp = v.animate();
+ float dest;
+ if (View.LAYOUT_DIRECTION_RTL == TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault())) {
+ switch (orientation) {
+ case 0:
+ dest = v.getX();
+ v.setX(-(dest - delta));
+ vp.translationX(dest);
+ break;
+ case 90:
+ dest = v.getY();
+ v.setY(-(dest + delta));
+ vp.translationY(dest);
+ break;
+ case 180:
+ dest = v.getX();
+ v.setX(-(dest + delta));
+ vp.translationX(dest);
+ break;
+ case 270:
+ dest = v.getY();
+ v.setY(-(dest - delta));
+ vp.translationY(dest);
+ break;
+ }
+ } else {
+ switch (orientation) {
+ case 0:
+ dest = v.getX();
+ v.setX(dest - delta);
+ vp.translationX(dest);
+ break;
+ case 90:
+ dest = v.getY();
+ v.setY(dest + delta);
+ vp.translationY(dest);
+ break;
+ case 180:
+ dest = v.getX();
+ v.setX(dest + delta);
+ vp.translationX(dest);
+ break;
+ case 270:
+ dest = v.getY();
+ v.setY(dest - delta);
+ vp.translationY(dest);
+ break;
+ }
}
- setShowMenu(previewFocused);
+ vp.setDuration(ANIMATION_DURATION).start();
}
- public ViewGroup getMenuLayout() {
- return mMenuLayout;
+ private void initializeSettingMenu() {
+ LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ mSettingMenu = (ListMenu) inflater.inflate(
+ R.layout.list_menu, null, false);
+
+ mSettingMenu.setSettingChangedListener(this);
+ mSettingMenu.setSettingsManager(mSettingsManager);
+
+ String[] keys = mSettingKeys;
+ if (mActivity.isDeveloperMenuEnabled()) {
+ keys = mDeveloperKeys;
+ String[] combined = new String[mSettingKeys.length + mDeveloperKeys.length];
+ int idx = 0;
+ for (String key: mSettingKeys) {
+ combined[idx++] = key;
+ }
+ for (String key: mDeveloperKeys) {
+ combined[idx++] = key;
+ }
+ keys = combined;
+ }
+ mSettingMenu.initializeForCamera2(keys);
+ }
+
+ public boolean isMenuBeingShown() {
+ return mSettingMenuState != SETTING_MENU_NONE;
+ }
+
+ public boolean isMenuBeingAnimated() {
+ return mSettingMenuState == SETTING_MENU_IN_ANIMATION;
+ }
+
+
+ public void showSettingMenu() {
+ if (isMenuBeingShown() || CameraControls.isAnimating()) {
+ return;
+ }
+ if (mSettingMenu == null) {
+ initializeSettingMenu();
+ }
+ showSettingMenu(SETTING_MENU_LEVEL_ONE, true);
}
- public void showPopup(ListView popup, int level, boolean animate) {
+ private void showSettingMenu(int level, boolean animate) {
FrameLayout.LayoutParams params;
hideUI();
- popup.setVisibility(View.VISIBLE);
- if (level == 1) {
+ mSettingMenu.setVisibility(View.VISIBLE);
+ mSettingMenuState = SETTING_MENU_ON;
+ if (level == SETTING_MENU_LEVEL_ONE) {
+ mSettingMenuLevel = SETTING_MENU_LEVEL_ONE;
if (mMenuLayout == null) {
mMenuLayout = new RotateLayout(mActivity, null);
if (mRootView.getLayoutDirection() != View.LAYOUT_DIRECTION_RTL) {
- params = new FrameLayout.LayoutParams(
- CameraActivity.SETTING_LIST_WIDTH_1, LayoutParams.WRAP_CONTENT,
- Gravity.LEFT | Gravity.TOP);
+ params = new FrameLayout.LayoutParams(CameraActivity.SETTING_LIST_WIDTH_1,
+ FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP);
} else {
- params = new FrameLayout.LayoutParams(
- CameraActivity.SETTING_LIST_WIDTH_1, LayoutParams.WRAP_CONTENT,
- Gravity.RIGHT | Gravity.TOP);
+ params = new FrameLayout.LayoutParams(CameraActivity.SETTING_LIST_WIDTH_1,
+ FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.RIGHT | Gravity.TOP);
}
mMenuLayout.setLayoutParams(params);
((ViewGroup) mRootView).addView(mMenuLayout);
}
mMenuLayout.setOrientation(mOrientation, true);
- mMenuLayout.addView(popup);
- }
- if (level == 2) {
+ mMenuLayout.addView(mSettingMenu);
+ } else if (level == SETTING_MENU_LEVEL_TWO) {
+ mSettingMenuLevel = SETTING_MENU_LEVEL_TWO;
if (mSubMenuLayout == null) {
mSubMenuLayout = new RotateLayout(mActivity, null);
((ViewGroup) mRootView).addView(mSubMenuLayout);
}
if (mRootView.getLayoutDirection() != View.LAYOUT_DIRECTION_RTL) {
- params = new FrameLayout.LayoutParams(
- CameraActivity.SETTING_LIST_WIDTH_2, LayoutParams.WRAP_CONTENT,
- Gravity.LEFT | Gravity.TOP);
+ params = new FrameLayout.LayoutParams(CameraActivity.SETTING_LIST_WIDTH_2,
+ FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP);
} else {
- params = new FrameLayout.LayoutParams(
- CameraActivity.SETTING_LIST_WIDTH_2, LayoutParams.WRAP_CONTENT,
- Gravity.RIGHT | Gravity.TOP);
+ params = new FrameLayout.LayoutParams(CameraActivity.SETTING_LIST_WIDTH_2,
+ FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.RIGHT | Gravity.TOP);
}
int screenHeight = (mOrientation == 0 || mOrientation == 180)
? mRootView.getHeight() : mRootView.getWidth();
- int height = ((ListSubMenu) popup).getPreCalculatedHeight();
- int yBase = ((ListSubMenu) popup).getYBase();
+ int height = mSettingSubMenu.getPreCalculatedHeight();
+ int yBase = mSettingSubMenu.getYBase();
int y = Math.max(0, yBase);
if (yBase + height > screenHeight)
y = Math.max(0, screenHeight - height);
@@ -518,111 +949,143 @@ public class CaptureUI implements PieListener,
mSubMenuLayout.setLayoutParams(params);
- mSubMenuLayout.addView(popup);
+ mSubMenuLayout.addView(mSettingSubMenu);
mSubMenuLayout.setOrientation(mOrientation, true);
}
if (animate) {
- if (level == 1)
- mMenu.animateSlideIn(mMenuLayout, CameraActivity.SETTING_LIST_WIDTH_1, true);
- if (level == 2)
- mMenu.animateFadeIn(popup);
- } else
- popup.setAlpha(0.85f);
+ if (level == SETTING_MENU_LEVEL_ONE) {
+ animateSlideIn(mMenuLayout, CameraActivity.SETTING_LIST_WIDTH_1, true);
+ }
+ if (level == SETTING_MENU_LEVEL_TWO) {
+ animateFadeIn(mSettingSubMenu);
+ }
+ } else {
+ if (level == SETTING_MENU_LEVEL_ONE) {
+ mMenuLayout.setAlpha(0.85f);
+ }
+ if (level == SETTING_MENU_LEVEL_TWO) {
+ mSettingSubMenu.setAlpha(0.85f);
+ }
+ }
}
- public void removeLevel2() {
- if (mSubMenuLayout != null) {
- View v = mSubMenuLayout.getChildAt(0);
- mSubMenuLayout.removeView(v);
- }
+ public void hideUIWhileCountDown() {
+ hideCameraControls(true);
+ mGestures.setZoomOnly(true);
}
- public void cleanupListview() {
- showUI();
- mActivity.setSystemBarsVisibility(false);
+ public void showUIAfterCountDown() {
+ hideCameraControls(false);
+ mGestures.setZoomOnly(false);
}
- public void dismissAllPopup() {
- if (mPopup != null && mPopup.isShowing()) {
- mPopup.dismiss();
- }
+ public void hideCameraControls(boolean hide) {
+ final int status = (hide) ? View.INVISIBLE : View.VISIBLE;
+ if (mMenuButton != null) mMenuButton.setVisibility(status);
+ if (mFrontBackSwitcher != null) mFrontBackSwitcher.setVisibility(status);
+ if (mSceneModeSwitcher != null) mSceneModeSwitcher.setVisibility(status);
+ if (mFilterModeSwitcher != null) mFilterModeSwitcher.setVisibility(status);
+ if (mSwitcher != null) mSwitcher.setVisibility(status);
}
- public void dismissLevel1() {
- if (mMenuLayout != null) {
- ((ViewGroup) mRootView).removeView(mMenuLayout);
- mMenuLayout = null;
- }
+ public void initializeControlByIntent() {
+ mThumbnail = (ImageView) mRootView.findViewById(R.id.preview_thumb);
+ mThumbnail.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!CameraControls.isAnimating() && !mModule.isTakingPicture())
+ mActivity.gotoGallery();
+ }
+ });
+ mMenuButton = mRootView.findViewById(R.id.menu);
+ mMenuButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showSettingMenu();
+ }
+ });
}
- public void dismissLevel2() {
- if (mSubMenuLayout != null) {
- ((ViewGroup) mRootView).removeView(mSubMenuLayout);
- mSubMenuLayout = null;
- }
+ public void doShutterAnimation() {
+ AnimationDrawable frameAnimation = (AnimationDrawable) mShutterButton.getDrawable();
+ frameAnimation.stop();
+ frameAnimation.start();
}
- public boolean sendTouchToPreviewMenu(MotionEvent ev) {
- return mPreviewMenuLayout.dispatchTouchEvent(ev);
+ public void showUI() {
+ if (!mUIhidden || isMenuBeingShown())
+ return;
+ mUIhidden = false;
+ mCameraControls.showUI();
}
- public boolean sendTouchToMenu(MotionEvent ev) {
- if (mMenuLayout != null) {
- View v = mMenuLayout.getChildAt(0);
- return v.dispatchTouchEvent(ev);
- }
- return false;
+ public void hideUI() {
+ mSwitcher.closePopup();
+ if (mUIhidden)
+ return;
+ mUIhidden = true;
+ mCameraControls.hideUI();
}
- public void dismissSceneModeMenu() {
- if (mPreviewMenuLayout != null) {
- ((ViewGroup) mRootView).removeView(mPreviewMenuLayout);
- mPreviewMenuLayout = null;
- }
+ public void cleanUpMenus() {
+ showUI();
+ mActivity.setSystemBarsVisibility(false);
}
- public void onShowSwitcherPopup() {
- if (mPieRenderer != null && mPieRenderer.showsItems()) {
- mPieRenderer.hide();
- }
+ public boolean arePreviewControlsVisible() {
+ return !mUIhidden;
}
- private void setShowMenu(boolean show) {
- if (mOnScreenIndicators != null) {
- mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE);
- }
+ public void onOrientationChanged() {
+ removeSettingMenu(SETTING_MENU_LEVEL_TWO, false);
+ if (mSettingMenu != null)
+ mSettingMenu.resetHighlight();
}
- public boolean collapseCameraControls() {
- // TODO: Mode switcher should behave like a popup and should hide itself when there
- // is a touch outside of it.
- mSwitcher.closePopup();
- // Remove all the popups/dialog boxes
- boolean ret = false;
- if (mMenu != null) {
- mMenu.removeAllView();
- }
- if (mPopup != null) {
- dismissAllPopup();
- ret = true;
- }
- onShowSwitcherPopup();
- return ret;
+ public void removeAllSettingMenu(boolean animate) {
+ removeSettingMenu(SETTING_MENU_LEVEL_TWO, false);
+ removeSettingMenu(SETTING_MENU_LEVEL_ONE, animate);
}
- public void setDisplayOrientation(int orientation) {
- if ((mPreviewOrientation == -1 || mPreviewOrientation != orientation)
- && mMenu != null && mMenu.isPreviewMenuBeingShown()) {
- dismissSceneModeMenu();
- }
- mPreviewOrientation = orientation;
+ public void removeAllSettingMenu() {
+ removeAllSettingMenu(false);
}
- public boolean isShutterPressed() {
- return mShutterButton.isPressed();
+ public void removeSettingMenu(int level, boolean animate) {
+ if (mSettingMenuState == SETTING_MENU_NONE)
+ return;
+ if (!animate) {
+ if (level == SETTING_MENU_LEVEL_TWO) {
+ if (mSubMenuLayout != null) {
+ mSubMenuLayout.removeView(mSubMenuLayout.getChildAt(0));
+ mSubMenuLayout = null;
+ }
+ mSettingSubMenu = null;
+ mSettingMenuState = SETTING_MENU_ON;
+ mSettingMenuLevel = SETTING_MENU_LEVEL_ONE;
+ } else if (level == SETTING_MENU_LEVEL_ONE) {
+ mSettingMenu.resetHighlight();
+ if (mMenuLayout != null) {
+ mMenuLayout.removeView(mMenuLayout.getChildAt(0));
+ mMenuLayout = null;
+ }
+ mSettingMenu = null;
+ mSettingMenuState = SETTING_MENU_NONE;
+ cleanUpMenus();
+ }
+ } else {
+ if (level == SETTING_MENU_LEVEL_TWO) {
+ mSettingMenu.resetHighlight();
+ animateFadeOut(mSettingSubMenu, level);
+ } else if (level == SETTING_MENU_LEVEL_ONE) {
+ animateSlideOut(mSettingMenu, level);
+ }
+ }
}
- // shutter button handling
+ public void removeAllMenu() {
+ removeAllSettingMenu();
+ }
/**
* Enables or disables the shutter button.
@@ -633,29 +1096,36 @@ public class CaptureUI implements PieListener,
}
}
- public void pressShutterButton() {
- if (mShutterButton.isInTouchMode()) {
- mShutterButton.requestFocusFromTouch();
- } else {
- mShutterButton.requestFocus();
+ private boolean handleBackKeyOnMenu() {
+ if (mSceneAndFilterMenuStatus == SCENE_AND_FILTER_MENU_ON) {
+ removeSceneAndFilterMenu(true);
+ return true;
}
- mShutterButton.setPressed(true);
- }
-
- @Override
- public void onPieOpened(int centerX, int centerY) {
- setSwipingEnabled(false);
- // Close module selection menu when pie menu is opened.
- mSwitcher.closePopup();
+ if (mSettingMenuState == SETTING_MENU_NONE)
+ return false;
+ if (mSettingMenuState == SETTING_MENU_ON) {
+ removeSettingMenu(mSettingMenuLevel, true);
+ }
+ return true;
}
- @Override
- public void onPieClosed() {
- setSwipingEnabled(true);
- }
+ public boolean onBackPressed() {
+ if (handleBackKeyOnMenu()) return true;
+ if (mPieRenderer != null && mPieRenderer.showsItems()) {
+ mPieRenderer.hide();
+ return true;
+ }
- public void setSwipingEnabled(boolean enable) {
- mActivity.setSwipingEnabled(enable);
+ if (!mModule.isCameraIdle()) {
+ // ignore backs while we're taking a picture
+ return true;
+ }
+ if (mSwitcher != null && mSwitcher.showsPopup()) {
+ mSwitcher.closePopup();
+ return true;
+ } else {
+ return false;
+ }
}
public SurfaceHolder getSurfaceHolder() {
@@ -677,20 +1147,45 @@ public class CaptureUI implements PieListener,
}
}
- public void hideSurfaceView() {
- mSurfaceView.setVisibility(View.INVISIBLE);
+ private void initializeCountDown() {
+ mActivity.getLayoutInflater().inflate(R.layout.count_down_to_capture,
+ (ViewGroup) mRootView, true);
+ mCountDownView = (CountDownView) (mRootView.findViewById(R.id.count_down_to_capture));
+ mCountDownView.setCountDownFinishedListener((CountDownView.OnCountDownFinishedListener) mModule);
+ mCountDownView.bringToFront();
+ mCountDownView.setOrientation(mOrientation);
}
- public void showSurfaceView() {
- mSurfaceView.setVisibility(View.VISIBLE);
+ public boolean isCountingDown() {
+ return mCountDownView != null && mCountDownView.isCountingDown();
+ }
+
+ public void cancelCountDown() {
+ if (mCountDownView == null) return;
+ mCountDownView.cancelCountDown();
+ showUIAfterCountDown();
+ }
+
+ public void startCountDown(int sec, boolean playSound) {
+ if (mCountDownView == null) initializeCountDown();
+ mCountDownView.startCountDown(sec, playSound);
+ hideUIWhileCountDown();
}
public void onPause() {
- // Clear UI.
+ cancelCountDown();
collapseCameraControls();
}
- // focus UI implementation
+ public boolean collapseCameraControls() {
+ mSwitcher.closePopup();
+ // Remove all the popups/dialog boxes
+ boolean ret = false;
+ removeAllMenu();
+ mCameraControls.showRefocusToast(false);
+ return ret;
+ }
+
private FocusIndicator getFocusIndicator() {
return mPieRenderer;
}
@@ -703,10 +1198,6 @@ public class CaptureUI implements PieListener,
public void clearFaces() {
}
- public void setPreference(String key, String value) {
- mMenu.setPreference(key, value);
- }
-
@Override
public void clearFocus() {
FocusIndicator indicator = getFocusIndicator();
@@ -731,13 +1222,13 @@ public class CaptureUI implements PieListener,
}
@Override
- public void onFocusFailed(boolean timeout) {
- FocusIndicator indicator = getFocusIndicator();
- if (indicator != null) indicator.showFail(timeout);
+ public void onFocusFailed(boolean timeOut) {
+
}
@Override
public void pauseFaceDetection() {
+
}
@Override
@@ -754,11 +1245,20 @@ public class CaptureUI implements PieListener,
public void onFaceDetection(Face[] faces, CameraManager.CameraProxy camera) {
}
- @Override
- public void onDisplayChanged() {
- Log.d(TAG, "Device flip detected.");
- mCameraControls.checkLayoutFlip();
- mController.updateCameraOrientation();
+ 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 void adjustOrientation() {
+ setOrientation(mOrientation, true);
}
public void setOrientation(int orientation, boolean animation) {
@@ -768,8 +1268,8 @@ public class CaptureUI implements PieListener,
mMenuLayout.setOrientation(orientation, animation);
if (mSubMenuLayout != null)
mSubMenuLayout.setOrientation(orientation, animation);
- if (mPreviewMenuLayout != null) {
- ViewGroup vg = (ViewGroup) mPreviewMenuLayout.getChildAt(0);
+ if (mSceneAndFilterLayout != null) {
+ ViewGroup vg = (ViewGroup) mSceneAndFilterLayout.getChildAt(0);
if (vg != null)
vg = (ViewGroup) vg.getChildAt(0);
if (vg != null) {
@@ -779,33 +1279,151 @@ public class CaptureUI implements PieListener,
}
}
}
-
+ if (mCountDownView != null)
+ mCountDownView.setOrientation(orientation);
RotateTextToast.setOrientation(orientation);
if (mZoomRenderer != null) {
mZoomRenderer.setOrientation(orientation);
}
}
- public Point getSurfaceViewSize() {
- Point point = new Point();
- if (mSurfaceView != null) point.set(mSurfaceView.getWidth(), mSurfaceView.getHeight());
- return point;
+ public int getOrientation() {
+ return mOrientation;
}
- public Point getSurfaceView2Size() {
- Point point = new Point();
- if (mSurfaceView2 != null) point.set(mSurfaceView2.getWidth(), mSurfaceView2.getHeight());
- return point;
+ @Override
+ public void showGpsOnScreenIndicator(boolean hasSignal) {
+
}
- public int getOrientation() {
- return mOrientation;
+ @Override
+ public void hideGpsOnScreenIndicator() {
+
+ }
+
+ @Override
+ public void onSingleTapUp(View view, int x, int y) {
+ mModule.onSingleTapUp(view, x, y);
+ }
+
+ public void onPreviewFocusChanged(boolean previewFocused) {
+ if (previewFocused) {
+ showUI();
+ } else {
+ hideUI();
+ }
+ if (mGestures != null) {
+ mGestures.setEnabled(previewFocused);
+ }
+ if (mRenderOverlay != null) {
+ // this can not happen in capture mode
+ mRenderOverlay.setVisibility(previewFocused ? View.VISIBLE : View.GONE);
+ }
+ if (mPieRenderer != null) {
+ mPieRenderer.setBlockFocus(!previewFocused);
+ }
+ if (!previewFocused && mCountDownView != null) mCountDownView.cancelCountDown();
+ }
+
+ public ViewGroup getMenuLayout() {
+ return mMenuLayout;
+ }
+
+ public boolean isShutterPressed() {
+ return mShutterButton.isPressed();
+ }
+
+ public void pressShutterButton() {
+ if (mShutterButton.isInTouchMode()) {
+ mShutterButton.requestFocusFromTouch();
+ } else {
+ mShutterButton.requestFocus();
+ }
+ mShutterButton.setPressed(true);
+ }
+
+ @Override
+ public void onSettingsChanged(List<SettingsManager.SettingState> settings) {
+ for (SettingsManager.SettingState setting : settings) {
+ String key = setting.key;
+ SettingsManager.Values values = setting.values;
+ String value = (values.overriddenValue == null) ? values.value : values.overriddenValue;
+ switch (key) {
+ case SettingsManager.KEY_COLOR_EFFECT:
+ changeFilterModeControlIcon(value);
+ updateFilterModeIcon(values.overriddenValue == null);
+ break;
+ }
+ }
+ }
+
+ public void hideSurfaceView() {
+ mSurfaceView.setVisibility(View.INVISIBLE);
+ mSurfaceView2.setVisibility(View.INVISIBLE);
+ }
+
+ public void showSurfaceView() {
+ mSurfaceView.setVisibility(View.VISIBLE);
+ mSurfaceView2.setVisibility(View.VISIBLE);
+ }
+
+ public void setSurfaceView(boolean show) {
+ if (show) {
+ mSurfaceView2.setVisibility(View.VISIBLE);
+ } else {
+ mSurfaceView2.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ public void setPreviewSize(int width, int height) {
+ mSurfaceView.getHolder().setFixedSize(width, height);
+ mCameraControls.setPreviewRatio(0, true);
+ mSurfaceView.setAspectRatio(height, width);
+ }
+
+ @Override
+ public void onSettingChanged(ListPreference pref) {
+ removeAllSettingMenu();
+ }
+
+ @Override
+ public void onPreferenceClicked(ListPreference pref) {
+ onPreferenceClicked(pref, 0);
+ }
+
+ @Override
+ public void onPreferenceClicked(ListPreference pref, int y) {
+ LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ removeSettingMenu(SETTING_MENU_LEVEL_TWO, false);
+ mSettingSubMenu = (ListSubMenu) inflater.inflate(R.layout.list_sub_menu, null, false);
+ mSettingSubMenu.initialize(pref, y);
+ mSettingSubMenu.setSettingChangedListener(mSettingMenu);
+ mSettingSubMenu.setAlpha(0f);
+
+ if (mSettingMenuState == SETTING_MENU_ON) {
+ if (mSettingMenuLevel == SETTING_MENU_LEVEL_TWO) {
+ showSettingMenu(SETTING_MENU_LEVEL_TWO, false);
+ } else if (mSettingMenuLevel == SETTING_MENU_LEVEL_ONE) {
+ showSettingMenu(SETTING_MENU_LEVEL_TWO, true);
+ }
+ }
+ }
+
+ @Override
+ public void onListMenuTouched() {
+ removeSettingMenu(SETTING_MENU_LEVEL_TWO, false);
+ }
+
+ @Override
+ public void onListPrefChanged(ListPreference pref) {
+ removeAllSettingMenu();
}
private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener {
@Override
public void onZoomValueChanged(float mZoomValue) {
- mController.onZoomChanged(mZoomValue);
+ mModule.onZoomChanged(mZoomValue);
if (mZoomRenderer != null) {
mZoomRenderer.setZoom(mZoomValue);
}
diff --git a/src/com/android/camera/ComboPreferences.java b/src/com/android/camera/ComboPreferences.java
index d0039ab9e..7d4d92087 100644
--- a/src/com/android/camera/ComboPreferences.java
+++ b/src/com/android/camera/ComboPreferences.java
@@ -152,7 +152,13 @@ public class ComboPreferences implements
|| key.equals(CameraSettings.KEY_TIMER)
|| key.equals(CameraSettings.KEY_TIMER_SOUND_EFFECTS)
|| key.equals(CameraSettings.KEY_PHOTOSPHERE_PICTURESIZE)
- || key.equals(CameraSettings.KEY_CAMERA_SAVEPATH);
+ || key.equals(CameraSettings.KEY_CAMERA_SAVEPATH)
+ || key.equals(SettingsManager.KEY_CAMERA2)
+ || key.equals(SettingsManager.KEY_INITIAL_CAMERA)
+ || key.equals(SettingsManager.KEY_CAMERA_ID)
+ || key.equals(SettingsManager.KEY_MONO_ONLY)
+ || key.equals(SettingsManager.KEY_MONO_PREVIEW)
+ || key.equals(SettingsManager.KEY_CLEARSIGHT);
}
@Override
diff --git a/src/com/android/camera/ListPreference.java b/src/com/android/camera/ListPreference.java
index c79d18c1a..000baf125 100644
--- a/src/com/android/camera/ListPreference.java
+++ b/src/com/android/camera/ListPreference.java
@@ -38,10 +38,11 @@ public class ListPreference extends CameraPreference {
private static final String TAG = "ListPreference";
private final String mKey;
private String mValue;
- private final CharSequence[] mDefaultValues;
+ public final CharSequence[] mDefaultValues;
private CharSequence[] mEntries;
private CharSequence[] mEntryValues;
+ private CharSequence[] mDependencyList;
private CharSequence[] mLabels;
private boolean mLoaded = false;
@@ -73,6 +74,8 @@ public class ListPreference extends CameraPreference {
R.styleable.ListPreference_entryValues));
setLabels(a.getTextArray(
R.styleable.ListPreference_labelList));
+ setDependencyList(a.getTextArray(
+ R.styleable.ListPreference_dependencyList));
a.recycle();
}
@@ -92,6 +95,10 @@ public class ListPreference extends CameraPreference {
return mLabels;
}
+ public CharSequence[] getDependencyList() {
+ return mDependencyList;
+ }
+
public void setEntries(CharSequence entries[]) {
mEntries = entries == null ? new CharSequence[0] : entries;
}
@@ -104,6 +111,10 @@ public class ListPreference extends CameraPreference {
mLabels = labels == null ? new CharSequence[0] : labels;
}
+ public void setDependencyList(CharSequence dependencyList[]) {
+ mDependencyList = dependencyList == null ? new CharSequence[0] : dependencyList;
+ }
+
public String getValue() {
if (!mLoaded) {
mValue = getSharedPreferences().getString(mKey,
@@ -113,6 +124,10 @@ public class ListPreference extends CameraPreference {
return mValue;
}
+ public String getOffValue() {
+ return mEntryValues[0].toString();
+ }
+
// Find the first value in mDefaultValues which is supported.
private String findSupportedDefaultValue() {
for (int i = 0; i < mDefaultValues.length; i++) {
diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java
index b9ecdcc8d..083b019c4 100644
--- a/src/com/android/camera/PhotoMenu.java
+++ b/src/com/android/camera/PhotoMenu.java
@@ -234,7 +234,7 @@ public class PhotoMenu extends MenuController
CameraSettings.KEY_MANUAL_EXPOSURE,
CameraSettings.KEY_MANUAL_WB,
CameraSettings.KEY_MANUAL_FOCUS,
- CameraSettings.KEY_CAMERA2
+ SettingsManager.KEY_CAMERA2
};
initSwitchItem(CameraSettings.KEY_CAMERA_ID, mFrontBackSwitcher);
@@ -731,6 +731,8 @@ public class PhotoMenu extends MenuController
mActivity.getString(R.string.pref_camera_advanced_feature_default));
popup1.setPreferenceEnabled(CameraSettings.KEY_ADVANCED_FEATURES, false);
+ popup1.setPreferenceEnabled(CameraSettings.KEY_INSTANT_CAPTURE, false);
+
if(!TsMakeupManager.HAS_TS_MAKEUP) {
if (mHdrSwitcher.getVisibility() == View.VISIBLE) {
buttonSetEnabled(mHdrSwitcher, true);
@@ -752,7 +754,7 @@ public class PhotoMenu extends MenuController
popup1.setPreferenceEnabled(CameraSettings.KEY_COLOR_EFFECT, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_TOUCH_AF_AEC, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_SCENE_MODE, false);
-
+ popup1.setPreferenceEnabled(CameraSettings.KEY_INSTANT_CAPTURE, false);
setPreference(CameraSettings.KEY_CAMERA_HDR, mSettingOff);
if(!TsMakeupManager.HAS_TS_MAKEUP) {
if (mHdrSwitcher.getVisibility() == View.VISIBLE) {
@@ -1467,17 +1469,9 @@ public class PhotoMenu extends MenuController
updateFilterModeIcon(pref, pref);
super.onSettingChanged(pref);
- if (same(pref, CameraSettings.KEY_CAMERA2, "enable")) {
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(mActivity);
- prefs.edit().putBoolean(CameraSettings.KEY_CAMERA2, true).apply();
- CameraActivity.CAMERA_2_ON = true;
+ if (same(pref, SettingsManager.KEY_CAMERA2, "enable")) {
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;
+ } else if (notSame(pref, SettingsManager.KEY_CAMERA2, "enable")) {
mActivity.onModuleSelected(ModuleSwitcher.PHOTO_MODULE_INDEX);
}
}
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index 7324484ae..d6caf7eb8 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -881,8 +881,7 @@ public class PhotoModule
}
// Initialize location service.
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
+ boolean recordLocation = RecordLocationPreference.get(mPreferences);
mLocationManager.recordLocation(recordLocation);
mUI.initializeFirstTime();
@@ -913,8 +912,7 @@ public class PhotoModule
// onResume.
private void initializeSecondTime() {
// Start location update if needed.
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
+ boolean recordLocation = RecordLocationPreference.get(mPreferences);
mLocationManager.recordLocation(recordLocation);
MediaSaveService s = mActivity.getMediaSaveService();
if (s != null) {
@@ -2939,10 +2937,10 @@ public class PhotoModule
CameraSettings.KEY_INSTANT_CAPTURE,
mActivity.getString(R.string.pref_camera_instant_capture_default));
if (instantCapture.equals(mActivity.getString(
- R.string.pref_camera_instant_capture_value_enable))) {
- return true;
+ R.string.pref_camera_instant_capture_value_disable))) {
+ return false;
}
- return false;
+ return true;
}
private void qcomUpdateAdvancedFeatures(String ubiFocus,
@@ -3225,23 +3223,6 @@ public class PhotoModule
mParameters.set(CameraSettings.KEY_SNAPCAM_HDR_NEED_1X, hdrNeed1x);
}
- // Set Instant Capture
- String instantCapture = mPreferences.getString(
- CameraSettings.KEY_INSTANT_CAPTURE,
- mActivity.getString(R.string.pref_camera_instant_capture_default));
-
- if (instantCapture.equals(mActivity.getString(
- R.string.pref_camera_instant_capture_value_enable))) {
- if (!mInstantCaptureSnapShot) {
- // Disable instant capture after first snapshot is taken
- instantCapture = mActivity.getString(
- R.string.pref_camera_instant_capture_value_disable);
- }
- }
- Log.v(TAG, "Instant capture = " + instantCapture + ", mInstantCaptureSnapShot = "
- + mInstantCaptureSnapShot);
- mParameters.set(CameraSettings.KEY_QC_INSTANT_CAPTURE, instantCapture);
-
// Set Advanced features.
String advancedFeature = mPreferences.getString(
CameraSettings.KEY_ADVANCED_FEATURES,
@@ -3491,6 +3472,39 @@ public class PhotoModule
}
}
+ // Set Instant Capture
+ String instantCapture = mPreferences.getString(
+ CameraSettings.KEY_INSTANT_CAPTURE,
+ mActivity.getString(R.string.pref_camera_instant_capture_default));
+
+ if (!instantCapture.equals(mActivity.getString(
+ R.string.pref_camera_instant_capture_value_disable))) {
+ if (zsl.equals("on") &&
+ advancedFeature.equals(mActivity.getString(R.string.pref_camera_advanced_feature_value_none))) {
+ if (!mInstantCaptureSnapShot) {
+ // Disable instant capture after first snapshot is taken
+ instantCapture = mActivity.getString(
+ R.string.pref_camera_instant_capture_value_disable);
+ }
+ } else {
+ mParameters.set(CameraSettings.KEY_QC_INSTANT_CAPTURE,
+ mActivity.getString(R.string.pref_camera_instant_capture_value_disable));
+ instantCapture = mActivity.getString(
+ R.string.pref_camera_instant_capture_value_disable);
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mUI.overrideSettings(CameraSettings.KEY_INSTANT_CAPTURE,
+ mActivity.getString(R.string.pref_camera_instant_capture_value_disable));
+ }
+ });
+ }
+ }
+ Log.v(TAG, "Instant capture = " + instantCapture + ", mInstantCaptureSnapShot = "
+ + mInstantCaptureSnapShot);
+ mParameters.set(CameraSettings.KEY_QC_INSTANT_CAPTURE, instantCapture);
+
+
//Set Histogram
String histogram = mPreferences.getString(
CameraSettings.KEY_HISTOGRAM,
@@ -4546,8 +4560,7 @@ public class PhotoModule
// ignore the events after "onPause()"
if (mPaused) return;
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
+ boolean recordLocation = RecordLocationPreference.get(mPreferences);
mLocationManager.recordLocation(recordLocation);
if(needRestart()){
Log.v(TAG, "Restarting Preview... Camera Mode Changed");
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 250f265b2..09e24a710 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -767,8 +767,7 @@ public class PhotoUI implements PieListener,
// make sure the correct value was found
// otherwise use auto index
mOnScreenIndicators.updateWBIndicator(wbIndex < 0 ? 2 : wbIndex);
- boolean location = RecordLocationPreference.get(
- prefs, mActivity.getContentResolver());
+ boolean location = RecordLocationPreference.get(prefs);
mOnScreenIndicators.updateLocationIndicator(location);
}
@@ -1068,7 +1067,9 @@ public class PhotoUI implements PieListener,
mReviewImage.setVisibility(View.GONE);
mOnScreenIndicators.setVisibility(View.VISIBLE);
mMenuButton.setVisibility(View.VISIBLE);
- mMenu.hideTopMenu(false);
+ if (mMenu != null) {
+ mMenu.hideTopMenu(false);
+ }
CameraUtil.fadeOut(mReviewDoneButton);
mShutterButton.setVisibility(View.VISIBLE);
CameraUtil.fadeOut(mReviewRetakeButton);
diff --git a/src/com/android/camera/PreviewGestures.java b/src/com/android/camera/PreviewGestures.java
index 4f26240ea..48bfb7e58 100644
--- a/src/com/android/camera/PreviewGestures.java
+++ b/src/com/android/camera/PreviewGestures.java
@@ -55,7 +55,7 @@ public class PreviewGestures
private boolean mEnabled;
private boolean mZoomOnly;
private GestureDetector mGestureDetector;
- private CaptureMenu mCaptureMenu;
+ private CaptureUI mCaptureUI;
private PhotoMenu mPhotoMenu;
private VideoMenu mVideoMenu;
private boolean waitUntilNextDown;
@@ -95,8 +95,8 @@ public class PreviewGestures
orientation = mPhotoMenu.getOrientation();
else if (mVideoMenu != null)
orientation = mVideoMenu.getOrientation();
- else if (mCaptureMenu != null)
- orientation = mCaptureMenu.getOrientation();
+ else if (mCaptureUI != null)
+ orientation = mCaptureUI.getOrientation();
if (isLeftSwipe(orientation, deltaX, deltaY)) {
waitUntilNextDown = true;
@@ -104,8 +104,8 @@ public class PreviewGestures
mPhotoMenu.openFirstLevel();
else if (mVideoMenu != null && !mVideoMenu.isMenuBeingShown())
mVideoMenu.openFirstLevel();
- else if (mCaptureMenu != null && !mCaptureMenu.isMenuBeingShown())
- mCaptureMenu.openFirstLevel();
+ else if (mCaptureUI != null && !mCaptureUI.isMenuBeingShown())
+ mCaptureUI.showSettingMenu();
return true;
} else {
return onSingleTapUp(e2);
@@ -161,8 +161,8 @@ public class PreviewGestures
return mEnabled;
}
- public void setCaptureMenu(CaptureMenu menu) {
- mCaptureMenu = menu;
+ public void setCaptureUI(CaptureUI ui) {
+ mCaptureUI = ui;
}
public void setPhotoMenu(PhotoMenu menu) {
@@ -173,10 +173,6 @@ public class PreviewGestures
mVideoMenu = menu;
}
- public CaptureMenu getCaptureMenu() {
- return mCaptureMenu;
- }
-
public PhotoMenu getPhotoMenu() {
return mPhotoMenu;
}
@@ -213,16 +209,17 @@ public class PreviewGestures
return sendToPie(m);
}
- if (mCaptureMenu != null) {
- if (mCaptureMenu.isMenuBeingShown()) {
- if (!mCaptureMenu.isMenuBeingAnimated()) {
+ if (mCaptureUI != null) {
+ if (mCaptureUI.isMenuBeingShown()) {
+ if (!mCaptureUI.isMenuBeingAnimated()) {
waitUntilNextDown = true;
- mCaptureMenu.closeView();
+ mCaptureUI.removeAllSettingMenu(true);
}
return true;
}
- if (mCaptureMenu.isPreviewMenuBeingShown()) {
+ if (mCaptureUI.isPreviewMenuBeingShown()) {
waitUntilNextDown = true;
+ mCaptureUI.removeSceneAndFilterMenu(true);
return true;
}
}
diff --git a/src/com/android/camera/RecordLocationPreference.java b/src/com/android/camera/RecordLocationPreference.java
index 9992afabb..b88f5e4ed 100644
--- a/src/com/android/camera/RecordLocationPreference.java
+++ b/src/com/android/camera/RecordLocationPreference.java
@@ -40,11 +40,10 @@ public class RecordLocationPreference extends IconListPreference {
@Override
public String getValue() {
- return get(getSharedPreferences(), mResolver) ? VALUE_ON : VALUE_OFF;
+ return get(getSharedPreferences()) ? VALUE_ON : VALUE_OFF;
}
- public static boolean get(
- SharedPreferences pref, ContentResolver resolver) {
+ public static boolean get(SharedPreferences pref) {
String value = pref.getString(
CameraSettings.KEY_RECORD_LOCATION, VALUE_NONE);
return VALUE_ON.equals(value);
diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java
new file mode 100644
index 000000000..215ab8436
--- /dev/null
+++ b/src/com/android/camera/SettingsManager.java
@@ -0,0 +1,813 @@
+/*
+ * 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.content.Context;
+import android.graphics.ImageFormat;
+import android.graphics.Rect;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.util.Log;
+import android.util.Range;
+import android.util.Rational;
+import android.util.Size;
+
+import com.android.camera.imageprocessor.filter.OptizoomFilter;
+import com.android.camera.ui.ListMenu;
+
+import org.codeaurora.snapcam.R;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class SettingsManager implements ListMenu.SettingsListener {
+ public static final int RESOURCE_TYPE_THUMBNAIL = 0;
+ public static final int RESOURCE_TYPE_LARGEICON = 1;
+ // Custom-Scenemodes start from 100
+ public static final int SCENE_MODE_DUAL_INT = 100;
+ public static final int SCENE_MODE_OPTIZOOM_INT = 101;
+ public static final String SCENE_MODE_DUAL_STRING = "100";
+ public static final String KEY_CAMERA_SAVEPATH = "pref_camera2_savepath_key";
+ public static final String KEY_RECORD_LOCATION = "pref_camera2_recordlocation_key";
+ public static final String KEY_JPEG_QUALITY = "pref_camera2_jpegquality_key";
+ public static final String KEY_FOCUS_MODE = "pref_camera2_focusmode_key";
+ public static final String KEY_FLASH_MODE = "pref_camera2_flashmode_key";
+ public static final String KEY_WHITE_BALANCE = "pref_camera2_whitebalance_key";
+ public static final String KEY_MAKEUP = "pref_camera2_makeup_key";
+ public static final String KEY_CAMERA2 = "pref_camera2_camera2_key";
+ 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_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";
+ public static final String KEY_REDEYE_REDUCTION = "pref_camera2_redeyereduction_key";
+ public static final String KEY_CAMERA_ID = "pref_camera2_id_key";
+ public static final String KEY_PICTURE_SIZE = "pref_camera2_picturesize_key";
+ public static final String KEY_ISO = "pref_camera2_iso_key";
+ public static final String KEY_EXPOSURE = "pref_camera2_exposure_key";
+ public static final String KEY_TIMER = "pref_camera2_timer_key";
+ public static final String KEY_LONGSHOT = "pref_camera2_longshot_key";
+ public static final String KEY_INITIAL_CAMERA = "pref_camera2_initial_camera_key";
+ private static final String TAG = "SnapCam_SettingsManager";
+ private static final List<CameraCharacteristics> mCharacteristics = new ArrayList<>();
+
+ private static SettingsManager sInstance;
+
+ private ArrayList<Listener> mListeners;
+ private Map<String, Values> mValuesMap;
+ private Context mContext;
+ private PreferenceGroup mPreferenceGroup;
+ private ComboPreferences mPreferences;
+ private Map<String, Set<String>> mDependendsOnMap;
+ private boolean mIsMonoCameraPresent = false;
+ private boolean mIsFrontCameraPresent = false;
+
+ private SettingsManager(Context context) {
+ mListeners = new ArrayList<>();
+ mContext = context;
+ mPreferences = new ComboPreferences(mContext);
+ CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal(), mContext);
+
+ CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+ try {
+ String[] cameraIdList = manager.getCameraIdList();
+ for (int i = 0; i < cameraIdList.length; i++) {
+ String cameraId = cameraIdList[i];
+ CameraCharacteristics characteristics
+ = manager.getCameraCharacteristics(cameraId);
+ Byte monoOnly = 0;
+ try {
+ monoOnly = characteristics.get(CaptureModule.MetaDataMonoOnlyKey);
+ }catch(Exception e) {
+ }
+ if (monoOnly == 1) {
+ CaptureModule.MONO_ID = i;
+ mIsMonoCameraPresent = true;
+ }
+ int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
+ if (facing == CameraCharacteristics.LENS_FACING_FRONT) {
+ CaptureModule.FRONT_ID = i;
+ mIsFrontCameraPresent = true;
+ }
+ mCharacteristics.add(i, characteristics);
+ }
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static SettingsManager createInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new SettingsManager(context);
+ }
+ return sInstance;
+ }
+
+ public static SettingsManager getInstance() {
+ return sInstance;
+ }
+
+ public List<String> getDisabledList() {
+ List<String> list = new ArrayList<>();
+ Set<String> keySet = mValuesMap.keySet();
+ for (String key : keySet) {
+ Values value = mValuesMap.get(key);
+ if (value.overriddenValue != null) {
+ list.add(key);
+ }
+ }
+ return list;
+ }
+
+ @Override
+ public void onSettingChanged(ListPreference pref) {
+ String key = pref.getKey();
+ List changed = checkDependencyAndUpdate(key);
+ if (changed == null) return;
+ notifyListeners(changed);
+ }
+
+ public void init() {
+ Log.d(TAG, "SettingsManager init");
+ int cameraId = CameraSettings.getInitialCameraId(mPreferences);
+ setLocalIdAndInitialize(cameraId);
+ }
+
+ public void reinit(int cameraId) {
+ Log.d(TAG, "SettingsManager reinit " + cameraId);
+ setLocalIdAndInitialize(cameraId);
+ }
+
+ private void setLocalIdAndInitialize(int cameraId) {
+ mPreferences.setLocalId(mContext, cameraId);
+ CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
+
+ PreferenceInflater inflater = new PreferenceInflater(mContext);
+ mPreferenceGroup =
+ (PreferenceGroup) inflater.inflate(R.xml.capture_preferences);
+ mValuesMap = new HashMap<>();
+ mDependendsOnMap = new HashMap<>();
+ filterPreferences(cameraId);
+ initDepedencyTable();
+ initializeValueMap();
+ }
+
+ private void initDepedencyTable() {
+ for (int i = 0; i < mPreferenceGroup.size(); i++) {
+ ListPreference pref = (ListPreference) mPreferenceGroup.get(i);
+ String baseKey = pref.getKey();
+ CharSequence[] dependencyList = null;
+ if (!specialDepedency(baseKey)) dependencyList = pref.getDependencyList();
+ else {
+ List<KeyValue> keyValue = getSpecialDependencyList(pref);
+ if (keyValue.size() > 0) {
+ dependencyList = new CharSequence[keyValue.size()];
+ int k = 0;
+ for (KeyValue kv: keyValue) {
+ dependencyList[k++] = kv.key;
+ }
+ }
+ pref.setDependencyList(dependencyList);
+ }
+ if (dependencyList != null) {
+ for (int j = 0; j < dependencyList.length; j++) {
+ String key = dependencyList[j].toString();
+ pref = mPreferenceGroup.findPreference(key);
+ if (pref == null) continue; //filtered?
+ Set set = mDependendsOnMap.get(key);
+ if (set == null) {
+ set = new HashSet<>();
+ }
+ set.add(baseKey);
+ mDependendsOnMap.put(key, set);
+ }
+ }
+ }
+ }
+
+ private void initializeValueMap() {
+ List<String> processLater = new ArrayList<String>();
+ for (int i = 0; i < mPreferenceGroup.size(); i++) {
+ ListPreference pref = (ListPreference) mPreferenceGroup.get(i);
+ String key = pref.getKey();
+ if (mDependendsOnMap.get(key) != null && mDependendsOnMap.get(key).size() != 0) {
+ processLater.add(key);
+ continue;
+ }
+ Values values = new Values(pref.getValue(), null);
+ mValuesMap.put(pref.getKey(), values);
+ }
+ for (String keyToProcess : processLater) {
+ Set<String> dependsOnSet = mDependendsOnMap.get(keyToProcess);
+ boolean active = true;
+ List<KeyValue> keyValue = null;
+ for (String s : dependsOnSet) {
+ if (specialDepedency(s) || isOptionOn(s)) {
+ active = false;
+ if (specialDepedency(s)) {
+ keyValue = getSpecialDependencyList(s);
+ }
+ }
+ break;
+ }
+ ListPreference pref = mPreferenceGroup.findPreference(keyToProcess);
+ Values values = new Values(pref.getValue(), null);
+ if (!active) {
+ String offValue = pref.getOffValue();
+ if (keyValue != null) {
+ String matchValue = getMatchingValue(keyToProcess, keyValue);
+ if (matchValue != null)
+ offValue = matchValue;
+ }
+ values.overriddenValue = offValue;
+ }
+ mValuesMap.put(keyToProcess, values);
+ }
+ }
+
+ private List<SettingState> checkDependencyAndUpdate(String changedPrefKey) {
+ ListPreference changedPref = mPreferenceGroup.findPreference(changedPrefKey);
+ if (changedPref == null) return null;
+
+ String key = changedPref.getKey();
+ String value = changedPref.getValue();
+ boolean special = specialDepedency(changedPrefKey);
+ String prevValue = getValue(changedPrefKey);
+ if (value.equals(prevValue)) return null;
+
+ boolean turnedOff = value.equals(changedPref.getOffValue());
+ boolean updateBackDependency = false;
+ List<SettingState> changed = new ArrayList();
+ Values values = new Values(value, null);
+ mValuesMap.put(key, values);
+ changed.add(new SettingState(key, values));
+
+ Set<CharSequence> turnOn = new HashSet<>();
+ Set<CharSequence> turnOff = new HashSet<>();
+
+ CharSequence[] originalDependencyList = changedPref.getDependencyList();
+ CharSequence[] dependencyList = null;
+ List<KeyValue> keyValue = null;
+ if (special) {
+ keyValue = getSpecialDependencyList(changedPref);
+ if (keyValue.size() > 0) {
+ dependencyList = new CharSequence[keyValue.size()];
+ int k = 0;
+ for (KeyValue kv : keyValue) {
+ dependencyList[k++] = kv.key;
+ }
+ }
+ }
+
+ if (special) {
+ boolean same = Arrays.equals(originalDependencyList, dependencyList);
+ if (!same) {
+ changedPref.setDependencyList(dependencyList);
+ if (originalDependencyList != null)
+ for (CharSequence c : originalDependencyList) {
+ turnOn.add(c);
+ }
+ if (dependencyList != null)
+ for (CharSequence c : dependencyList) {
+ turnOff.add(c);
+ }
+
+ if (originalDependencyList != null)
+ for (CharSequence c : originalDependencyList) {
+ turnOff.remove(c);
+ }
+ if (dependencyList != null)
+ for (CharSequence c : dependencyList) {
+ turnOn.remove(c);
+ }
+ updateBackDependency = true;
+ }
+ } else {
+ if (originalDependencyList != null) {
+ for (CharSequence c : originalDependencyList) {
+ if (turnedOff) turnOn.add(c);
+ else turnOff.add(c);
+ }
+ }
+ }
+
+ for (CharSequence c : turnOn) {// turn back on
+ key = c.toString();
+ Set<String> dependsOnSet = mDependendsOnMap.get(key);
+ if (dependsOnSet == null) continue;
+ boolean active = true;
+ for (String s : dependsOnSet) {
+ if (s.equals(changedPrefKey)) continue;
+ if (isOptionOn(s)) active = false;
+ break;
+ }
+ if (active) {
+ values = mValuesMap.get(key);
+ if (values == null) continue;
+ values.overriddenValue = null;
+ mValuesMap.put(key, values);
+ changed.add(new SettingState(key, values));
+ }
+ }
+
+ for (CharSequence c : turnOff) {// turn off logic
+ key = c.toString();
+ ListPreference pref = mPreferenceGroup.findPreference(key);
+ if (pref == null) continue;
+ values = mValuesMap.get(key);
+ if (values == null) continue;
+ if (values != null && values.overriddenValue != null) continue;
+ String offValue = pref.getOffValue();
+ if (keyValue != null) {
+ String matchValue = getMatchingValue(key, keyValue);
+ if (matchValue != null)
+ offValue = matchValue;
+ }
+ Values newValue = new Values(pref.getValue(), offValue);
+ mValuesMap.put(key, newValue);
+ changed.add(new SettingState(key, newValue));
+ }
+
+ if (updateBackDependency) {
+ updateBackDependency(changedPrefKey, turnOn, turnOff);
+ }
+
+ return changed;
+ }
+
+ private void updateBackDependency(String key, Set<CharSequence> remove, Set<CharSequence>
+ add) {
+ for (CharSequence c : remove) {
+ String currentKey = c.toString();
+ Set<String> dependsOnSet = mDependendsOnMap.get(currentKey);
+ if (dependsOnSet != null) dependsOnSet.remove(key);
+ }
+ for (CharSequence c : add) {
+ String currentKey = c.toString();
+ Set<String> dependsOnSet = mDependendsOnMap.get(currentKey);
+ if (dependsOnSet == null) {
+ dependsOnSet = new HashSet<>();
+ mDependendsOnMap.put(currentKey, dependsOnSet);
+ }
+ dependsOnSet.add(key);
+ }
+ }
+
+ public void registerListener(Listener listener) {
+ mListeners.add(listener);
+ }
+
+ private void notifyListeners(List<SettingState> changes) {
+ for (Listener listener : mListeners) {
+ listener.onSettingsChanged(changes);
+ }
+ }
+
+ public boolean isCamera2On() {
+ return mPreferences.getString(KEY_CAMERA2, "disable").equals("enable");
+ }
+
+ public String getValue(String key) {
+ Values values = mValuesMap.get(key);
+ if (values == null) return null;
+ if (values.overriddenValue == null) return values.value;
+ else return values.overriddenValue;
+ }
+
+ public int getValueIndex(String key) {
+ ListPreference pref = mPreferenceGroup.findPreference(key);
+ String value = getValue(key);
+ if (value == null) return -1;
+ return pref.findIndexOfValue(value);
+ }
+
+ public boolean isOverriden(String key) {
+ Values values = mValuesMap.get(key);
+ return values.overriddenValue != null;
+ }
+
+ public void setValue(String key, String value) {
+ ListPreference pref = mPreferenceGroup.findPreference(key);
+ pref.setValue(value);
+ updateMapAndNotify(pref);
+ }
+
+ public void setValueIndex(String key, int index) {
+ ListPreference pref = mPreferenceGroup.findPreference(key);
+ pref.setValueIndex(index);
+ updateMapAndNotify(pref);
+ }
+
+ private void updateMapAndNotify(ListPreference pref) {
+ String key = pref.getKey();
+ List changed = checkDependencyAndUpdate(key);
+ if (changed == null) return;
+ notifyListeners(changed);
+ }
+
+ private boolean isOptionOn(String key) {
+ ListPreference pref = mPreferenceGroup.findPreference(key);
+ Values values = mValuesMap.get(key);
+ return (values.overriddenValue == null && !pref.getValue().equals(pref.getOffValue()));
+ }
+
+ public PreferenceGroup getPreferenceGroup() {
+ return mPreferenceGroup;
+ }
+
+ public CharSequence[] getEntries(String key) {
+ ListPreference pref = mPreferenceGroup.findPreference(key);
+ return pref.getEntries();
+ }
+
+ public int[] getResource(String key, int type) {
+ IconListPreference pref = (IconListPreference) mPreferenceGroup.findPreference(key);
+ switch (type) {
+ case RESOURCE_TYPE_THUMBNAIL:
+ return pref.getThumbnailIds();
+ case RESOURCE_TYPE_LARGEICON:
+ return pref.getLargeIconIds();
+ }
+ return null;
+ }
+
+ private void filterPreferences(int cameraId) {
+ // filter unsupported preferences
+ ListPreference whiteBalance = mPreferenceGroup.findPreference(KEY_WHITE_BALANCE);
+ ListPreference flashMode = mPreferenceGroup.findPreference(KEY_FLASH_MODE);
+ ListPreference colorEffect = mPreferenceGroup.findPreference(KEY_COLOR_EFFECT);
+ ListPreference sceneMode = mPreferenceGroup.findPreference(KEY_SCENE_MODE);
+ ListPreference cameraIdPref = mPreferenceGroup.findPreference(KEY_CAMERA_ID);
+ ListPreference pictureSize = mPreferenceGroup.findPreference(KEY_PICTURE_SIZE);
+ ListPreference exposure = mPreferenceGroup.findPreference(KEY_EXPOSURE);
+ ListPreference iso = mPreferenceGroup.findPreference(KEY_ISO);
+ ListPreference clearsight = mPreferenceGroup.findPreference(KEY_CLEARSIGHT);
+ ListPreference monoPreview = mPreferenceGroup.findPreference(KEY_MONO_PREVIEW);
+ ListPreference monoOnly = mPreferenceGroup.findPreference(KEY_MONO_ONLY);
+
+ if (whiteBalance != null) {
+ CameraSettings.filterUnsupportedOptions(mPreferenceGroup,
+ whiteBalance, getSupportedWhiteBalanceModes(cameraId));
+ }
+ if (flashMode != null) {
+ CameraSettings.filterUnsupportedOptions(mPreferenceGroup,
+ flashMode, getSupportedFlashModes(cameraId));
+ }
+
+ if (colorEffect != null) {
+ CameraSettings.filterUnsupportedOptions(mPreferenceGroup,
+ colorEffect, getSupportedColorEffects(cameraId));
+ }
+
+ if (sceneMode != null) {
+ CameraSettings.filterUnsupportedOptions(mPreferenceGroup,
+ sceneMode, getSupportedSceneModes(cameraId));
+ }
+
+ if (cameraIdPref != null) buildCameraId();
+
+ if (pictureSize != null) {
+ CameraSettings.filterUnsupportedOptions(mPreferenceGroup,
+ pictureSize, getSupportedPictureSize(cameraId));
+ }
+
+ if (exposure != null) buildExposureCompensation(cameraId);
+
+ if (iso != null) {
+ CameraSettings.filterUnsupportedOptions(mPreferenceGroup,
+ iso, getSupportedIso(cameraId));
+ }
+
+ if (!mIsMonoCameraPresent) {
+ if (clearsight != null) removePreference(mPreferenceGroup, KEY_CLEARSIGHT);
+ if (monoPreview != null) removePreference(mPreferenceGroup, KEY_MONO_PREVIEW);
+ if (monoOnly != null) removePreference(mPreferenceGroup, KEY_MONO_ONLY);
+
+ }
+ }
+
+ private void buildExposureCompensation(int cameraId) {
+ Range<Integer> range = mCharacteristics.get(cameraId).get(CameraCharacteristics
+ .CONTROL_AE_COMPENSATION_RANGE);
+ int max = range.getUpper();
+ int min = range.getLower();
+ if (min == 0 && max == 0) {
+ removePreference(mPreferenceGroup, KEY_EXPOSURE);
+ return;
+ }
+ ListPreference pref = mPreferenceGroup.findPreference(KEY_EXPOSURE);
+ Rational rational = mCharacteristics.get(cameraId).get(CameraCharacteristics
+ .CONTROL_AE_COMPENSATION_STEP);
+ double step = rational.doubleValue();
+ int increment = 1;
+ while ((max - min) / increment > 10) {
+ increment++;
+ }
+ int start = min;
+ if (start < 0) {
+ while (Math.abs(start) % increment != 0) {
+ start++;
+ }
+ }
+ int size = 0;
+ for (int i = start; i <= max; i += increment) size++;
+ CharSequence entries[] = new CharSequence[size];
+ CharSequence entryValues[] = new CharSequence[size];
+ int count = 0;
+ for (int i = start; i <= max; i += increment, count++) {
+ entryValues[count] = Integer.toString(i);
+ StringBuilder builder = new StringBuilder();
+ if (i > 0) builder.append('+');
+ DecimalFormat format = new DecimalFormat("#.##");
+ entries[count] = builder.append(format.format(i * step)).toString();
+ }
+ pref.setEntries(entries);
+ pref.setEntryValues(entryValues);
+ }
+
+ private void buildCameraId() {
+ int numOfCameras = mCharacteristics.size();
+ if (!mIsFrontCameraPresent) {
+ removePreference(mPreferenceGroup, KEY_CAMERA_ID);
+ return;
+ }
+
+ CharSequence[] entryValues = new CharSequence[numOfCameras];
+ CharSequence[] entries = new CharSequence[numOfCameras];
+ //TODO: Modify this after bayer/mono/front/back determination is done
+ entryValues[0] = "" + CaptureModule.BAYER_ID;
+ entries[0] = "BACK";
+ if (mIsFrontCameraPresent) {
+ entryValues[1] = "" + CaptureModule.FRONT_ID;
+ entries[1] = "FRONT";
+ }
+ ListPreference cameraIdPref = mPreferenceGroup.findPreference(KEY_CAMERA_ID);
+ cameraIdPref.setEntryValues(entryValues);
+ cameraIdPref.setEntries(entries);
+ }
+
+ private boolean removePreference(PreferenceGroup group, String key) {
+ for (int i = 0, n = group.size(); i < n; i++) {
+ CameraPreference child = group.get(i);
+ if (child instanceof PreferenceGroup) {
+ if (removePreference((PreferenceGroup) child, key)) {
+ return true;
+ }
+ }
+ if (child instanceof ListPreference &&
+ ((ListPreference) child).getKey().equals(key)) {
+ group.removePreference(i);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public float getMaxZoom(int id) {
+ return mCharacteristics.get(id).get(CameraCharacteristics
+ .SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
+ }
+
+ public Rect getSensorActiveArraySize(int id) {
+ return mCharacteristics.get(id).get(CameraCharacteristics
+ .SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ }
+
+ public float getMaxZoom(List<Integer> ids) {
+ float zoomMax = Float.MAX_VALUE;
+ for (int id : ids) {
+ zoomMax = Math.min(getMaxZoom(id), zoomMax);
+ }
+ return zoomMax;
+ }
+
+ public boolean isZoomSupported(int id) {
+ return mCharacteristics.get(id).get(CameraCharacteristics
+ .SCALER_AVAILABLE_MAX_DIGITAL_ZOOM) > 1f;
+ }
+
+ public boolean isAutoFocusSupported(List<Integer> ids) {
+ for (int id : ids) {
+ if (!isAutoFocusSupported(id))
+ return false;
+ }
+ return true;
+ }
+
+
+ public boolean isZoomSupported(List<Integer> ids) {
+ for (int id : ids) {
+ if (!isZoomSupported(id))
+ return false;
+ }
+ return true;
+ }
+
+ public boolean isAutoFocusSupported(int id) {
+ Integer maxAfRegions = mCharacteristics.get(id).get(
+ CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
+ return maxAfRegions != null && maxAfRegions > 0;
+ }
+
+ public boolean isFixedFocus(int id) {
+ Float focusDistance = mCharacteristics.get(id).get(CameraCharacteristics
+ .LENS_INFO_MINIMUM_FOCUS_DISTANCE);
+ if (focusDistance == null || focusDistance == 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isFlashSupported(int id) {
+ return mCharacteristics.get(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE) &&
+ mValuesMap.get(KEY_FLASH_MODE) != null;
+ }
+
+ private List<String> getSupportedPictureSize(int cameraId) {
+ StreamConfigurationMap map = mCharacteristics.get(cameraId).get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ Size[] sizes = map.getOutputSizes(ImageFormat.JPEG);
+ List<String> res = new ArrayList<>();
+ for (int i = 0; i < sizes.length; i++) {
+ res.add(sizes[i].toString());
+ }
+ return res;
+ }
+
+ private List<String> getSupportedWhiteBalanceModes(int cameraId) {
+ int[] whiteBalanceModes = mCharacteristics.get(cameraId).get(CameraCharacteristics
+ .CONTROL_AWB_AVAILABLE_MODES);
+ List<String> modes = new ArrayList<>();
+ for (int mode : whiteBalanceModes) {
+ modes.add("" + mode);
+ }
+ return modes;
+ }
+
+ private List<String> getSupportedSceneModes(int cameraId) {
+ int[] sceneModes = mCharacteristics.get(cameraId).get(CameraCharacteristics
+ .CONTROL_AVAILABLE_SCENE_MODES);
+ List<String> modes = new ArrayList<>();
+ modes.add("0"); // need special case handle for auto scene mode
+ if (mIsMonoCameraPresent) modes.add(SCENE_MODE_DUAL_STRING); // need special case handle for dual mode
+ if (OptizoomFilter.isSupportedStatic()) modes.add(SCENE_MODE_OPTIZOOM_INT + ""); // need special case handle for dual mode
+ for (int mode : sceneModes) {
+ modes.add("" + mode);
+ }
+ return modes;
+ }
+
+ private List<String> getSupportedFlashModes(int cameraId) {
+ int[] flashModes = mCharacteristics.get(cameraId).get(CameraCharacteristics
+ .CONTROL_AE_AVAILABLE_MODES);
+ List<String> modes = new ArrayList<>();
+ for (int mode : flashModes) {
+ modes.add("" + mode);
+ }
+ return modes;
+ }
+
+ public List<String> getSupportedColorEffects(int cameraId) {
+ int[] flashModes = mCharacteristics.get(cameraId).get(CameraCharacteristics
+ .CONTROL_AVAILABLE_EFFECTS);
+ List<String> modes = new ArrayList<>();
+ for (int mode : flashModes) {
+ modes.add("" + mode);
+ }
+ return modes;
+ }
+
+ private List<String> getSupportedIso(int cameraId) {
+ Range<Integer> range = mCharacteristics.get(cameraId).get(CameraCharacteristics
+ .SENSOR_INFO_SENSITIVITY_RANGE);
+ int max = range.getUpper();
+ int value = 50;
+ List<String> supportedIso = new ArrayList<>();
+ supportedIso.add("auto");
+ while (value <= max) {
+ if (range.contains(value)) {
+ supportedIso.add("" + value);
+ }
+ value += 50;
+ }
+ return supportedIso;
+ }
+
+ private boolean specialDepedency(String key) {
+ return key.equals(KEY_SCENE_MODE);
+ }
+
+ private List<KeyValue> getSpecialDependencyList(String key) {
+ ListPreference pref = mPreferenceGroup.findPreference(key);
+ return getSpecialDependencyList(pref);
+ }
+
+ private List<KeyValue> getSpecialDependencyList(ListPreference pref) {
+ String key = pref.getKey();
+ List<KeyValue> dependency = new ArrayList<>();
+ switch (key) {
+ case KEY_SCENE_MODE:
+ String value = pref.getValue();
+ switch (value) {
+ case "0":
+ dependency.add(new KeyValue(KEY_CLEARSIGHT, "off"));
+ dependency.add(new KeyValue(KEY_MONO_PREVIEW, "off"));
+ break;
+ case SCENE_MODE_DUAL_STRING:
+ dependency.add(new KeyValue(KEY_LONGSHOT, "off"));
+ dependency.add(new KeyValue(KEY_MONO_ONLY, "off"));
+ break;
+ default:
+ dependency.add(new KeyValue(KEY_COLOR_EFFECT, "0"));
+ dependency.add(new KeyValue(KEY_FLASH_MODE, "2"));
+ dependency.add(new KeyValue(KEY_WHITE_BALANCE, "1"));
+ dependency.add(new KeyValue(KEY_EXPOSURE, "0"));
+ dependency.add(new KeyValue(KEY_CLEARSIGHT, "off"));
+ dependency.add(new KeyValue(KEY_MONO_PREVIEW, "off"));
+ break;
+ }
+ break;
+ }
+ return dependency;
+ }
+
+ public interface Listener {
+ void onSettingsChanged(List<SettingState> settings);
+ }
+
+ private String getMatchingValue(String key, List<KeyValue> keyValue) {
+ for (KeyValue kv: keyValue) {
+ if (key.equals(kv.key)) {
+ return kv.value;
+ }
+ }
+ return null;
+ }
+
+ static class KeyValue {
+ String key;
+ String value;
+
+ KeyValue(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+ }
+ static class Values {
+ String value;
+ String overriddenValue;
+
+ Values(String value, String overriddenValue) {
+ this.value = value;
+ this.overriddenValue = overriddenValue;
+ }
+ }
+
+ static class SettingState {
+ String key;
+ Values values;
+
+ SettingState(String key, Values values) {
+ this.key = key;
+ this.values = values;
+ }
+ }
+
+}
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index cbfe7b94a..96423044f 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -315,7 +315,13 @@ public class VideoModule implements CameraModule,
VIDEO_ENCODER_TABLE.put("h263", MediaRecorder.VideoEncoder.H263);
VIDEO_ENCODER_TABLE.put("h264", MediaRecorder.VideoEncoder.H264);
- VIDEO_ENCODER_TABLE.put("h265", MediaRecorder.VideoEncoder.HEVC);
+ int h265 = ApiHelper.getIntFieldIfExists(MediaRecorder.VideoEncoder.class,
+ "HEVC", null, MediaRecorder.VideoEncoder.DEFAULT);
+ if (h265 == MediaRecorder.VideoEncoder.DEFAULT) {
+ h265 = ApiHelper.getIntFieldIfExists(MediaRecorder.VideoEncoder.class,
+ "H265", null, MediaRecorder.VideoEncoder.DEFAULT);
+ }
+ VIDEO_ENCODER_TABLE.put("h265", h265);
VIDEO_ENCODER_TABLE.put("m4v", MediaRecorder.VideoEncoder.MPEG_4_SP);
VIDEO_ENCODER_TABLE.putDefault(MediaRecorder.VideoEncoder.DEFAULT);
@@ -1106,8 +1112,7 @@ public class VideoModule implements CameraModule,
mOrientationManager.resume();
// Initialize location service.
- boolean recordLocation = RecordLocationPreference.get(mPreferences,
- mContentResolver);
+ boolean recordLocation = RecordLocationPreference.get(mPreferences);
mLocationManager.recordLocation(recordLocation);
if (mPreviewing) {
@@ -1487,6 +1492,10 @@ public class VideoModule implements CameraModule,
mProfile.audioCodec = mAudioEncoder;
mProfile.duration = mMaxVideoDurationInMs;
+ if ((mProfile.audioCodec == MediaRecorder.AudioEncoder.AMR_NB) &&
+ !mCaptureTimeLapse && !isHFR) {
+ mProfile.fileFormat = MediaRecorder.OutputFormat.THREE_GPP;
+ }
// Set params individually for HFR case, as we do not want to encode audio
if ((isHFR || isHSR) && captureRate > 0) {
if (isHSR) {
@@ -2701,8 +2710,7 @@ public class VideoModule implements CameraModule,
// startPreview().
if (mCameraDevice == null) return;
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
+ boolean recordLocation = RecordLocationPreference.get(mPreferences);
mLocationManager.recordLocation(recordLocation);
readVideoPreferences();
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index c99c8c8f5..5203d9e35 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -705,8 +705,7 @@ public class VideoUI implements PieRenderer.PieListener,
public void updateOnScreenIndicators(Parameters param, ComboPreferences prefs) {
mOnScreenIndicators.updateFlashOnScreenIndicator(param.getFlashMode());
- boolean location = RecordLocationPreference.get(
- prefs, mActivity.getContentResolver());
+ boolean location = RecordLocationPreference.get(prefs);
mOnScreenIndicators.updateLocationIndicator(location);
}
diff --git a/src/com/android/camera/WideAnglePanoramaModule.java b/src/com/android/camera/WideAnglePanoramaModule.java
index 7b4bc1901..9a0e9ce7e 100644
--- a/src/com/android/camera/WideAnglePanoramaModule.java
+++ b/src/com/android/camera/WideAnglePanoramaModule.java
@@ -832,6 +832,7 @@ public class WideAnglePanoramaModule
ExifInterface exif = new ExifInterface();
try {
exif.readExif(jpegData);
+ exif.addMakeAndModelTag();
exif.addGpsDateTimeStampTag(mTimeTaken);
exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, mTimeTaken,
TimeZone.getDefault());
@@ -1010,8 +1011,7 @@ public class WideAnglePanoramaModule
mOrientationManager.resume();
// Initialize location service.
- boolean recordLocation = RecordLocationPreference.get(mPreferences,
- mContentResolver);
+ boolean recordLocation = RecordLocationPreference.get(mPreferences);
mLocationManager.recordLocation(recordLocation);
mUI.initDisplayChangeListener();
UsageStatistics.onContentViewChanged(
diff --git a/src/com/android/camera/exif/ExifInterface.java b/src/com/android/camera/exif/ExifInterface.java
index f353f3586..2fec1bf4f 100644
--- a/src/com/android/camera/exif/ExifInterface.java
+++ b/src/com/android/camera/exif/ExifInterface.java
@@ -19,6 +19,7 @@ package com.android.camera.exif;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.SparseIntArray;
+import android.os.Build;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -2028,6 +2029,21 @@ public class ExifInterface {
return true;
}
+ public boolean addMakeAndModelTag() {
+ ExifTag t = buildTag(TAG_MAKE, Build.MANUFACTURER);
+ if (t == null) {
+ return false;
+ }
+ setTag(t);
+ t = buildTag(TAG_MODEL, Build.MODEL);
+ if (t == null) {
+ return false;
+ }
+ setTag(t);
+ return true;
+ }
+
+
private static Rational[] toExifLatLong(double value) {
// convert to the format dd/1 mm/1 ssss/100
value = Math.abs(value);
diff --git a/src/com/android/camera/imageprocessor/FrameProcessor.java b/src/com/android/camera/imageprocessor/FrameProcessor.java
new file mode 100644
index 000000000..951479de9
--- /dev/null
+++ b/src/com/android/camera/imageprocessor/FrameProcessor.java
@@ -0,0 +1,335 @@
+/*
+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.imageprocessor;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ImageFormat;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.YuvImage;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicYuvToRGB;
+import android.renderscript.Type;
+import android.util.Log;
+import android.util.Size;
+import android.view.Surface;
+
+import com.android.camera.CaptureModule;
+import com.android.camera.PhotoModule;
+import com.android.camera.imageprocessor.filter.BeautificationFilter;
+import com.android.camera.imageprocessor.filter.ImageFilter;
+import com.android.camera.util.CameraUtil;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+public class FrameProcessor {
+
+ private ImageReader mInputImageReader;
+ private Allocation mInputAllocation;
+ private Allocation mProcessAllocation;
+ private Allocation mOutputAllocation;
+
+ private HandlerThread mProcessingThread;
+ private Handler mProcessingHandler;
+ private HandlerThread mOutingThread;
+ private Handler mOutingHandler;
+
+ public ProcessingTask mTask;
+ private RenderScript mRs;
+ private Activity mActivity;
+ ScriptC_YuvToRgb mRsYuvToRGB;
+ ScriptC_rotator mRsRotator;
+ private Size mSize;
+ private Object mAllocationLock = new Object();
+ private boolean mIsAllocationEverUsed;
+ private ArrayList<ImageFilter> mPreviewFilters;
+ private ArrayList<ImageFilter> mFinalFilters;
+ private Surface mSurfaceAsItIs;
+ private boolean mIsActive = false;
+ public static final int FILTER_NONE = 0;
+ public static final int FILTER_MAKEUP = 1;
+ private CaptureModule mModule;
+
+ public FrameProcessor(Activity activity, CaptureModule module) {
+ mActivity = activity;
+ mModule = module;
+ mPreviewFilters = new ArrayList<ImageFilter>();
+ mFinalFilters = new ArrayList<ImageFilter>();
+ }
+
+ public void init(Size previewDim) {
+ mSize = previewDim;
+ synchronized (mAllocationLock) {
+ mRs = RenderScript.create(mActivity);
+ mRsYuvToRGB = new ScriptC_YuvToRgb(mRs);
+ mRsRotator = new ScriptC_rotator(mRs);
+ mInputImageReader = ImageReader.newInstance(mSize.getWidth(), mSize.getHeight(), ImageFormat.YUV_420_888, 8);
+
+ Type.Builder rgbTypeBuilder = new Type.Builder(mRs, Element.RGBA_8888(mRs));
+ rgbTypeBuilder.setX(mSize.getHeight());
+ rgbTypeBuilder.setY(mSize.getWidth());
+ mOutputAllocation = Allocation.createTyped(mRs, rgbTypeBuilder.create(),
+ Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT);
+
+ if (mProcessingThread == null) {
+ mProcessingThread = new HandlerThread("FrameProcessor");
+ mProcessingThread.start();
+ mProcessingHandler = new Handler(mProcessingThread.getLooper());
+ }
+
+ if (mOutingThread == null) {
+ mOutingThread = new HandlerThread("FrameOutingThread");
+ mOutingThread.start();
+ mOutingHandler = new Handler(mOutingThread.getLooper());
+ }
+
+ mTask = new ProcessingTask();
+ mInputImageReader.setOnImageAvailableListener(mTask, mProcessingHandler);
+ mIsAllocationEverUsed = false;
+ }
+ }
+
+ private void createAllocation(int width, int height) {
+ Type.Builder yuvTypeBuilder = new Type.Builder(mRs, Element.YUV(mRs));
+ yuvTypeBuilder.setX(width);
+ yuvTypeBuilder.setY(height);
+ yuvTypeBuilder.setYuvFormat(ImageFormat.NV21);
+ mInputAllocation = Allocation.createTyped(mRs, yuvTypeBuilder.create(), Allocation.USAGE_SCRIPT);
+ Type.Builder nv21TypeBuilder = new Type.Builder(mRs, Element.U8(mRs));
+ nv21TypeBuilder.setX(width * height * 3 / 2);
+ mProcessAllocation = Allocation.createTyped(mRs, nv21TypeBuilder.create(), Allocation.USAGE_SCRIPT);
+ mRsRotator.set_gIn(mInputAllocation);
+ mRsRotator.set_gOut(mProcessAllocation);
+ mRsRotator.set_width(width);
+ mRsRotator.set_height(height);
+ mRsYuvToRGB.set_gIn(mProcessAllocation);
+ mRsYuvToRGB.set_width(height);
+ mRsYuvToRGB.set_height(width);
+ }
+
+ public ArrayList<ImageFilter> getFrameFilters() {
+ return mFinalFilters;
+ }
+
+ private void cleanFilterSet() {
+ if(mPreviewFilters != null) {
+ for (ImageFilter filter : mPreviewFilters) {
+ filter.deinit();
+ }
+ }
+ if(mFinalFilters != null) {
+ for (ImageFilter filter : mFinalFilters) {
+ filter.deinit();
+ }
+ }
+ mPreviewFilters = new ArrayList<ImageFilter>();
+ mFinalFilters = new ArrayList<ImageFilter>();
+ }
+
+ public void onOpen(ArrayList<Integer> filterIds) {
+ mIsActive = true;
+ synchronized (mAllocationLock) {
+ cleanFilterSet();
+ if (filterIds != null) {
+ for (Integer i : filterIds) {
+ addFilter(i.intValue());
+ }
+ }
+ }
+ }
+
+ private void addFilter(int filterId) {
+ if(filterId == FILTER_MAKEUP) {
+ ImageFilter filter = new BeautificationFilter(mModule);
+ if(filter.isSupported()) {
+ mPreviewFilters.add(filter);
+ mFinalFilters.add(filter);
+ }
+ }
+ }
+
+ public void onClose() {
+ mIsActive = false;
+ synchronized (mAllocationLock) {
+ if (mIsAllocationEverUsed) {
+ if (mInputAllocation != null) {
+ mInputAllocation.destroy();
+ }
+ if (mOutputAllocation != null) {
+ mOutputAllocation.destroy();
+ }
+ if (mProcessAllocation != null) {
+ mProcessAllocation.destroy();
+ }
+ }
+ if (mRs != null) {
+ mRs.destroy();
+ }
+ mRs = null;
+ mProcessAllocation = null;
+ mOutputAllocation = null;
+ mInputAllocation = null;
+ }
+ if (mProcessingThread != null) {
+ mProcessingThread.quitSafely();
+ try {
+ mProcessingThread.join();
+ mProcessingThread = null;
+ mProcessingHandler = null;
+ } catch (InterruptedException e) {
+ }
+ }
+ if (mOutingThread != null) {
+ mOutingThread.quitSafely();
+ try {
+ mOutingThread.join();
+ mOutingThread = null;
+ mOutingHandler = null;
+ } catch (InterruptedException e) {
+ }
+ }
+ for(ImageFilter filter : mPreviewFilters) {
+ filter.deinit();
+ }
+ for(ImageFilter filter : mFinalFilters) {
+ filter.deinit();
+ }
+ }
+
+ public Surface getInputSurface() {
+ if(mPreviewFilters.size() == 0) {
+ return mSurfaceAsItIs;
+ }
+ synchronized (mAllocationLock) {
+ if (mInputImageReader == null)
+ return null;
+ return mInputImageReader.getSurface();
+ }
+ }
+
+ public boolean isFrameFilterEnabled() {
+ if(mPreviewFilters.size() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public void setOutputSurface(Surface surface) {
+ if(mPreviewFilters.size() == 0) {
+ mSurfaceAsItIs = surface;
+ } else {
+ mOutputAllocation.setSurface(surface);
+ }
+ }
+
+ class ProcessingTask implements Runnable, ImageReader.OnImageAvailableListener {
+ byte[] yvuBytes = null;
+ int ySize;
+ int stride;
+ int height;
+
+ public ProcessingTask() {
+ }
+
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ synchronized (mAllocationLock) {
+ if(mOutputAllocation == null)
+ return;
+ try {
+ Image image = reader.acquireLatestImage();
+ if(image == null)
+ return;
+ if(!mIsActive) {
+ image.close();
+ return;
+ }
+ mIsAllocationEverUsed = true;
+ ByteBuffer bY = image.getPlanes()[0].getBuffer();
+ ByteBuffer bVU = image.getPlanes()[2].getBuffer();
+ if(yvuBytes == null) {
+ stride = image.getPlanes()[0].getRowStride();
+ height = mSize.getHeight();
+ ySize = stride * mSize.getHeight();
+ yvuBytes = new byte[ySize*3/2];
+ }
+ //Start processing yvu buf
+ for (ImageFilter filter : mPreviewFilters) {
+ filter.init(mSize.getWidth(), mSize.getHeight(), stride, stride);
+ filter.addImage(bY, bVU, 0, new Boolean(true));
+ }
+ //End processing yvu buf
+ bY.get(yvuBytes, 0, bY.remaining());
+ bVU.get(yvuBytes, ySize, bVU.remaining());
+ image.close();
+ mOutingHandler.post(this);
+ } catch (IllegalStateException e) {
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ synchronized (mAllocationLock) {
+ if(!mIsActive) {
+ return;
+ }
+ if(mInputAllocation == null) {
+ createAllocation(stride, height);
+ }
+ mInputAllocation.copyFrom(yvuBytes);
+ mRsRotator.forEach_rotate90andMerge(mInputAllocation);
+ mRsYuvToRGB.forEach_nv21ToRgb(mOutputAllocation);
+ mOutputAllocation.ioSend();
+ }
+ }
+ }
+
+ private native int nativeRotateNV21(ByteBuffer inBuf, int imageWidth, int imageHeight, int degree, ByteBuffer outBuf);
+
+ private native int nativeNV21toRgb(ByteBuffer yvuBuf, ByteBuffer rgbBuf, int width, int height);
+
+ static {
+ System.loadLibrary("jni_imageutil");
+ }
+}
+
diff --git a/src/com/android/camera/imageprocessor/PostProcessor.java b/src/com/android/camera/imageprocessor/PostProcessor.java
new file mode 100644
index 000000000..a126e8817
--- /dev/null
+++ b/src/com/android/camera/imageprocessor/PostProcessor.java
@@ -0,0 +1,448 @@
+/*
+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.imageprocessor;
+
+import android.content.ContentResolver;
+import android.graphics.ImageFormat;
+import android.graphics.Rect;
+import android.graphics.YuvImage;
+import android.hardware.camera2.CaptureRequest;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.camera.CameraActivity;
+import com.android.camera.CaptureModule;
+import com.android.camera.MediaSaveService;
+import com.android.camera.PhotoModule;
+import com.android.camera.SettingsManager;
+import com.android.camera.imageprocessor.filter.OptizoomFilter;
+import com.android.camera.ui.RotateTextToast;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import com.android.camera.imageprocessor.filter.ImageFilter;
+
+public class PostProcessor implements ImageReader.OnImageAvailableListener{
+
+ private CaptureModule mController;
+
+ private static final String TAG = "PostProcessor";
+ public static final int FILTER_NONE = 0;
+ public static final int FILTER_OPTIZOOM = 1;
+ public static final int FILTER_MAX = 2;
+
+ private int mCurrentNumImage = 0;
+ private ImageFilter mFilter;
+ private int mFilterIndex;
+ private HandlerThread mHandlerThread;
+ private ProcessorHandler mHandler;
+ private CameraActivity mActivity;
+ private int mWidth;
+ private int mHeight;
+ private int mStride;
+ private Object lock = new Object();
+ private ImageFilter.ResultImage mDefaultResultImage; //This is used only no filter is chosen.
+ private Image[] mImages;
+ private PhotoModule.NamedImages mNamedImages;
+ private WatchdogThread mWatchdog;
+
+ //This is for the debug feature.
+ private static boolean DEBUG_FILTER = true; //TODO: This has to be false before releasing.
+ private ImageFilter.ResultImage mDebugResultImage;
+
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ try {
+ Image image = reader.acquireNextImage();
+ addImage(image);
+ if (isReadyToProcess()) {
+ long captureStartTime = System.currentTimeMillis();
+ mNamedImages.nameNewImage(captureStartTime);
+ PhotoModule.NamedImages.NamedEntity name = mNamedImages.getNextNameEntity();
+ String title = (name == null) ? null : name.title;
+ long date = (name == null) ? -1 : name.date;
+ processImage(title, date, mController.getMediaSavedListener(), mActivity.getContentResolver());
+ }
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Max images has been already acquired. ");
+ }
+ }
+
+ enum STATUS {
+ DEINIT,
+ INIT,
+ BUSY
+ }
+ private STATUS mStatus = STATUS.DEINIT;
+
+ public PostProcessor(CameraActivity activity, CaptureModule module) {
+ mController = module;
+ mActivity = activity;
+ mNamedImages = new PhotoModule.NamedImages();
+
+ }
+
+ public boolean isItBusy() {
+ if(mStatus == STATUS.BUSY)
+ return true;
+ return false;
+ }
+
+ public List<CaptureRequest> setRequiredImages(CaptureRequest.Builder builder) {
+ if(mFilter == null) {
+ List<CaptureRequest> list = new ArrayList<CaptureRequest>();
+ list.add(builder.build());
+ return list;
+ } else {
+ return mFilter.setRequiredImages(builder);
+ }
+ }
+
+ public boolean isFilterOn() {
+ if(mFilter != null) {
+ return true;
+ }
+ if(mController.getFrameFilters().size() != 0) {
+ return true;
+ }
+ return false;
+ }
+
+ public void onOpen(int postFilterId) {
+ setFilter(postFilterId);
+ startBackgroundThread();
+
+ }
+
+ public int getFilterIndex() {
+ return mFilterIndex;
+ }
+
+ public void onClose() {
+ synchronized (lock) {
+ if(mHandler != null) {
+ mHandler.setInActive();
+ }
+ stopBackgroundThread();
+ }
+ setFilter(FILTER_NONE);
+ }
+
+ private void startBackgroundThread() {
+ mHandlerThread = new HandlerThread("PostProcessorThread");
+ mHandlerThread.start();
+ mHandler = new ProcessorHandler(mHandlerThread.getLooper());
+
+ mWatchdog = new WatchdogThread();
+ mWatchdog.start();
+ }
+
+ class WatchdogThread extends Thread {
+ private boolean isAlive = true;
+ private boolean isMonitor = false;
+ private int counter = 0;
+ public void run() {
+ while(isAlive) {
+ try {
+ Thread.sleep(200);
+ }catch(InterruptedException e) {
+ }
+ if(isMonitor) {
+ counter++;
+ if(counter >= 40) { //This is 4 seconds.
+ bark();
+ break;
+ }
+ }
+ }
+
+ }
+
+ public void startMonitor() {
+ isMonitor = true;
+ }
+
+ public void stopMonitor() {
+ isMonitor = false;
+ counter = 0;
+ }
+
+ public void kill() {
+ isAlive = false;
+ }
+ private void bark() {
+ Log.e(TAG, "It takes too long to get the images and process the filter!");
+ int index = getFilterIndex();
+ setFilter(FILTER_NONE);
+ setFilter(index);
+ }
+ }
+
+ class ProcessorHandler extends Handler {
+ boolean isRunning;
+
+ public ProcessorHandler(Looper looper) {
+ super(looper);
+ isRunning = true;
+ }
+
+ public void setInActive() {
+ isRunning = false;
+ }
+ }
+
+ private void stopBackgroundThread() {
+ if (mHandlerThread != null) {
+ mHandlerThread.quitSafely();
+ try {
+ mHandlerThread.join();
+ } catch (InterruptedException e) {
+ }
+ mHandlerThread = null;
+ mHandler = null;
+ }
+ if(mWatchdog != null) {
+ mWatchdog.kill();
+ mWatchdog = null;
+ }
+ clear();
+ }
+
+ public boolean setFilter(int index) {
+ if(index < 0 || index >= FILTER_MAX) {
+ Log.e(TAG, "Invalid scene filter ID");
+ return false;
+ }
+ synchronized (lock) {
+ if (mFilter != null) {
+ mFilter.deinit();
+ }
+ mStatus = STATUS.DEINIT;
+ switch (index) {
+ case FILTER_NONE:
+ mFilter = null;
+ break;
+ case FILTER_OPTIZOOM:
+ mFilter = new OptizoomFilter(mController);
+ break;
+ }
+ }
+
+ if(mFilter != null && !mFilter.isSupported()) {
+ final String filterName = mFilter.getStringName();
+ mFilter = null;
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ RotateTextToast.makeText(mActivity, filterName+" is not supported. ", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ if(mFilter == null) {
+ mFilterIndex = FILTER_NONE;
+ return false;
+ }
+ mFilterIndex = index;
+ mImages = new Image[mFilter.getNumRequiredImage()];
+ return true;
+ }
+
+ private boolean isReadyToProcess() {
+ synchronized (lock) {
+ if (mFilter == null) {
+ return true;
+ }
+ if (mCurrentNumImage >= mFilter.getNumRequiredImage()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void addImage(final Image image) {
+ if(mHandler == null || !mHandler.isRunning) {
+ return;
+ }
+ final ProcessorHandler handler = mHandler;
+ if (mStatus == STATUS.DEINIT) {
+ mWidth = image.getWidth();
+ mHeight = image.getHeight();
+ mStride = image.getPlanes()[0].getRowStride();
+ mStatus = STATUS.INIT;
+ mHandler.post(new Runnable() {
+ public void run() {
+ synchronized (lock) {
+ if(!handler.isRunning) {
+ return;
+ }
+ if(mFilter == null) {
+ //Nothing here we have to do if filter is not chosen.
+ } else {
+ mFilter.init(mWidth, mHeight, mStride, mStride);
+ }
+ }
+ }
+ });
+ }
+ if(mCurrentNumImage == 0) {
+ mStatus = STATUS.BUSY;
+ if(mWatchdog != null) {
+ mWatchdog.startMonitor();
+ }
+ }
+ if(mFilter != null && mCurrentNumImage >= mFilter.getNumRequiredImage()) {
+ return;
+ }
+ final int numImage = mCurrentNumImage;
+ mCurrentNumImage++;
+ if(mHandler == null) {
+ return;
+ }
+ mHandler.post(new Runnable() {
+ public void run() {
+ synchronized (lock) {
+ if(!handler.isRunning) {
+ return;
+ }
+ ByteBuffer yBuf = image.getPlanes()[0].getBuffer();
+ ByteBuffer vuBuf = image.getPlanes()[2].getBuffer();
+ if(mFilter != null && DEBUG_FILTER && numImage == 0) {
+ mDebugResultImage = new ImageFilter.ResultImage(ByteBuffer.allocateDirect(mStride * mHeight*3/2),
+ new Rect(0, 0, mWidth, mHeight), mWidth, mHeight, mStride);
+ yBuf.get(mDebugResultImage.outBuffer.array(), 0, yBuf.remaining());
+ vuBuf.get(mDebugResultImage.outBuffer.array(), mStride * mHeight, vuBuf.remaining());
+ yBuf.rewind();
+ vuBuf.rewind();
+ }
+ if(mFilter == null) {
+ mDefaultResultImage = new ImageFilter.ResultImage(ByteBuffer.allocateDirect(mStride * mHeight*3/2),
+ new Rect(0, 0, mWidth, mHeight), mWidth, mHeight, mStride);
+ yBuf.get(mDefaultResultImage.outBuffer.array(), 0, yBuf.remaining());
+ vuBuf.get(mDefaultResultImage.outBuffer.array(), mStride*mHeight, vuBuf.remaining());
+ image.close();
+ } else {
+ mFilter.addImage(image.getPlanes()[0].getBuffer(),
+ image.getPlanes()[2].getBuffer(), numImage, null);
+ mImages[numImage] = image;
+ }
+ }
+ }
+ });
+ }
+
+ private void clear() {
+ mCurrentNumImage = 0;
+ }
+
+ private void processImage(final String title, final long date,
+ final MediaSaveService.OnMediaSavedListener mediaSavedListener,
+ final ContentResolver contentResolver) {
+ if(mHandler == null || !mHandler.isRunning) {
+ return;
+ }
+ final ProcessorHandler handler = mHandler;
+ mHandler.post(new Runnable() {
+ public void run() {
+ byte[] bytes;
+ ImageFilter.ResultImage resultImage = null;
+ synchronized (lock) {
+ if (!handler.isRunning) {
+ return;
+ }
+ if (mFilter == null) { //In case no post filter is chosen
+ resultImage = mDefaultResultImage;
+ } else {
+ resultImage = mFilter.processImage();
+ for (int i = 0; i < mImages.length; i++) {
+ if(mImages[i] != null) {
+ mImages[i].close();
+ mImages[i] = null;
+ }
+ }
+ }
+ //Start processing FrameProcessor filter as well
+ for (ImageFilter filter : mController.getFrameFilters()) {
+ filter.init(resultImage.width, resultImage.height, resultImage.stride, resultImage.stride);
+ filter.addImage(resultImage.outBuffer, null, 0, new Boolean(false));
+ }
+ //End processing FrameProessor filter
+ clear();
+ mStatus = STATUS.INIT;
+ if(mWatchdog != null) {
+ mWatchdog.stopMonitor();
+ }
+ if((resultImage.outRoi.left + resultImage.outRoi.width() > resultImage.width) ||
+ (resultImage.outRoi.top + resultImage.outRoi.height() > resultImage.height)
+ ) {
+ Log.e(TAG, "Processed outRoi is not within picture range");
+ } else {
+ if(mFilter != null && DEBUG_FILTER) {
+ bytes = nv21ToJpeg(mDebugResultImage);
+ mActivity.getMediaSaveService().addImage(
+ bytes, title + "_beforeApplyingFilter", date, null, mDebugResultImage.outRoi.width(), mDebugResultImage.outRoi.height(),
+ 0, null, mediaSavedListener, contentResolver, "jpeg");
+ }
+ bytes = nv21ToJpeg(resultImage);
+ mController.updateThumbnailJpegData(bytes);
+ mActivity.getMediaSaveService().addImage(
+ bytes, title, date, null, resultImage.outRoi.width(), resultImage.outRoi.height(),
+ 0, null, mediaSavedListener, contentResolver, "jpeg");
+ }
+ }
+ }
+ });
+ }
+
+ private byte[] nv21ToJpeg(ImageFilter.ResultImage resultImage) {
+ BitmapOutputStream bos = new BitmapOutputStream(1024);
+ YuvImage im = new YuvImage(resultImage.outBuffer.array(), ImageFormat.NV21,
+ resultImage.width, resultImage.height, new int[]{resultImage.stride, resultImage.stride});
+ im.compressToJpeg(resultImage.outRoi, 50, bos);
+ return bos.getArray();
+ }
+
+ private class BitmapOutputStream extends ByteArrayOutputStream {
+ public BitmapOutputStream(int size) {
+ super(size);
+ }
+
+ public byte[] getArray() {
+ return buf;
+ }
+ }
+
+
+}
diff --git a/src/com/android/camera/imageprocessor/filter/BeautificationFilter.java b/src/com/android/camera/imageprocessor/filter/BeautificationFilter.java
new file mode 100644
index 000000000..6ec9376d0
--- /dev/null
+++ b/src/com/android/camera/imageprocessor/filter/BeautificationFilter.java
@@ -0,0 +1,134 @@
+/*
+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.imageprocessor.filter;
+
+import android.graphics.Rect;
+import android.hardware.Camera;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.Face;
+import android.util.Log;
+import android.util.Size;
+
+import com.android.camera.CaptureModule;
+import com.android.camera.ui.FilmstripBottomControls;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+public class BeautificationFilter implements ImageFilter {
+
+ int mWidth;
+ int mHeight;
+ int mStrideY;
+ int mStrideVU;
+ private CaptureModule mModule;
+ private static boolean DEBUG = false;
+ private static String TAG = "BeautificationFilter";
+ private static boolean mIsSupported = false;
+
+ public BeautificationFilter(CaptureModule module) {
+ mModule = module;
+ }
+
+ @Override
+ public List<CaptureRequest> setRequiredImages(CaptureRequest.Builder builder) {
+ return null;
+ }
+
+ @Override
+ public String getStringName() {
+ return "BeautificationFilter";
+ }
+
+ @Override
+ public int getNumRequiredImage() {
+ return 0;
+ }
+
+ @Override
+ public void init(int width, int height, int strideY, int strideVU) {
+ mWidth = width;
+ mHeight = height;
+ mStrideY = strideY;
+ mStrideVU = strideVU;
+ }
+
+ @Override
+ public void deinit() {
+
+ }
+
+ @Override
+ public void addImage(ByteBuffer bY, ByteBuffer bVU, int imageNum, Object isPreview) {
+ Rect back = mModule.getCameraRegion();
+ Face[] faces;
+ if(((Boolean)isPreview).booleanValue()) {
+ faces = mModule.getPreviewFaces();
+ } else {
+ faces = mModule.getStickyFaces();
+ }
+ float widthRatio = (float)mWidth/back.width();
+ float heightRatio = (float)mHeight/back.height();
+ if(faces == null || faces.length == 0)
+ return;
+ Rect rect = faces[0].getBounds();
+ int value = nativeBeautificationProcess(bY, bVU, mWidth, mHeight, mStrideY,
+ (int)(rect.left*widthRatio), (int)(rect.top*heightRatio),
+ (int)(rect.right*widthRatio), (int)(rect.bottom*heightRatio));
+ if(DEBUG && value < 0) {
+ if(value == -1) {
+ Log.d(TAG, "library initialization is failed.");
+ } else if(value == -2) {
+ Log.d(TAG, "No face is recognized");
+ }
+ }
+ }
+
+ @Override
+ public ResultImage processImage() {
+ return null;
+ }
+
+ @Override
+ public boolean isSupported() {
+ return mIsSupported;
+ }
+
+ private native int nativeBeautificationProcess(ByteBuffer yB, ByteBuffer vuB,
+ int width, int height, int stride, int fleft, int ftop, int fright, int fbottom);
+
+ static {
+ try {
+ System.loadLibrary("jni_makeup");
+ mIsSupported = true;
+ }catch(UnsatisfiedLinkError e) {
+ mIsSupported = false;
+ }
+ }
+}
diff --git a/src/com/android/camera/imageprocessor/filter/ImageFilter.java b/src/com/android/camera/imageprocessor/filter/ImageFilter.java
new file mode 100644
index 000000000..e62d9b30a
--- /dev/null
+++ b/src/com/android/camera/imageprocessor/filter/ImageFilter.java
@@ -0,0 +1,74 @@
+/*
+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.imageprocessor.filter;
+
+import android.graphics.Rect;
+import android.hardware.camera2.CaptureRequest;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+public interface ImageFilter {
+
+ /* Return the number of required images to process*/
+ List<CaptureRequest> setRequiredImages(CaptureRequest.Builder builder);
+
+ String getStringName();
+
+ int getNumRequiredImage();
+
+ void init(int width, int height, int strideY, int strideVU);
+
+ /* Free all buffer */
+ void deinit();
+
+ /* Adding the image to process */
+ void addImage(ByteBuffer bY, ByteBuffer bVU, int imageNum, Object param);
+
+ /* Processing all the added images and return roi*/
+ ResultImage processImage();
+
+ boolean isSupported();
+
+ class ResultImage {
+ public ByteBuffer outBuffer;
+ public Rect outRoi;
+ public int width;
+ public int height;
+ public int stride;
+
+ public ResultImage(ByteBuffer buf, Rect roi, int width, int height, int stride) {
+ outBuffer = buf;
+ outRoi = roi;
+ this.width = width;
+ this.height = height;
+ this.stride = stride;
+ }
+ }
+}
diff --git a/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java b/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java
new file mode 100644
index 000000000..4773418de
--- /dev/null
+++ b/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java
@@ -0,0 +1,148 @@
+/*
+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.imageprocessor.filter;
+
+import android.graphics.Rect;
+import android.hardware.camera2.CaptureRequest;
+import android.util.Log;
+
+import com.android.camera.CaptureModule;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+public class OptizoomFilter implements ImageFilter{
+ public static final int NUM_REQUIRED_IMAGE = 8;
+ private int mWidth;
+ private int mHeight;
+ private int mStrideY;
+ private int mStrideVU;
+ private static String TAG = "OptizoomFilter";
+ private static final boolean DEBUG = true; //TODO: Have to be false before releasing.
+ private int temp;
+ private static boolean mIsSupported = true;
+ private ByteBuffer mOutBuf;
+ private CaptureModule mModule;
+
+ private static void Log(String msg) {
+ if(DEBUG) {
+ Log.d(TAG, msg);
+ }
+ }
+
+ public OptizoomFilter(CaptureModule module) {
+ mModule = module;
+ }
+
+ @Override
+ public List<CaptureRequest> setRequiredImages(CaptureRequest.Builder builder) {
+ List<CaptureRequest> list = new ArrayList<CaptureRequest>();
+ for(int i=0; i < NUM_REQUIRED_IMAGE; i++) {
+ list.add(builder.build());
+ }
+ return list;
+ }
+
+ @Override
+ public String getStringName() {
+ return "OptizoomFilter";
+ }
+
+ @Override
+ public int getNumRequiredImage() {
+ return NUM_REQUIRED_IMAGE;
+ }
+
+ @Override
+ public void init(int width, int height, int strideY, int strideVU) {
+ Log("init");
+ mWidth = width/2*2;
+ mHeight = height/2*2;
+ mStrideY = strideY/2*2;
+ mStrideVU = strideVU/2*2;
+ mOutBuf = ByteBuffer.allocate(mStrideY*mHeight*6); // YUV Buffer to hold (mWidth*2) X (mHeight*2)
+ Log("width: "+mWidth+" height: "+mHeight+" strideY: "+mStrideY+" strideVU: "+mStrideVU);
+ nativeInit(mWidth, mHeight, mStrideY, mStrideVU,
+ 0, 0, mWidth, mHeight, NUM_REQUIRED_IMAGE);
+ }
+
+ @Override
+ public void deinit() {
+ Log("deinit");
+ mOutBuf = null;
+ nativeDeinit();
+ }
+
+ @Override
+ public void addImage(ByteBuffer bY, ByteBuffer bVU, int imageNum, Object param) {
+ Log("addImage");
+ int yActualSize = bY.remaining();
+ int vuActualSize = bVU.remaining();
+ nativeAddImage(bY, bVU, yActualSize, vuActualSize, imageNum);
+ }
+
+ @Override
+ public ResultImage processImage() {
+ Log("processImage " + mModule.getZoomValue());
+ int[] roi = new int[4];
+ int status = nativeProcessImage(mOutBuf.array(), mModule.getZoomValue(), roi);
+ Log("processImage done");
+ if(status < 0) { //In failure case, library will return the first image as it is.
+ Log.w(TAG, "Fail to process the optizoom. It only processes when zoomValue >= 1.5f");
+ return new ResultImage(mOutBuf, new Rect(roi[0], roi[1], roi[0]+roi[2], roi[1] + roi[3]), mWidth, mHeight, mStrideY);
+ } else { //In success case, it will return twice bigger width and height.
+ return new ResultImage(mOutBuf, new Rect(roi[0], roi[1], roi[0]+roi[2], roi[1] + roi[3]), mWidth*2, mHeight*2, mStrideY*2);
+ }
+ }
+
+ @Override
+ public boolean isSupported() {
+ return mIsSupported;
+ }
+
+ public static boolean isSupportedStatic() {
+ return mIsSupported;
+ }
+
+ private native int nativeInit(int width, int height, int yStride, int vuStride,
+ int roiX, int roiY, int roiW, int roiH, int numImages);
+ private native int nativeDeinit();
+ private native int nativeAddImage(ByteBuffer yB, ByteBuffer vuB, int ySize, int vuSize, int imageNum);
+ private native int nativeProcessImage(byte[] buffer, float zoomLvl, int[] roi);
+
+ static {
+ try {
+ System.loadLibrary("jni_optizoom");
+ mIsSupported = true;
+ }catch(UnsatisfiedLinkError e) {
+ mIsSupported = false;
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index 1f9c8d921..e6e00ad56 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -37,7 +37,6 @@ import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
-import com.android.camera.CaptureMenu;
import com.android.camera.PhotoMenu;
import com.android.camera.VideoMenu;
import com.android.camera.PreviewGestures;
@@ -1832,7 +1831,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
return true;
PhotoMenu pMenu = mPreviewGestures.getPhotoMenu();
VideoMenu vMenu = mPreviewGestures.getVideoMenu();
- CaptureMenu cMenu = mPreviewGestures.getCaptureMenu();
+
if (pMenu != null) {
if (pMenu.isMenuBeingShown()) {
if (pMenu.isMenuBeingAnimated()) {
@@ -1850,23 +1849,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
}
}
}
- if (cMenu != null) {
- if (cMenu.isMenuBeingShown()) {
- if (cMenu.isMenuBeingAnimated()) {
- if (cMenu.isOverMenu(ev)) {
- mSendToMenu = true;
- return true;
- }
- }
- }
- if (cMenu.isPreviewMenuBeingShown()) {
- if (cMenu.isOverPreviewMenu(ev)) {
- mSendToPreviewMenu = true;
- return true;
- }
- }
- }
if (vMenu != null) {
if (vMenu.isMenuBeingShown()) {
if (vMenu.isMenuBeingAnimated()) {
@@ -1903,7 +1886,6 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
}
PhotoMenu pMenu = mPreviewGestures.getPhotoMenu();
VideoMenu vMenu = mPreviewGestures.getVideoMenu();
- CaptureMenu cMenu = mPreviewGestures.getCaptureMenu();
if (pMenu != null) {
if (mSendToPreviewMenu)
return pMenu.sendTouchToPreviewMenu(ev);
@@ -1917,19 +1899,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
return pMenu.sendTouchToPreviewMenu(ev);
}
}
- if (cMenu != null) {
- if (mSendToPreviewMenu)
- return cMenu.sendTouchToPreviewMenu(ev);
- if (mSendToMenu)
- return cMenu.sendTouchToMenu(ev);
- if (cMenu.isMenuBeingShown()) {
- return cMenu.sendTouchToMenu(ev);
- }
- if (cMenu.isPreviewMenuBeingShown()) {
- return cMenu.sendTouchToPreviewMenu(ev);
- }
- }
if (vMenu != null) {
if (mSendToPreviewMenu)
return vMenu.sendTouchToPreviewMenu(ev);
diff --git a/src/com/android/camera/ui/ListMenu.java b/src/com/android/camera/ui/ListMenu.java
index 1c9c611e3..d83114cce 100644
--- a/src/com/android/camera/ui/ListMenu.java
+++ b/src/com/android/camera/ui/ListMenu.java
@@ -19,8 +19,6 @@
package com.android.camera.ui;
-import java.util.ArrayList;
-
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
@@ -34,21 +32,40 @@ import android.widget.ListView;
import com.android.camera.ListPreference;
import com.android.camera.PreferenceGroup;
+import com.android.camera.SettingsManager;
+
import org.codeaurora.snapcam.R;
+import java.util.ArrayList;
+import java.util.List;
+
/* A popup window that contains several camera settings. */
public class ListMenu extends ListView
implements ListMenuItem.Listener,
- AdapterView.OnItemClickListener {
+ AdapterView.OnItemClickListener,
+ ListSubMenu.Listener {
@SuppressWarnings("unused")
private static final String TAG = "ListMenu";
private int mHighlighted = -1;
private Listener mListener;
+ private SettingsManager mSettingsManager;
private ArrayList<ListPreference> mListItem = new ArrayList<ListPreference>();
// Keep track of which setting items are disabled
// e.g. White balance will be disabled when scene mode is set to non-auto
private boolean[] mEnabled;
+ private boolean mForCamera2 = false;
+
+ @Override
+ public void onListPrefChanged(ListPreference pref) {
+ // listen from ListSubMenu
+ if (mListener != null) {
+ mListener.onSettingChanged(pref);
+ }
+ if (mSettingsManager != null) {
+ mSettingsManager.onSettingChanged(pref);
+ }
+ }
static public interface Listener {
public void onSettingChanged(ListPreference pref);
@@ -60,6 +77,11 @@ public class ListMenu extends ListView
public void onListMenuTouched();
}
+ static public interface SettingsListener {
+ // notify SettingsManager
+ public void onSettingChanged(ListPreference pref);
+ }
+
private class MoreSettingAdapter extends ArrayAdapter<ListPreference> {
LayoutInflater mInflater;
String mOnString;
@@ -90,6 +112,9 @@ public class ListMenu extends ListView
view.setSettingChangedListener(ListMenu.this);
if (position >= 0 && position < mEnabled.length) {
view.setEnabled(mEnabled[position]);
+ if (mForCamera2 && !mEnabled[position]) {
+ view.overrideSettings(mSettingsManager.getValue(pref.getKey()));
+ }
} else {
Log.w(TAG, "Invalid input: enabled list length, " + mEnabled.length
+ " position " + position);
@@ -109,6 +134,10 @@ public class ListMenu extends ListView
}
}
+ public void setSettingsManager(SettingsManager settingsManager) {
+ mSettingsManager = settingsManager;
+ }
+
public void setSettingChangedListener(Listener listener) {
mListener = listener;
}
@@ -117,6 +146,32 @@ public class ListMenu extends ListView
super(context, attrs);
}
+ public void initializeForCamera2(String[] keys) {
+ mForCamera2 = true;
+ PreferenceGroup group = mSettingsManager.getPreferenceGroup();
+ List<String> disabledList = mSettingsManager.getDisabledList();
+ // Prepare the setting items.
+ for (int i = 0; i < keys.length; ++i) {
+ ListPreference pref = group.findPreference(keys[i]);
+ if (pref != null)
+ mListItem.add(pref);
+ }
+
+ ArrayAdapter<ListPreference> mListItemAdapter = new MoreSettingAdapter();
+ setAdapter(mListItemAdapter);
+ setOnItemClickListener(this);
+ setSelector(android.R.color.transparent);
+ // Initialize mEnabled
+ mEnabled = new boolean[mListItem.size()];
+ for (int i = 0; i < mEnabled.length; i++) {
+ mEnabled[i] = true;
+ }
+
+ for (String s: disabledList) {
+ setPreferenceEnabled(s, false);
+ }
+ }
+
public void initialize(PreferenceGroup group, String[] keys) {
// Prepare the setting items.
for (int i = 0; i < keys.length; ++i) {
diff --git a/src/com/android/camera/ui/ListMenuItem.java b/src/com/android/camera/ui/ListMenuItem.java
index f3c7f017e..b051fdd27 100644
--- a/src/com/android/camera/ui/ListMenuItem.java
+++ b/src/com/android/camera/ui/ListMenuItem.java
@@ -159,4 +159,26 @@ public class ListMenuItem extends RelativeLayout {
setAlpha(0.3f);
}
}
+
+ public void setEnabled(boolean enable, String value) {
+ super.setEnabled(enable);
+ if (enable)
+ setAlpha(1f);
+ else
+ setAlpha(0.3f);
+ if (mTitle != null) {
+ mTitle.setEnabled(enable);
+ if (enable)
+ setAlpha(1f);
+ else
+ setAlpha(0.3f);
+ }
+ if (mEntry != null) {
+ mEntry.setEnabled(enable);
+ if (enable)
+ setAlpha(1f);
+ else
+ setAlpha(0.3f);
+ }
+ }
}
diff --git a/src/com/android/camera/ui/ListSubMenu.java b/src/com/android/camera/ui/ListSubMenu.java
index 3501af3bc..a425c7680 100644
--- a/src/com/android/camera/ui/ListSubMenu.java
+++ b/src/com/android/camera/ui/ListSubMenu.java
@@ -136,8 +136,9 @@ public class ListSubMenu extends ListView implements
public void onItemClick(AdapterView<?> parent, View view,
int index, long id) {
mPreference.setValueIndex(index);
- if (mListener != null)
+ if (mListener != null) {
mListener.onListPrefChanged(mPreference);
+ }
}
@Override
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index b1deca6e0..812220c1a 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -35,7 +35,6 @@ import android.hardware.Camera;
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;
@@ -1169,32 +1168,4 @@ public class CameraUtil {
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;
- }
}
diff --git a/src/com/android/camera/util/PersistUtil.java b/src/com/android/camera/util/PersistUtil.java
new file mode 100644
index 000000000..c9a5a474a
--- /dev/null
+++ b/src/com/android/camera/util/PersistUtil.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util;
+
+import android.os.SystemProperties;
+
+public class PersistUtil {
+
+ private static final String PERSIST_MEMORY_LIMIT = "persist.camera.perf.memlimit";
+ private static final String PERSIST_SKIP_MEMORY_CHECK = "persist.camera.perf.skip_memck";
+ private static final String PERSIST_LONGSHOT_SHOT_LIMIT = "persist.camera.longshot.shotnum";
+
+ public static int getMemoryLimit() {
+ return SystemProperties.getInt(PERSIST_MEMORY_LIMIT, 60);
+ }
+
+ public static boolean getSkipMemoryCheck() {
+ return SystemProperties.getBoolean(PERSIST_SKIP_MEMORY_CHECK, false);
+ }
+
+ public static int getLongshotShotLimit() {
+ return SystemProperties.getInt(PERSIST_LONGSHOT_SHOT_LIMIT, 20);
+ }
+
+}