OSDN Git Service

Make temp session directory creation more robust and efficient.
authorSascha Haeberling <haeberling@google.com>
Thu, 9 Oct 2014 18:55:23 +0000 (11:55 -0700)
committerSascha Haeberling <haeberling@google.com>
Sat, 11 Oct 2014 00:00:25 +0000 (17:00 -0700)
Also rename some methods for clarity.

Change-Id: Ic6d3e7902ae5396f33231f1471df9eae89234132

src/com/android/camera/session/CaptureSession.java
src/com/android/camera/session/CaptureSessionManagerImpl.java
src/com/android/camera/session/SessionStorageManagerImpl.java

index 0e3baea..7b3c7f0 100644 (file)
@@ -131,10 +131,11 @@ public interface CaptureSession {
     public void finishWithFailure(CharSequence reason);
 
     /**
-     * Returns the path to the final output of this session. This is only
-     * available after startSession has been called.
+     * Returns the path to where the final output of this session should be
+     * stored. This is only available after startSession has been called and
+     * will become unavailable after finish() was called.
      */
-    public String getPath();
+    public String getTempOutputPath();
 
     /**
      * Returns the URI to the final output of this session. This is only available
@@ -151,11 +152,11 @@ public interface CaptureSession {
     public Uri getContentUri();
 
     /**
-     * Whether this session already has a path. This is the case once it has
-     * been started. False is returned, if the session has not been started yet
-     * and no path is available.
+     * Whether this session has been started. Once it has been started it will
+     * have a valid path and can be processed. False is returned, if the session
+     * has not been started yet and no path is available.
      */
-    public boolean hasPath();
+    public boolean isStarted();
 
     /**
      * Updates the preview from a file. {@link #onPreviewAvailable()} will be
index 14d6ffc..84bd693 100644 (file)
@@ -51,7 +51,7 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
         private Uri mUri;
         /** The title of the item being processed. */
         private final String mTitle;
-        /** The location this session was created at. Used for media store.*/
+        /** The location this session was created at. Used for media store. */
         private Location mLocation;
         /** The current progress of this session in percent. */
         private int mProgressPercent = 0;
@@ -65,18 +65,25 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
         private final HashSet<ProgressListener> mProgressListeners =
                 new HashSet<ProgressListener>();
         private final long mSessionStartMillis;
+        /**
+         * The path that can be used to write the final JPEG output temporarily,
+         * before it is copied to the final location.
+         */
+        private final String mTempOutputPath;
 
         /**
          * Creates a new {@link CaptureSession}.
          *
          * @param title the title of this session.
-         * @param sessionStartMillis the timestamp of this capture session (since epoch).
+         * @param sessionStartMillis the timestamp of this capture session
+         *            (since epoch).
          * @param location the location of this session, used for media store.
          */
         private CaptureSessionImpl(String title, long sessionStartMillis, Location location) {
             mTitle = title;
             mSessionStartMillis = sessionStartMillis;
             mLocation = location;
+            mTempOutputPath = createTempOutputPath(mTitle);
         }
 
         @Override
@@ -151,7 +158,7 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
 
         @Override
         public synchronized void cancel() {
-            if (mUri != null) {
+            if (isStarted()) {
                 removeSession(mUri.toString());
             }
         }
@@ -186,14 +193,12 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
                         "Cannot call finish without calling startSession first.");
             }
 
-            final String path = this.getPath();
-
             AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() {
                 @Override
                 public void run() {
                     byte[] jpegDataTemp;
                     try {
-                        jpegDataTemp = FileUtil.readFileToByteArray(new File(path));
+                        jpegDataTemp = FileUtil.readFileToByteArray(new File(mTempOutputPath));
                     } catch (IOException e) {
                         return;
                     }
@@ -221,29 +226,53 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
         }
 
         @Override
-        public String getPath() {
-            if (mUri == null) {
+        public String getTempOutputPath() {
+            if (!isStarted()) {
                 throw new IllegalStateException("Cannot retrieve URI of not started session.");
             }
+            return mTempOutputPath;
+        }
 
+        /**
+         * Initializes the directories for storing the final output temporarily
+         * before it is copied to the final location after calling
+         * {@link #finish()}.
+         * <p>
+         * This method will make sure the directories and file exists and is
+         * writeable, otherwise it will throw an exception.
+         *
+         * @param title the title of this session. Will be used to create a
+         *            unique sub-directory.
+         * @return The path to a JPEG file which can be used to write the final
+         *         output to.
+         */
+        private String createTempOutputPath(String title) {
             File tempDirectory = null;
             try {
                 tempDirectory = new File(
-                        getSessionDirectory(TEMP_SESSIONS), mTitle);
+                        getSessionDirectory(TEMP_SESSIONS), title);
             } catch (IOException e) {
                 Log.e(TAG, "Could not get temp session directory", e);
                 throw new RuntimeException("Could not get temp session directory", e);
             }
-            tempDirectory.mkdirs();
-            File tempFile = new File(tempDirectory, mTitle  + ".jpg");
+            if (!tempDirectory.mkdirs()) {
+                throw new IllegalStateException("Could not create output data directory.");
+            }
+            File tempFile = new File(tempDirectory, mTitle + ".jpg");
             try {
                 if (!tempFile.exists()) {
-                    tempFile.createNewFile();
+                    if (!tempFile.createNewFile()) {
+                        throw new IllegalStateException("Could not create output data file.");
+                    }
                 }
             } catch (IOException e) {
                 Log.e(TAG, "Could not create temp session file", e);
                 throw new RuntimeException("Could not create temp session file", e);
             }
+
+            if (!tempFile.canWrite()) {
+                throw new RuntimeException("Temporary output file is not writeable.");
+            }
             return tempFile.getPath();
         }
 
@@ -258,7 +287,7 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
         }
 
         @Override
-        public boolean hasPath() {
+        public boolean isStarted() {
             return mUri != null;
         }
 
@@ -269,9 +298,7 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
 
         @Override
         public void updatePreview(String previewPath) {
-
-            final String path = this.getPath();
-
+            final String path = this.getTempOutputPath();
             AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() {
                 @Override
                 public void run() {
@@ -289,7 +316,8 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
                     int width = options.outWidth;
                     int height = options.outHeight;
 
-                    mPlaceholderManager.replacePlaceholder(mPlaceHolderSession, jpegData, width, height);
+                    mPlaceholderManager.replacePlaceholder(mPlaceHolderSession, jpegData, width,
+                            height);
                     onPreviewAvailable();
                 }
             });
@@ -372,14 +400,14 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
 
     @Override
     public void putSession(Uri sessionUri, CaptureSession session) {
-        synchronized (mSessions)  {
+        synchronized (mSessions) {
             mSessions.put(sessionUri.toString(), session);
         }
     }
 
     @Override
     public CaptureSession getSession(Uri sessionUri) {
-        synchronized (mSessions)  {
+        synchronized (mSessions) {
             return mSessions.get(sessionUri.toString());
         }
     }
@@ -408,7 +436,7 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
 
     @Override
     public File getSessionDirectory(String subDirectory) throws IOException {
-      return mSessionStorageManager.getSessionDirectory(subDirectory);
+        return mSessionStorageManager.getSessionDirectory(subDirectory);
     }
 
     private void removeSession(String sessionUri) {
@@ -486,8 +514,8 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
     }
 
     /**
-     * Notifies all task listeners that the task with the given URI has
-     * changed its progress message.
+     * Notifies all task listeners that the task with the given URI has changed
+     * its progress message.
      */
     private void notifyTaskProgressText(final Uri uri, final CharSequence message) {
         mMainHandler.post(new Runnable() {
index d863830..ea7a907 100644 (file)
@@ -98,6 +98,7 @@ public class SessionStorageManagerImpl implements SessionStorageManager {
 
         final long nowInMillis = System.currentTimeMillis();
         for (File sessionDir : sessionDirs) {
+            Log.v(TAG, "Check for potential clean-up: " + sessionDir.getAbsolutePath());
             if (sessionDir.lastModified() < (nowInMillis - MAX_SESSION_AGE_MILLIS)) {
                 if (!FileUtil.deleteDirectoryRecursively(sessionDir)) {
                     Log.w(TAG, "Could not clean up " + sessionDir.getAbsolutePath());