Merge changes from topic "api29" am: 55d843fcf1 am: d96b5af9c4 am: b0382e4d82
Original change: https://android-review.googlesource.com/c/platform/packages/apps/Camera2/+/1347923
Change-Id: Id5489bab88a226880128d6d5cc173e626d388538
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 002bf5f..751d08a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -6,7 +6,7 @@
<uses-sdk
android:minSdkVersion="19"
- android:targetSdkVersion="28" />
+ android:targetSdkVersion="1000" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -26,7 +26,6 @@
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<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_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 6b81641..9de0037 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -889,7 +889,7 @@
@Override
public void onSessionQueued(final Uri uri) {
Log.v(TAG, "onSessionQueued: " + uri);
- if (!Storage.isSessionUri(uri)) {
+ if (!Storage.instance().isSessionUri(uri)) {
return;
}
Optional<SessionItem> newData = SessionItem.create(getApplicationContext(), uri);
@@ -907,7 +907,7 @@
@Override
public void onSessionDone(final Uri sessionUri) {
Log.v(TAG, "onSessionDone:" + sessionUri);
- Uri contentUri = Storage.getContentUriForSessionUri(sessionUri);
+ Uri contentUri = Storage.instance().getContentUriForSessionUri(sessionUri);
if (contentUri == null) {
mDataAdapter.refresh(sessionUri);
return;
@@ -936,7 +936,7 @@
&& mFilmstripController.isVisible(oldSessionData)) {
Log.v(TAG, "session item visible, setting transition placeholder");
newData.setSessionPlaceholderBitmap(
- Storage.getPlaceholderForSession(sessionUri));
+ Storage.instance().getPlaceholderForSession(sessionUri));
}
mDataAdapter.updateItemAt(pos, newData);
}
@@ -1932,8 +1932,7 @@
}
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED &&
- checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED &&
- checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
+ checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
mHasCriticalPermissions = true;
} else {
mHasCriticalPermissions = false;
@@ -2381,7 +2380,7 @@
@Override
protected Long doInBackground(Void ... arg) {
synchronized (mStorageSpaceLock) {
- mStorageSpaceBytes = Storage.getAvailableSpace();
+ mStorageSpaceBytes = Storage.instance().getAvailableSpace();
return mStorageSpaceBytes;
}
}
diff --git a/src/com/android/camera/MediaSaverImpl.java b/src/com/android/camera/MediaSaverImpl.java
index 3107bb5..a8e96ec 100644
--- a/src/com/android/camera/MediaSaverImpl.java
+++ b/src/com/android/camera/MediaSaverImpl.java
@@ -179,7 +179,7 @@
height = options.outHeight;
}
try {
- return Storage.addImage(
+ return Storage.instance().addImage(
resolver, title, date, loc, orientation, exif, data, width, height,
mimeType);
} catch (IOException e) {
diff --git a/src/com/android/camera/PermissionsActivity.java b/src/com/android/camera/PermissionsActivity.java
index aca4778..895d316 100644
--- a/src/com/android/camera/PermissionsActivity.java
+++ b/src/com/android/camera/PermissionsActivity.java
@@ -43,13 +43,9 @@
private boolean mShouldRequestCameraPermission;
private boolean mShouldRequestMicrophonePermission;
private boolean mShouldRequestLocationPermission;
- private boolean mShouldRequestStoragePermission;
- private boolean mShouldRequestWriteStoragePermission;
private int mNumPermissionsToRequest;
private boolean mFlagHasCameraPermission;
private boolean mFlagHasMicrophonePermission;
- private boolean mFlagHasStoragePermission;
- private boolean mFlagHasWriteStoragePermission;
private SettingsManager mSettingsManager;
/**
@@ -119,22 +115,6 @@
mFlagHasMicrophonePermission = true;
}
- if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
- != PackageManager.PERMISSION_GRANTED) {
- mNumPermissionsToRequest++;
- mShouldRequestStoragePermission = true;
- } else {
- mFlagHasStoragePermission = true;
- }
-
- if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
- != PackageManager.PERMISSION_GRANTED) {
- mNumPermissionsToRequest++;
- mShouldRequestWriteStoragePermission = true;
- } else {
- mFlagHasWriteStoragePermission = true;
- }
-
if (mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
Keys.KEY_RECORD_LOCATION)
&& (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
@@ -171,16 +151,6 @@
mIndexPermissionRequestMicrophone = permissionsRequestIndex;
permissionsRequestIndex++;
}
- if (mShouldRequestStoragePermission) {
- permissionsToRequest[permissionsRequestIndex] = Manifest.permission.READ_EXTERNAL_STORAGE;
- mIndexPermissionRequestStorage = permissionsRequestIndex;
- permissionsRequestIndex++;
- }
- if (mShouldRequestWriteStoragePermission) {
- permissionsToRequest[permissionsRequestIndex] = Manifest.permission.WRITE_EXTERNAL_STORAGE;
- mIndexPermissionRequestWriteStorage = permissionsRequestIndex;
- permissionsRequestIndex++;
- }
if (mShouldRequestLocationPermission) {
permissionsToRequest[permissionsRequestIndex] = Manifest.permission.ACCESS_COARSE_LOCATION;
mIndexPermissionRequestLocation = permissionsRequestIndex;
@@ -215,23 +185,6 @@
handlePermissionsFailure();
}
}
- if (mShouldRequestStoragePermission) {
- if (grantResults.length > 0 && grantResults[mIndexPermissionRequestStorage] ==
- PackageManager.PERMISSION_GRANTED) {
- mFlagHasStoragePermission = true;
- } else {
- handlePermissionsFailure();
- }
- }
- if (mShouldRequestWriteStoragePermission) {
- if (grantResults.length > 0 && grantResults[mIndexPermissionRequestWriteStorage] ==
- PackageManager.PERMISSION_GRANTED) {
- mFlagHasWriteStoragePermission = true;
- } else {
- handlePermissionsFailure();
- }
- }
-
if (mShouldRequestLocationPermission) {
if (grantResults.length > 0 && grantResults[mIndexPermissionRequestLocation] ==
PackageManager.PERMISSION_GRANTED) {
@@ -241,8 +194,7 @@
}
}
- if (mFlagHasCameraPermission && mFlagHasMicrophonePermission &&
- mFlagHasStoragePermission && mFlagHasWriteStoragePermission) {
+ if (mFlagHasCameraPermission && mFlagHasMicrophonePermission) {
handlePermissionsSuccess();
}
}
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index f29b08e..6fb8243 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -727,7 +727,7 @@
queue.addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
- Storage.ensureOSXCompatible();
+ Storage.instance().ensureOSXCompatible();
return false;
}
});
diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java
index 842f9a4..385e465 100644
--- a/src/com/android/camera/Storage.java
+++ b/src/com/android/camera/Storage.java
@@ -18,38 +18,35 @@
import android.content.ContentResolver;
import android.content.ContentValues;
+import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.location.Location;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.provider.MediaStore.MediaColumns;
+import android.provider.MediaStore.Images.Media;
import android.util.LruCache;
import com.android.camera.data.FilmstripItemData;
import com.android.camera.debug.Log;
import com.android.camera.exif.ExifInterface;
-import com.android.camera.util.ApiHelper;
+import com.android.camera.util.AndroidContext;
import com.android.camera.util.Size;
import com.google.common.base.Optional;
import java.io.File;
-import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.HashMap;
import java.util.UUID;
-import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
public class Storage {
- public static final String DCIM =
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString();
- public static final String DIRECTORY = DCIM + "/Camera";
- public static final File DIRECTORY_FILE = new File(DIRECTORY);
+ public final String DIRECTORY;
public static final String JPEG_POSTFIX = ".jpg";
public static final String GIF_POSTFIX = ".gif";
public static final long UNAVAILABLE = -1L;
@@ -60,9 +57,9 @@
public static final String CAMERA_SESSION_SCHEME = "camera_session";
private static final Log.Tag TAG = new Log.Tag("Storage");
private static final String GOOGLE_COM = "google.com";
- private static HashMap<Uri, Uri> sSessionsToContentUris = new HashMap<>();
- private static HashMap<Uri, Uri> sContentUrisToSessions = new HashMap<>();
- private static LruCache<Uri, Bitmap> sSessionsToPlaceholderBitmap =
+ private HashMap<Uri, Uri> sSessionsToContentUris = new HashMap<>();
+ private HashMap<Uri, Uri> sContentUrisToSessions = new HashMap<>();
+ private LruCache<Uri, Bitmap> sSessionsToPlaceholderBitmap =
// 20MB cache as an upper bound for session bitmap storage
new LruCache<Uri, Bitmap>(20 * 1024 * 1024) {
@Override
@@ -70,8 +67,20 @@
return value.getByteCount();
}
};
- private static HashMap<Uri, Point> sSessionsToSizes = new HashMap<>();
- private static HashMap<Uri, Integer> sSessionsToPlaceholderVersions = new HashMap<>();
+ private HashMap<Uri, Point> sSessionsToSizes = new HashMap<>();
+ private HashMap<Uri, Integer> sSessionsToPlaceholderVersions = new HashMap<>();
+
+ private static class Singleton {
+ private static final Storage INSTANCE = new Storage(AndroidContext.instance().get());
+ }
+
+ public static Storage instance() {
+ return Singleton.INSTANCE;
+ }
+
+ private Storage(Context context) {
+ DIRECTORY = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getPath();
+ }
/**
* Save the image with default JPEG MIME type and add it to the MediaStore.
@@ -88,7 +97,7 @@
* @param height The height of the media file after the orientation is
* applied.
*/
- public static Uri addImage(ContentResolver resolver, String title, long date,
+ public Uri addImage(ContentResolver resolver, String title, long date,
Location location, int orientation, ExifInterface exif, byte[] jpeg, int width,
int height) throws IOException {
@@ -117,15 +126,14 @@
* @return The URI of the added image, or null if the image could not be
* added.
*/
- public static Uri addImage(ContentResolver resolver, String title, long date,
+ public Uri addImage(ContentResolver resolver, String title, long date,
Location location, int orientation, ExifInterface exif, byte[] data, int width,
int height, String mimeType) throws IOException {
- String path = generateFilepath(title, mimeType);
- long fileLength = writeFile(path, data, exif);
- if (fileLength >= 0) {
- return addImageToMediaStore(resolver, title, date, location, orientation, fileLength,
- path, width, height, mimeType);
+ if (data.length >= 0) {
+ Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+ return addImageToMediaStore(resolver, title, date, location, orientation, data.length,
+ bitmap, width, height, mimeType, exif);
}
return null;
}
@@ -138,25 +146,26 @@
* @param date The date for the media file.
* @param location The location of the media file.
* @param orientation The orientation of the media file.
+ * @param bitmap The bitmap representation of the media to store.
* @param width The width of the media file after the orientation is
* applied.
* @param height The height of the media file after the orientation is
* applied.
* @param mimeType The MIME type of the data.
+ * @param exif The exif of the image.
* @return The content URI of the inserted media file or null, if the image
* could not be added.
*/
- public static Uri addImageToMediaStore(ContentResolver resolver, String title, long date,
- Location location, int orientation, long jpegLength, String path, int width, int height,
- String mimeType) {
+ public Uri addImageToMediaStore(ContentResolver resolver, String title, long date,
+ Location location, int orientation, long jpegLength, Bitmap bitmap, int width,
+ int height, String mimeType, ExifInterface exif) {
// Insert into MediaStore.
- ContentValues values =
- getContentValuesForData(title, date, location, orientation, jpegLength, path, width,
- height, mimeType);
+ ContentValues values = getContentValuesForData(title, date, location, mimeType, true);
Uri uri = null;
try {
- uri = resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values);
+ uri = resolver.insert(Media.EXTERNAL_CONTENT_URI, values);
+ writeBitmap(uri, exif, bitmap, resolver);
} catch (Throwable th) {
// This can happen when the external volume is already mounted, but
// MediaScanner has not notify MediaProvider to add that volume.
@@ -164,34 +173,44 @@
// insert it into MediaProvider. The only problem is that the user
// cannot click the thumbnail to review the picture.
Log.e(TAG, "Failed to write MediaStore" + th);
+ if (uri != null) {
+ resolver.delete(uri, null, null);
+ }
}
return uri;
}
- // Get a ContentValues object for the given photo data
- public static ContentValues getContentValuesForData(String title,
- long date, Location location, int orientation, long jpegLength,
- String path, int width, int height, String mimeType) {
+ private void writeBitmap(Uri uri, ExifInterface exif, Bitmap bitmap, ContentResolver resolver)
+ throws FileNotFoundException, IOException {
+ OutputStream os = resolver.openOutputStream(uri);
+ if (exif != null) {
+ exif.writeExif(bitmap, os);
+ } else {
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 90, os);
+ }
- File file = new File(path);
- long dateModifiedSeconds = TimeUnit.MILLISECONDS.toSeconds(file.lastModified());
+ ContentValues publishValues = new ContentValues();
+ publishValues.put(Media.IS_PENDING, 0);
+ resolver.update(uri, publishValues, null, null);
+ }
+
+ // Get a ContentValues object for the given photo data
+ public ContentValues getContentValuesForData(String title, long date, Location location,
+ String mimeType, boolean isPending) {
ContentValues values = new ContentValues(11);
- values.put(ImageColumns.TITLE, title);
- values.put(ImageColumns.DISPLAY_NAME, title + JPEG_POSTFIX);
- values.put(ImageColumns.DATE_TAKEN, date);
- values.put(ImageColumns.MIME_TYPE, mimeType);
- values.put(ImageColumns.DATE_MODIFIED, dateModifiedSeconds);
- // Clockwise rotation in degrees. 0, 90, 180, or 270.
- values.put(ImageColumns.ORIENTATION, orientation);
- values.put(ImageColumns.DATA, path);
- values.put(ImageColumns.SIZE, jpegLength);
+ values.put(Media.TITLE, title);
+ values.put(Media.DISPLAY_NAME, title + JPEG_POSTFIX);
+ values.put(Media.DATE_TAKEN, date);
+ values.put(Media.MIME_TYPE, mimeType);
- setImageSize(values, width, height);
+ if (isPending) {
+ values.put(Media.IS_PENDING, 1);
+ }
if (location != null) {
- values.put(ImageColumns.LATITUDE, location.getLatitude());
- values.put(ImageColumns.LONGITUDE, location.getLongitude());
+ values.put(Media.LATITUDE, location.getLatitude());
+ values.put(Media.LONGITUDE, location.getLongitude());
}
return values;
}
@@ -202,7 +221,7 @@
* @param placeholder the placeholder image
* @return A new URI used to reference this placeholder
*/
- public static Uri addPlaceholder(Bitmap placeholder) {
+ public Uri addPlaceholder(Bitmap placeholder) {
Uri uri = generateUniquePlaceholderUri();
replacePlaceholder(uri, placeholder);
return uri;
@@ -211,7 +230,7 @@
/**
* Remove a placeholder from in memory storage.
*/
- public static void removePlaceholder(Uri uri) {
+ public void removePlaceholder(Uri uri) {
sSessionsToSizes.remove(uri);
sSessionsToPlaceholderBitmap.remove(uri);
sSessionsToPlaceholderVersions.remove(uri);
@@ -225,7 +244,7 @@
* @param placeholder the placeholder image
* @return A URI used to reference this placeholder
*/
- public static void replacePlaceholder(Uri uri, Bitmap placeholder) {
+ public void replacePlaceholder(Uri uri, Bitmap placeholder) {
Log.v(TAG, "session bitmap cache size: " + sSessionsToPlaceholderBitmap.size());
Point size = new Point(placeholder.getWidth(), placeholder.getHeight());
sSessionsToSizes.put(uri, size);
@@ -241,7 +260,7 @@
* @return A new URI used to reference this placeholder
*/
@Nonnull
- public static Uri addEmptyPlaceholder(@Nonnull Size size) {
+ public Uri addEmptyPlaceholder(@Nonnull Size size) {
Uri uri = generateUniquePlaceholderUri();
sSessionsToSizes.put(uri, new Point(size.getWidth(), size.getHeight()));
sSessionsToPlaceholderBitmap.remove(uri);
@@ -266,55 +285,21 @@
* @param mimeType of the image
* @return The content uri of the newly inserted or replaced item.
*/
- public static Uri updateImage(Uri imageUri, ContentResolver resolver, String title, long date,
+ public Uri updateImage(Uri imageUri, ContentResolver resolver, String title, long date,
Location location, int orientation, ExifInterface exif,
byte[] jpeg, int width, int height, String mimeType) throws IOException {
- String path = generateFilepath(title, mimeType);
- writeFile(path, jpeg, exif);
- return updateImage(imageUri, resolver, title, date, location, orientation, jpeg.length, path,
- width, height, mimeType);
+ Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length);
+ return updateImage(imageUri, resolver, title, date, location, orientation, jpeg.length,
+ bitmap, width, height, mimeType, exif);
}
- private static Uri generateUniquePlaceholderUri() {
+ private Uri generateUniquePlaceholderUri() {
Uri.Builder builder = new Uri.Builder();
String uuid = UUID.randomUUID().toString();
builder.scheme(CAMERA_SESSION_SCHEME).authority(GOOGLE_COM).appendPath(uuid);
return builder.build();
}
- private static void setImageSize(ContentValues values, int width, int height) {
- // The two fields are available since ICS but got published in JB
- if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
- values.put(MediaColumns.WIDTH, width);
- values.put(MediaColumns.HEIGHT, height);
- }
- }
-
- /**
- * Writes the JPEG data to a file. If there's EXIF info, the EXIF header
- * will be added.
- *
- * @param path The path to the target file.
- * @param jpeg The JPEG data.
- * @param exif The EXIF info. Can be {@code null}.
- *
- * @return The size of the file. -1 if failed.
- */
- public static long writeFile(String path, byte[] jpeg, ExifInterface exif) throws IOException {
- if (!createDirectoryIfNeeded(path)) {
- Log.e(TAG, "Failed to create parent directory for file: " + path);
- return -1;
- }
- if (exif != null) {
- exif.writeExif(jpeg, path);
- File f = new File(path);
- return f.length();
- } else {
- return writeFile(path, jpeg);
- }
-// return -1;
- }
-
/**
* Renames a file.
*
@@ -325,7 +310,7 @@
* @param newFilePath the new path of the file
* @return false if rename was not successful
*/
- public static boolean renameFile(File inputPath, File newFilePath) {
+ public boolean renameFile(File inputPath, File newFilePath) {
if (newFilePath.exists()) {
Log.e(TAG, "File path already exists: " + newFilePath.getAbsolutePath());
return false;
@@ -343,32 +328,6 @@
}
/**
- * Writes the data to a file.
- *
- * @param path The path to the target file.
- * @param data The data to save.
- *
- * @return The size of the file. -1 if failed.
- */
- private static long writeFile(String path, byte[] data) {
- FileOutputStream out = null;
- try {
- out = new FileOutputStream(path);
- out.write(data);
- return data.length;
- } catch (Exception e) {
- Log.e(TAG, "Failed to write data", e);
- } finally {
- try {
- out.close();
- } catch (Exception e) {
- Log.e(TAG, "Failed to close file after write", e);
- }
- }
- return -1;
- }
-
- /**
* Given a file path, makes sure the directory it's in exists, and if not
* that it is created.
*
@@ -377,7 +336,7 @@
* cannot be written to since the parent directory could not be
* created.
*/
- private static boolean createDirectoryIfNeeded(String filePath) {
+ private boolean createDirectoryIfNeeded(String filePath) {
File parentFile = new File(filePath).getParentFile();
// If the parent exists, return 'true' if it is a directory. If it's a
@@ -392,34 +351,30 @@
}
/** Updates the image values in MediaStore. */
- private static Uri updateImage(Uri imageUri, ContentResolver resolver, String title,
+ private Uri updateImage(Uri imageUri, ContentResolver resolver, String title,
long date, Location location, int orientation, int jpegLength,
- String path, int width, int height, String mimeType) {
-
- ContentValues values =
- getContentValuesForData(title, date, location, orientation, jpegLength, path,
- width, height, mimeType);
-
+ Bitmap bitmap, int width, int height, String mimeType, ExifInterface exif) {
Uri resultUri = imageUri;
- if (Storage.isSessionUri(imageUri)) {
+ if (isSessionUri(imageUri)) {
// If this is a session uri, then we need to add the image
resultUri = addImageToMediaStore(resolver, title, date, location, orientation,
- jpegLength, path, width, height, mimeType);
+ jpegLength, bitmap, width, height, mimeType, exif);
sSessionsToContentUris.put(imageUri, resultUri);
sContentUrisToSessions.put(resultUri, imageUri);
} else {
// Update the MediaStore
+ ContentValues values = getContentValuesForData(title, date, location, mimeType, false);
resolver.update(imageUri, values, null, null);
}
return resultUri;
}
- private static String generateFilepath(String title, String mimeType) {
+ private String generateFilepath(String title, String mimeType) {
return generateFilepath(DIRECTORY, title, mimeType);
}
- public static String generateFilepath(String directory, String title, String mimeType) {
+ public String generateFilepath(String directory, String title, String mimeType) {
String extension = null;
if (FilmstripItemData.MIME_TYPE_JPEG.equals(mimeType)) {
extension = JPEG_POSTFIX;
@@ -437,7 +392,7 @@
* @param uri the session uri to look up
* @return The bitmap or null
*/
- public static Optional<Bitmap> getPlaceholderForSession(Uri uri) {
+ public Optional<Bitmap> getPlaceholderForSession(Uri uri) {
return Optional.fromNullable(sSessionsToPlaceholderBitmap.get(uri));
}
@@ -445,7 +400,7 @@
* @return Whether a placeholder size for the session with the given URI
* exists.
*/
- public static boolean containsPlaceholderSize(Uri uri) {
+ public boolean containsPlaceholderSize(Uri uri) {
return sSessionsToSizes.containsKey(uri);
}
@@ -455,7 +410,7 @@
* @param uri the session uri to look up
* @return The size
*/
- public static Point getSizeForSession(Uri uri) {
+ public Point getSizeForSession(Uri uri) {
return sSessionsToSizes.get(uri);
}
@@ -465,7 +420,7 @@
* @param uri the uri of the session that was replaced
* @return The uri of the new media item, if it exists, or null.
*/
- public static Uri getContentUriForSessionUri(Uri uri) {
+ public Uri getContentUriForSessionUri(Uri uri) {
return sSessionsToContentUris.get(uri);
}
@@ -475,7 +430,7 @@
* @param contentUri the uri of the media store content
* @return The session uri of the original session, if it exists, or null.
*/
- public static Uri getSessionUriFromContentUri(Uri contentUri) {
+ public Uri getSessionUriFromContentUri(Uri contentUri) {
return sContentUrisToSessions.get(contentUri);
}
@@ -485,11 +440,11 @@
* @param uri the uri to check
* @return true if it is a session uri.
*/
- public static boolean isSessionUri(Uri uri) {
+ public boolean isSessionUri(Uri uri) {
return uri.getScheme().equals(CAMERA_SESSION_SCHEME);
}
- public static long getAvailableSpace() {
+ public long getAvailableSpace() {
String state = Environment.getExternalStorageState();
Log.d(TAG, "External storage state=" + state);
if (Environment.MEDIA_CHECKING.equals(state)) {
@@ -502,6 +457,7 @@
File dir = new File(DIRECTORY);
dir.mkdirs();
if (!dir.isDirectory() || !dir.canWrite()) {
+ Log.d(TAG, DIRECTORY + " mounted, but isn't directory or cannot write");
return UNAVAILABLE;
}
@@ -518,8 +474,8 @@
* OSX requires plugged-in USB storage to have path /DCIM/NNNAAAAA to be
* imported. This is a temporary fix for bug#1655552.
*/
- public static void ensureOSXCompatible() {
- File nnnAAAAA = new File(DCIM, "100ANDRO");
+ public void ensureOSXCompatible() {
+ File nnnAAAAA = new File(DIRECTORY, "100ANDRO");
if (!(nnnAAAAA.exists() || nnnAAAAA.mkdirs())) {
Log.e(TAG, "Failed to create " + nnnAAAAA.getPath());
}
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index e8222f6..856781b 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -1223,7 +1223,7 @@
// Used when emailing.
String filename = title + convertOutputFormatToFileExt(outputFileFormat);
String mime = convertOutputFormatToMimeType(outputFileFormat);
- String path = Storage.DIRECTORY + '/' + filename;
+ String path = Storage.instance().DIRECTORY + '/' + filename;
String tmpPath = path + ".tmp";
mCurrentVideoValues = new ContentValues(9);
mCurrentVideoValues.put(Video.Media.TITLE, title);
diff --git a/src/com/android/camera/app/CameraServicesImpl.java b/src/com/android/camera/app/CameraServicesImpl.java
index a1a2e86..804ba15 100644
--- a/src/com/android/camera/app/CameraServicesImpl.java
+++ b/src/com/android/camera/app/CameraServicesImpl.java
@@ -65,7 +65,7 @@
PlaceholderManager mPlaceHolderManager = new PlaceholderManager(context);
SessionStorageManager mSessionStorageManager = SessionStorageManagerImpl.create(context);
- StackSaverFactory mStackSaverFactory = new StackSaverFactory(Storage.DIRECTORY,
+ StackSaverFactory mStackSaverFactory = new StackSaverFactory(Storage.instance().DIRECTORY,
context.getContentResolver());
CaptureSessionFactory captureSessionFactory = new CaptureSessionFactoryImpl(
mMediaSaver, mPlaceHolderManager, mSessionStorageManager, mStackSaverFactory);
diff --git a/src/com/android/camera/data/CameraFilmstripDataAdapter.java b/src/com/android/camera/data/CameraFilmstripDataAdapter.java
index e4cf978..a42f6c5 100644
--- a/src/com/android/camera/data/CameraFilmstripDataAdapter.java
+++ b/src/com/android/camera/data/CameraFilmstripDataAdapter.java
@@ -350,7 +350,7 @@
// We may add data that is already present, but if we do, it will be deduped in addOrUpdate.
// addOrUpdate does not dedupe session items, so we ignore them here
for (FilmstripItem filmstripItem : newPhotoData) {
- Uri sessionUri = Storage.getSessionUriFromContentUri(
+ Uri sessionUri = Storage.instance().getSessionUriFromContentUri(
filmstripItem.getData().getUri());
if (sessionUri == null) {
addOrUpdate(filmstripItem);
diff --git a/src/com/android/camera/data/FilmstripContentQueries.java b/src/com/android/camera/data/FilmstripContentQueries.java
index a3c273c..2aba065 100644
--- a/src/com/android/camera/data/FilmstripContentQueries.java
+++ b/src/com/android/camera/data/FilmstripContentQueries.java
@@ -32,7 +32,6 @@
*/
public class FilmstripContentQueries {
private static final Log.Tag TAG = new Log.Tag("LocalDataQuery");
- private static final String CAMERA_PATH = Storage.DIRECTORY + "%";
private static final String SELECT_BY_PATH = MediaStore.MediaColumns.DATA + " LIKE ?";
public interface CursorToFilmstripItemFactory<I extends FilmstripItem> {
@@ -62,7 +61,8 @@
Uri contentUri, String[] projection, long minimumId, String orderBy,
CursorToFilmstripItemFactory<I> factory) {
String selection = SELECT_BY_PATH + " AND " + MediaStore.MediaColumns._ID + " > ?";
- String[] selectionArgs = new String[] { CAMERA_PATH, Long.toString(minimumId) };
+ String cameraPath = Storage.instance().DIRECTORY + "%";
+ String[] selectionArgs = new String[] { cameraPath, Long.toString(minimumId) };
Cursor cursor = contentResolver.query(contentUri, projection,
selection, selectionArgs, orderBy);
@@ -82,4 +82,4 @@
}
return result;
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/camera/data/FilmstripItemBase.java b/src/com/android/camera/data/FilmstripItemBase.java
index f225a07..e3c589f 100644
--- a/src/com/android/camera/data/FilmstripItemBase.java
+++ b/src/com/android/camera/data/FilmstripItemBase.java
@@ -146,7 +146,7 @@
}
// Check if this is a 'Camera' sub-directory.
- String cameraPathStr = Storage.DIRECTORY_FILE.getAbsolutePath();
+ String cameraPathStr = Storage.instance().DIRECTORY;
String fileParentPathStr = directory.getParentFile().getAbsolutePath();
Log.d(TAG, "CameraPathStr: " + cameraPathStr + " fileParentPathStr: " + fileParentPathStr);
diff --git a/src/com/android/camera/data/PhotoItem.java b/src/com/android/camera/data/PhotoItem.java
index 032c447..8215f73 100644
--- a/src/com/android/camera/data/PhotoItem.java
+++ b/src/com/android/camera/data/PhotoItem.java
@@ -222,7 +222,7 @@
final Bitmap bitmap;
if (getAttributes().isRendering()) {
- return Storage.getPlaceholderForSession(data.getUri());
+ return Storage.instance().getPlaceholderForSession(data.getUri());
} else {
FileInputStream stream;
diff --git a/src/com/android/camera/data/SessionItem.java b/src/com/android/camera/data/SessionItem.java
index e36931b..f059bdd 100644
--- a/src/com/android/camera/data/SessionItem.java
+++ b/src/com/android/camera/data/SessionItem.java
@@ -52,7 +52,7 @@
* @return If the session was found, a new SessionItem is returned.
*/
public static Optional<SessionItem> create(Context context, Uri uri) {
- if (!Storage.containsPlaceholderSize(uri)) {
+ if (!Storage.instance().containsPlaceholderSize(uri)) {
return Optional.absent();
}
Size dimension = getSessionSize(uri);
@@ -82,7 +82,7 @@
}
private static Size getSessionSize(Uri uri) {
- Point size = Storage.getSizeForSession(uri);
+ Point size = Storage.instance().getSizeForSession(uri);
if (size == null) {
return null;
}
@@ -101,7 +101,7 @@
imageView.setTag(R.id.mediadata_tag_viewtype, getItemViewType().ordinal());
}
- Optional<Bitmap> placeholder = Storage.getPlaceholderForSession(mData.getUri());
+ Optional<Bitmap> placeholder = Storage.instance().getPlaceholderForSession(mData.getUri());
if (placeholder.isPresent()) {
imageView.setImageBitmap(placeholder.get());
} else {
@@ -171,7 +171,7 @@
@Override
public Optional<Bitmap> generateThumbnail(int boundingWidthPx, int boundingHeightPx) {
- return Storage.getPlaceholderForSession(mUri);
+ return Storage.instance().getPlaceholderForSession(mUri);
}
@Override
diff --git a/src/com/android/camera/one/v2/OneCameraImpl.java b/src/com/android/camera/one/v2/OneCameraImpl.java
index c3b8ecb..8f0ffef 100644
--- a/src/com/android/camera/one/v2/OneCameraImpl.java
+++ b/src/com/android/camera/one/v2/OneCameraImpl.java
@@ -162,7 +162,7 @@
}
/** Directory to store raw DNG files in. */
- private static final File RAW_DIRECTORY = new File(Storage.DIRECTORY, "DNG");
+ private final File mRawDirectory;
/** Current CONTROL_AF_MODE request to Camera2 API. */
private int mControlAFMode = CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
@@ -322,6 +322,7 @@
mLensRange = LensRangeCalculator.getDiopterToRatioCalculator(characteristics);
mDirectionProvider = new CameraDirectionProvider(characteristics);
mFullSizeAspectRatio = calculateFullSizeAspectRatio(characteristics);
+ mRawDirectory = new File(Storage.instance().DIRECTORY, "DNG");
// Override pictureSize for RAW (our picture size settings don't include
// RAW, which typically only supports one size (sensor size). This also
@@ -766,12 +767,12 @@
// TODO: If we make this a real feature we should probably put the DNGs
// into the Camera directly.
if (sCaptureImageFormat == ImageFormat.RAW_SENSOR) {
- if (!RAW_DIRECTORY.exists()) {
- if (!RAW_DIRECTORY.mkdirs()) {
+ if (!mRawDirectory.exists()) {
+ if (!mRawDirectory.mkdirs()) {
throw new RuntimeException("Could not create RAW directory.");
}
}
- File dngFile = new File(RAW_DIRECTORY, capture.session.getTitle() + ".dng");
+ File dngFile = new File(mRawDirectory, capture.session.getTitle() + ".dng");
writeDngBytesAndClose(capture.image, capture.totalCaptureResult,
mCharacteristics, dngFile);
} else {
diff --git a/src/com/android/camera/session/PlaceholderManager.java b/src/com/android/camera/session/PlaceholderManager.java
index b54405f..a474250 100644
--- a/src/com/android/camera/session/PlaceholderManager.java
+++ b/src/com/android/camera/session/PlaceholderManager.java
@@ -69,7 +69,7 @@
* @return A session instance representing the new placeholder.
*/
public Placeholder insertEmptyPlaceholder(String title, Size size, long timestamp) {
- Uri uri = Storage.addEmptyPlaceholder(size);
+ Uri uri = Storage.instance().addEmptyPlaceholder(size);
return new Placeholder(title, uri, timestamp);
}
@@ -91,7 +91,7 @@
throw new IllegalArgumentException("Image had bad height/width");
}
- Uri uri = Storage.addPlaceholder(placeholder);
+ Uri uri = Storage.instance().addPlaceholder(placeholder);
if (uri == null) {
return null;
}
@@ -134,7 +134,7 @@
*/
public Uri finishPlaceholder(Placeholder placeholder, Location location, int orientation,
ExifInterface exif, byte[] jpeg, int width, int height, String mimeType) throws IOException {
- Uri resultUri = Storage.updateImage(placeholder.outputUri, mContext.getContentResolver(),
+ Uri resultUri = Storage.instance().updateImage(placeholder.outputUri, mContext.getContentResolver(),
placeholder.outputTitle, placeholder.time, location, orientation, exif, jpeg, width,
height, mimeType);
CameraUtil.broadcastNewPicture(mContext, resultUri);
@@ -148,7 +148,7 @@
* @param placeholder the placeholder bitmap
*/
public void replacePlaceholder(Placeholder session, Bitmap placeholder) {
- Storage.replacePlaceholder(session.outputUri, placeholder);
+ Storage.instance().replacePlaceholder(session.outputUri, placeholder);
CameraUtil.broadcastNewPicture(mContext, session.outputUri);
}
@@ -158,7 +158,7 @@
* @param placeholder the session for which to retrieve bitmap placeholder
*/
public Optional<Bitmap> getPlaceholder(Placeholder placeholder) {
- return Storage.getPlaceholderForSession(placeholder.outputUri);
+ return Storage.instance().getPlaceholderForSession(placeholder.outputUri);
}
@@ -168,7 +168,7 @@
* @param placeholder the session for which to remove the bitmap placeholder.
*/
public void removePlaceholder(Placeholder placeholder) {
- Storage.removePlaceholder(placeholder.outputUri);
+ Storage.instance().removePlaceholder(placeholder.outputUri);
}
/**
diff --git a/src/com/android/camera/session/StackSaverImpl.java b/src/com/android/camera/session/StackSaverImpl.java
index f5b1968..81870ae 100644
--- a/src/com/android/camera/session/StackSaverImpl.java
+++ b/src/com/android/camera/session/StackSaverImpl.java
@@ -17,6 +17,8 @@
package com.android.camera.session;
import android.content.ContentResolver;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.location.Location;
import android.net.Uri;
@@ -62,16 +64,18 @@
public Uri saveStackedImage(File inputImagePath, String title, int width, int height,
int imageOrientation, long captureTimeEpoch, String mimeType) {
String filePath =
- Storage.generateFilepath(mStackDirectory.getAbsolutePath(), title, mimeType);
+ Storage.instance().generateFilepath(mStackDirectory.getAbsolutePath(),
+ title, mimeType);
Log.d(TAG, "Saving using stack image saver: " + filePath);
File outputImagePath = new File(filePath);
+ Bitmap bitmap = BitmapFactory.decodeFile(filePath);
- if (Storage.renameFile(inputImagePath, outputImagePath)) {
+ if (Storage.instance().renameFile(inputImagePath, outputImagePath)) {
long fileLength = outputImagePath.length();
if (fileLength > 0) {
- return Storage.addImageToMediaStore(mContentResolver, title, captureTimeEpoch,
- mGpsLocation, imageOrientation, fileLength, filePath, width, height,
- mimeType);
+ return Storage.instance().addImageToMediaStore(mContentResolver, title,
+ captureTimeEpoch, mGpsLocation, imageOrientation, fileLength, bitmap,
+ width, height, mimeType, null);
}
}