summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanthosh Kumar H E <skhara@codeaurora.org>2014-01-21 19:21:42 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2014-02-27 05:01:12 -0800
commitb2da1c165bb60154b7cc64db8b7d832fa02b2708 (patch)
tree9a695f64007217b00399651da4f19eca0a3c2fe6
parent40aad1d5fb7ad8828b25c502165eaa557327edc2 (diff)
downloadandroid_packages_apps_Snap-b2da1c165bb60154b7cc64db8b7d832fa02b2708.tar.gz
android_packages_apps_Snap-b2da1c165bb60154b7cc64db8b7d832fa02b2708.tar.bz2
android_packages_apps_Snap-b2da1c165bb60154b7cc64db8b7d832fa02b2708.zip
Camera: Add a feature to choose where to store the picture and video
Add a feature to choose use SDcard or phone to store picture and video captured by camera and camcorder. Some of the changes are taken from: I987a691c93edc4250fe0366d0623c85ea0152117 CRs-Fixed: 619806 Change-Id: I009df4c70f0a1b49b20750f806c799f025bb6197
-rw-r--r--AndroidManifest.xml1
-rw-r--r--res/values/arrays.xml11
-rw-r--r--res/values/strings.xml6
-rw-r--r--res/xml/camera_preferences.xml6
-rw-r--r--res/xml/video_preferences.xml6
-rw-r--r--src/com/android/camera/CameraSettings.java1
-rw-r--r--src/com/android/camera/PhotoMenu.java3
-rw-r--r--src/com/android/camera/PhotoModule.java11
-rw-r--r--src/com/android/camera/SDCard.java107
-rw-r--r--src/com/android/camera/Storage.java70
-rw-r--r--src/com/android/camera/VideoMenu.java3
-rw-r--r--src/com/android/camera/VideoModule.java15
-rw-r--r--src/com/android/camera/data/CameraDataAdapter.java9
13 files changed, 223 insertions, 26 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0a98e1622..9e9b364c1 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -30,6 +30,7 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index c740d26be..d841d39a8 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -59,6 +59,17 @@
<item>2</item>
</string-array>
+ <!-- Camera Preference save path entries -->
+ <string-array name="pref_camera_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_camera_savepath_entryvalues" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ </string-array>
+
<!-- These values correspond to the time interval between frame capture in millseconds
for time lapse recording -->
<string-array name="pref_video_time_lapse_frame_interval_entryvalues" translatable="false">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index dc23bc1aa..370254961 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -219,6 +219,12 @@
<!-- Text followed by a checkbox to turn on/off sound effects during the countdown. [CHAR LIMIT = 24]-->
<string name="pref_camera_timer_sound_title">Beep during countdown</string>
+ <!-- Entry of camera save path -->
+ <string name="pref_camera_savepath_title">Storage Position</string>
+ <string name="pref_camera_savepath_default">0</string>
+ <string name="pref_camera_savepath_entry_0">Phone</string>
+ <string name="pref_camera_savepath_entry_1">SD Card</string>
+
<!-- Entry of a on/off setting. The setting is turned off. [CHAR LIMIT=15] -->
<string name="setting_off">Off</string>
<!-- Entry of a on/off setting. The setting is turned on. [CHAR LIMIT=15] -->
diff --git a/res/xml/camera_preferences.xml b/res/xml/camera_preferences.xml
index c6ac85929..c3afedecf 100644
--- a/res/xml/camera_preferences.xml
+++ b/res/xml/camera_preferences.xml
@@ -225,6 +225,12 @@
camera:entries="@array/pref_camera_zsl_entries"
camera:entryValues="@array/pref_camera_zsl_entryvalues" />
<ListPreference
+ camera:key="pref_camera_savepath_key"
+ camera:defaultValue="@string/pref_camera_savepath_default"
+ camera:title="@string/pref_camera_savepath_title"
+ camera:entries="@array/pref_camera_savepath_entries"
+ camera:entryValues="@array/pref_camera_savepath_entryvalues" />
+ <ListPreference
camera:key="pref_camera_videosnapsize_key"
camera:title="@string/pref_camera_picturesize_title"
camera:defaultValue="@string/pref_camera_videosnapsize_default"
diff --git a/res/xml/video_preferences.xml b/res/xml/video_preferences.xml
index ab876b81c..2ea5fa1ba 100644
--- a/res/xml/video_preferences.xml
+++ b/res/xml/video_preferences.xml
@@ -126,4 +126,10 @@
camera:title="@string/pref_camera_picturesize_title"
camera:entries="@array/pref_camera_picturesize_entries"
camera:entryValues="@array/pref_camera_picturesize_entryvalues" />
+ <ListPreference
+ camera:key="pref_camera_savepath_key"
+ camera:defaultValue="@string/pref_camera_savepath_default"
+ camera:title="@string/pref_camera_savepath_title"
+ camera:entries="@array/pref_camera_savepath_entries"
+ camera:entryValues="@array/pref_camera_savepath_entryvalues" />
</PreferenceGroup>
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 6ce53b720..60656cd08 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -78,6 +78,7 @@ public class CameraSettings {
public static final String KEY_POWER_MODE = "pref_camera_powermode_key";
public static final String KEY_PICTURE_FORMAT = "pref_camera_pictureformat_key";
public static final String KEY_ZSL = "pref_camera_zsl_key";
+ public static final String KEY_CAMERA_SAVEPATH = "pref_camera_savepath_key";
public static final String KEY_COLOR_EFFECT = "pref_camera_coloreffect_key";
public static final String KEY_FACE_DETECTION = "pref_camera_facedetection_key";
public static final String KEY_TOUCH_AF_AEC = "pref_camera_touchafaec_key";
diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java
index cdef2fa53..00feadf37 100644
--- a/src/com/android/camera/PhotoMenu.java
+++ b/src/com/android/camera/PhotoMenu.java
@@ -99,7 +99,8 @@ public class PhotoMenu extends PieController
CameraSettings.KEY_JPEG_QUALITY,
CameraSettings.KEY_ZSL,
CameraSettings.KEY_TIMER,
- CameraSettings.KEY_TIMER_SOUND_EFFECTS
+ CameraSettings.KEY_TIMER_SOUND_EFFECTS,
+ CameraSettings.KEY_CAMERA_SAVEPATH
};
mOtherKeys2 = new String[] {
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index dd0521576..3fa182b5f 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -494,6 +494,8 @@ public class PhotoModule
Title = (TextView)mRootView.findViewById(R.id.skintonetitle);
RightValue = (TextView)mRootView.findViewById(R.id.skintoneright);
LeftValue = (TextView)mRootView.findViewById(R.id.skintoneleft);
+ Storage.setSaveSDCard(
+ mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1"));
}
@@ -1712,6 +1714,12 @@ public class PhotoModule
Log.v(TAG, "On resume.");
onResumeTasks();
}
+ mHandler.post(new Runnable(){
+ @Override
+ public void run(){
+ mActivity.updateStorageSpaceAndHint();
+ }
+ });
}
private void onResumeTasks() {
@@ -2811,6 +2819,9 @@ public class PhotoModule
disableSkinToneSeekBar();
}
}
+ Storage.setSaveSDCard(
+ mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1"));
+ mActivity.updateStorageSpaceAndHint();
}
@Override
diff --git a/src/com/android/camera/SDCard.java b/src/com/android/camera/SDCard.java
new file mode 100644
index 000000000..dad354007
--- /dev/null
+++ b/src/com/android/camera/SDCard.java
@@ -0,0 +1,107 @@
+/* Copyright (c) 2014, 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.os.StatFs;
+import android.os.Environment;
+import android.os.storage.StorageVolume;
+import android.os.storage.IMountService;
+import android.os.ServiceManager;
+import android.util.Log;
+
+public class SDCard {
+ private static final String TAG = "SDCard";
+
+ private static final int VOLUME_SDCARD_INDEX = 1;
+ private IMountService mMountService = null;
+ private StorageVolume mVolume = null;
+ private String path = null;
+ private String rawpath = null;
+ private static SDCard sSDCard;
+
+ public boolean isWriteable() {
+ if (mVolume == null) return false;
+ final String state = getSDCardStorageState();
+ if (Environment.MEDIA_MOUNTED.equals(state)) {
+ return true;
+ }
+ return false;
+ }
+
+ public String getDirectory() {
+ if (mVolume == null) {
+ return null;
+ }
+ if (path == null) {
+ path = mVolume.getPath() + "/DCIM/Camera";
+ }
+ return path;
+ }
+
+ public String getRawDirectory() {
+ if (mVolume == null) {
+ return null;
+ }
+ if (rawpath == null) {
+ rawpath = mVolume.getPath() + "/DCIM/Camera/raw";
+ }
+ return rawpath;
+ }
+
+ public static synchronized SDCard instance() {
+ if (sSDCard == null) {
+ sSDCard = new SDCard();
+ }
+ return sSDCard;
+ }
+
+ private String getSDCardStorageState() {
+ try {
+ return mMountService.getVolumeState(mVolume.getPath());
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to read SDCard storage state; assuming REMOVED: " + e);
+ return Environment.MEDIA_REMOVED;
+ }
+ }
+
+ private SDCard() {
+ try {
+ mMountService = IMountService.Stub.asInterface(ServiceManager
+ .getService("mount"));
+ final StorageVolume[] volumes = mMountService.getVolumeList();
+ if (volumes.length > VOLUME_SDCARD_INDEX) {
+ mVolume = volumes[VOLUME_SDCARD_INDEX];
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "couldn't talk to MountService", e);
+ }
+ }
+
+}
diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java
index 29dad8aa4..4c966d47b 100644
--- a/src/com/android/camera/Storage.java
+++ b/src/com/android/camera/Storage.java
@@ -55,6 +55,16 @@ public class Storage {
public static final long UNKNOWN_SIZE = -3L;
public static final long LOW_STORAGE_THRESHOLD_BYTES = 50000000;
+ private static boolean sSaveSDCard = false;
+
+ public static boolean isSaveSDCard() {
+ return sSaveSDCard;
+ }
+
+ public static void setSaveSDCard(boolean saveSDCard) {
+ sSaveSDCard = saveSDCard;
+ }
+
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private static void setImageSize(ContentValues values, int width, int height) {
// The two fields are available since ICS but got published in JB
@@ -193,36 +203,54 @@ public class Storage {
}
public static String generateFilepath(String title, String pictureFormat) {
- if (pictureFormat.equalsIgnoreCase("jpeg") || pictureFormat == null) {
- return DIRECTORY + '/' + title + ".jpg";
+ if (pictureFormat == null || pictureFormat.equalsIgnoreCase("jpeg")) {
+ if (isSaveSDCard() && SDCard.instance().isWriteable()) {
+ return SDCard.instance().getDirectory() + '/' + title + ".jpg";
+ } else {
+ return DIRECTORY + '/' + title + ".jpg";
+ }
} else {
return RAW_DIRECTORY + '/' + title + ".raw";
}
}
public static long getAvailableSpace() {
- String state = Environment.getExternalStorageState();
- Log.d(TAG, "External storage state=" + state);
- if (Environment.MEDIA_CHECKING.equals(state)) {
- return PREPARING;
- }
- if (!Environment.MEDIA_MOUNTED.equals(state)) {
- return UNAVAILABLE;
- }
+ if (isSaveSDCard() && SDCard.instance().isWriteable()) {
+ File dir = new File(SDCard.instance().getDirectory());
+ dir.mkdirs();
+ try {
+ StatFs stat = new StatFs(SDCard.instance().getDirectory());
+ long ret = stat.getAvailableBlocks() * (long) stat.getBlockSize();
+ return ret;
+ } catch (Exception e) {
+ }
+ return UNKNOWN_SIZE;
+ } else if (isSaveSDCard() && !SDCard.instance().isWriteable()) {
+ return UNKNOWN_SIZE;
+ } else {
+ String state = Environment.getExternalStorageState();
+ Log.d(TAG, "External storage state=" + state);
+ if (Environment.MEDIA_CHECKING.equals(state)) {
+ return PREPARING;
+ }
+ if (!Environment.MEDIA_MOUNTED.equals(state)) {
+ return UNAVAILABLE;
+ }
- File dir = new File(DIRECTORY);
- dir.mkdirs();
- if (!dir.isDirectory() || !dir.canWrite()) {
- return UNAVAILABLE;
- }
+ File dir = new File(DIRECTORY);
+ dir.mkdirs();
+ if (!dir.isDirectory() || !dir.canWrite()) {
+ return UNAVAILABLE;
+ }
- try {
- StatFs stat = new StatFs(DIRECTORY);
- return stat.getAvailableBlocks() * (long) stat.getBlockSize();
- } catch (Exception e) {
- Log.i(TAG, "Fail to access external storage", e);
+ try {
+ StatFs stat = new StatFs(DIRECTORY);
+ return stat.getAvailableBlocks() * (long) stat.getBlockSize();
+ } catch (Exception e) {
+ Log.i(TAG, "Fail to access external storage", e);
+ }
+ return UNKNOWN_SIZE;
}
- return UNKNOWN_SIZE;
}
/**
diff --git a/src/com/android/camera/VideoMenu.java b/src/com/android/camera/VideoMenu.java
index 01b9ddbc4..440c70c46 100644
--- a/src/com/android/camera/VideoMenu.java
+++ b/src/com/android/camera/VideoMenu.java
@@ -71,7 +71,8 @@ public class VideoMenu extends PieController
CameraSettings.KEY_VIDEO_ENCODER,
CameraSettings.KEY_AUDIO_ENCODER,
CameraSettings.KEY_VIDEO_DURATION,
- CameraSettings.KEY_RECORD_LOCATION
+ CameraSettings.KEY_RECORD_LOCATION,
+ CameraSettings.KEY_CAMERA_SAVEPATH
};
//settings popup
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index f8db15bec..b3dd884e8 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -118,6 +118,8 @@ public class VideoModule implements CameraModule,
private ComboPreferences mPreferences;
private PreferenceGroup mPreferenceGroup;
+ private boolean mSaveToSDCard = false;
+
// Preference must be read before starting preview. We check this before starting
// preview.
private boolean mPreferenceRead;
@@ -425,6 +427,9 @@ public class VideoModule implements CameraModule,
mContentResolver = mActivity.getContentResolver();
+ Storage.setSaveSDCard(
+ mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1"));
+ mSaveToSDCard = Storage.isSaveSDCard();
// Surface texture is from camera screen nail and startPreview needs it.
// This must be done before startPreview.
mIsVideoCaptureIntent = isVideoCaptureIntent();
@@ -1309,7 +1314,12 @@ public class VideoModule implements CameraModule,
// Used when emailing.
String filename = title + convertOutputFormatToFileExt(outputFileFormat);
String mime = convertOutputFormatToMimeType(outputFileFormat);
- String path = Storage.DIRECTORY + '/' + filename;
+ String path = null;
+ if (Storage.isSaveSDCard() && SDCard.instance().isWriteable()) {
+ path = SDCard.instance().getDirectory() + '/' + filename;
+ } else {
+ path = Storage.DIRECTORY + '/' + filename;
+ }
String tmpPath = path + ".tmp";
mCurrentVideoValues = new ContentValues(9);
mCurrentVideoValues.put(Video.Media.TITLE, title);
@@ -2067,6 +2077,9 @@ public class VideoModule implements CameraModule,
}
mRestartPreview = false;
mUI.updateOnScreenIndicators(mParameters, mPreferences);
+ Storage.setSaveSDCard(
+ mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1"));
+ mActivity.updateStorageSpaceAndHint();
}
}
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index 77e665191..4643d03bf 100644
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -27,6 +27,7 @@ import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
+import com.android.camera.SDCard;
import com.android.camera.Storage;
import com.android.camera.app.PlaceholderManager;
import com.android.camera.ui.FilmStripView.ImageData;
@@ -41,7 +42,7 @@ public class CameraDataAdapter implements LocalDataAdapter {
private static final String TAG = "CAM_CameraDataAdapter";
private static final int DEFAULT_DECODE_SIZE = 1600;
- private static final String[] CAMERA_PATH = { Storage.DIRECTORY + "%" };
+ private static final String[] CAMERA_PATH = { Storage.DIRECTORY + "/%" ,SDCard.instance().getDirectory() + "/%"};
private LocalDataList mImages;
@@ -135,7 +136,8 @@ public class CameraDataAdapter implements LocalDataAdapter {
public void addNewVideo(ContentResolver cr, Uri uri) {
Cursor c = cr.query(uri,
LocalMediaData.VideoData.QUERY_PROJECTION,
- MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH,
+ MediaStore.Video.Media.DATA + " like ? or " +
+ MediaStore.Video.Media.DATA + " like ? ", CAMERA_PATH,
LocalMediaData.VideoData.QUERY_ORDER);
if (c == null || !c.moveToFirst()) {
return;
@@ -161,6 +163,7 @@ public class CameraDataAdapter implements LocalDataAdapter {
public void addNewPhoto(ContentResolver cr, Uri uri) {
Cursor c = cr.query(uri,
LocalMediaData.PhotoData.QUERY_PROJECTION,
+ MediaStore.Images.Media.DATA + " like ? or " +
MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH,
LocalMediaData.PhotoData.QUERY_ORDER);
if (c == null || !c.moveToFirst()) {
@@ -285,6 +288,7 @@ public class CameraDataAdapter implements LocalDataAdapter {
Cursor c = resolver[0].query(
LocalMediaData.PhotoData.CONTENT_URI,
LocalMediaData.PhotoData.QUERY_PROJECTION,
+ MediaStore.Images.Media.DATA + " like ? or " +
MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH,
LocalMediaData.PhotoData.QUERY_ORDER);
if (c != null && c.moveToFirst()) {
@@ -314,6 +318,7 @@ public class CameraDataAdapter implements LocalDataAdapter {
c = resolver[0].query(
LocalMediaData.VideoData.CONTENT_URI,
LocalMediaData.VideoData.QUERY_PROJECTION,
+ MediaStore.Video.Media.DATA + " like ? or " +
MediaStore.Video.Media.DATA + " like ? ", CAMERA_PATH,
LocalMediaData.VideoData.QUERY_ORDER);
if (c != null && c.moveToFirst()) {