Remove files actually.

Change-Id: Ideba2dfff0678f1049bf2bdc93cee98bbb0e589e
diff --git a/src/com/android/camera/NewCameraActivity.java b/src/com/android/camera/NewCameraActivity.java
index fd2056f..8985f7f 100644
--- a/src/com/android/camera/NewCameraActivity.java
+++ b/src/com/android/camera/NewCameraActivity.java
@@ -28,6 +28,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
 import android.provider.Settings;
 import android.view.LayoutInflater;
@@ -79,6 +80,7 @@
     private boolean mSecureCamera;
     private int mLastRawOrientation;
     private MyOrientationEventListener mOrientationListener;
+    private Handler mMainHandler;
     private class MyOrientationEventListener
         extends OrientationEventListener {
         public MyOrientationEventListener(Context context) {
@@ -107,6 +109,34 @@
                 mMediaSaveService = null;
             }};
 
+    private FilmStripView.Listener mFilmStripListener = new FilmStripView.Listener() {
+            @Override
+            public void onDataPromoted(int dataID) {
+                removeData(dataID);
+            }
+
+            @Override
+            public void onDataDemoted(int dataID) {
+                removeData(dataID);
+            }
+
+            @Override
+            public void onDataFullScreenChange(int dataID, boolean full) {
+            }
+
+            @Override
+            public void onSwitchMode(boolean toCamera) {
+                mCurrentModule.onSwitchMode(toCamera);
+            }
+        };
+
+    private Runnable mDeletionRunnable = new Runnable() {
+            @Override
+            public void run() {
+                mDataAdapter.executeDeletion(NewCameraActivity.this);
+            }
+        };
+
     public MediaSaveService getMediaSaveService() {
         return mMediaSaveService;
     }
@@ -126,6 +156,12 @@
         }
     }
 
+    private void removeData(int dataID) {
+        mDataAdapter.removeData(NewCameraActivity.this, dataID);
+        mMainHandler.removeCallbacks(mDeletionRunnable);
+        mMainHandler.postDelayed(mDeletionRunnable, 3000);
+    }
+
     private void bindMediaSaveService() {
         Intent intent = new Intent(this, MediaSaveService.class);
         startService(intent);  // start service before binding it so the
@@ -179,29 +215,11 @@
         mDataAdapter.setCameraPreviewInfo(rootLayout,
                 FilmStripView.ImageData.SIZE_FULL, FilmStripView.ImageData.SIZE_FULL);
         mFilmStripView.setDataAdapter(mDataAdapter);
-        mFilmStripView.setListener(new FilmStripView.Listener() {
-            @Override
-            public void onDataPromoted(int dataID) {
-                mDataAdapter.removeData(dataID);
-            }
-
-            @Override
-            public void onDataDemoted(int dataID) {
-                mDataAdapter.removeData(dataID);
-            }
-
-            @Override
-            public void onDataFullScreenChange(int dataID, boolean full) {
-            }
-
-            @Override
-            public void onSwitchMode(boolean toCamera) {
-                mCurrentModule.onSwitchMode(toCamera);
-            }
-        });
+        mFilmStripView.setListener(mFilmStripListener);
         mCurrentModule = new NewPhotoModule();
         mCurrentModule.init(this, mRootView);
         mOrientationListener = new MyOrientationEventListener(this);
+        mMainHandler = new Handler(getMainLooper());
         bindMediaSaveService();
     }
 
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index 609e812..0788c1a 100644
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -57,6 +57,7 @@
     private int mSuggestedHeight = DEFAULT_DECODE_SIZE;
 
     private boolean mCameraPreviewLocked;
+    private LocalData mLocalDataToDelete;
 
     public CameraDataAdapter(Drawable placeHolder) {
         mPlaceHolder = placeHolder;
@@ -86,6 +87,10 @@
 
     @Override
     public ImageData getImageData(int id) {
+        return getData(id);
+    }
+
+    public LocalData getData(int id) {
         if (mImages == null || id >= mImages.size() || id < 0) {
             return null;
         }
@@ -133,9 +138,12 @@
         return false;
     }
 
-    public void removeData(int dataID) {
+    public void removeData(Context c, int dataID) {
         if (dataID >= mImages.size()) return;
         LocalData d = mImages.remove(dataID);
+        // Delete previously removed data first.
+        executeDeletion(c);
+        mLocalDataToDelete = d;
         mListener.onDataRemoved(dataID, d);
     }
 
@@ -177,6 +185,23 @@
         }
     }
 
+    public boolean undoDataRemoval() {
+        if (mLocalDataToDelete == null) return false;
+        LocalData d = mLocalDataToDelete;
+        mLocalDataToDelete = null;
+        insertData(d);
+        return true;
+    }
+
+    public boolean executeDeletion(Context c) {
+        if (mLocalDataToDelete == null) return false;
+
+        DeletionTask task = new DeletionTask(c);
+        task.execute(mLocalDataToDelete);
+        mLocalDataToDelete = null;
+        return true;
+    }
+
     // Update all the data but keep the camera data if already set.
     private void replaceData(List<LocalData> list) {
         boolean changed = (list != mImages);
@@ -343,6 +368,26 @@
         }
     }
 
+    private class DeletionTask extends AsyncTask<LocalData, Void, Void> {
+        Context mContext;
+
+        DeletionTask(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        protected Void doInBackground(LocalData... data) {
+            for (int i = 0; i < data.length; i++) {
+                if (!data[i].isDataActionSupported(LocalData.ACTION_DELETE)) {
+                    Log.v(TAG, "Deletion is not supported:" + data[i]);
+                    continue;
+                }
+                data[i].delete(mContext);
+            }
+            return null;
+        }
+    }
+
     private class CameraPreviewData implements LocalData {
         private int width;
         private int height;
@@ -385,7 +430,17 @@
         }
 
         @Override
-        public boolean isActionSupported(int action) {
+        public boolean isUIActionSupported(int action) {
+            return false;
+        }
+
+        @Override
+        public boolean isDataActionSupported(int action) {
+            return false;
+        }
+
+        @Override
+        public boolean delete(Context c) {
             return false;
         }
 
diff --git a/src/com/android/camera/data/LocalData.java b/src/com/android/camera/data/LocalData.java
index 704e8ed..0ccc639 100644
--- a/src/com/android/camera/data/LocalData.java
+++ b/src/com/android/camera/data/LocalData.java
@@ -16,6 +16,7 @@
 
 package com.android.camera.data;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
 import android.graphics.Bitmap;
@@ -42,19 +43,26 @@
 import com.android.camera.ui.FilmStripView;
 import com.android.gallery3d.R;
 
+import java.io.File;
 import java.util.Comparator;
 import java.util.Date;
 
 /* An abstract interface that represents the local media data. Also implements
  * Comparable interface so we can sort in DataAdapter.
  */
-public abstract interface LocalData extends FilmStripView.ImageData {
-    static final String TAG = "LocalData";
+public interface LocalData extends FilmStripView.ImageData {
+    static final String TAG = "CAM_LocalData";
 
-    abstract View getView(Context c, int width, int height, Drawable placeHolder);
-    abstract long getDateTaken();
-    abstract long getDateModified();
-    abstract String getTitle();
+    public static final int ACTION_NONE = 0;
+    public static final int ACTION_PLAY = 1;
+    public static final int ACTION_DELETE = (1 << 1);
+
+    View getView(Context c, int width, int height, Drawable placeHolder);
+    long getDateTaken();
+    long getDateModified();
+    String getTitle();
+    boolean isDataActionSupported(int action);
+    boolean delete(Context c);
 
     static class NewestFirstComparator implements Comparator<LocalData> {
 
@@ -83,6 +91,8 @@
         }
     }
 
+    // Implementations below.
+
     /*
      * A base class for all the local media files. The bitmap is loaded in background
      * thread. Subclasses should implement their own background loading thread by
@@ -128,10 +138,21 @@
         }
 
         @Override
-        public boolean isActionSupported(int action) {
+        public boolean isUIActionSupported(int action) {
             return false;
         }
 
+        @Override
+        public boolean isDataActionSupported(int action) {
+            return false;
+        }
+
+        @Override
+        public boolean delete(Context c) {
+            File f = new File(path);
+            return f.delete();
+        }
+
         protected View fillViewBackground(Context c, View v,
                 int decodeWidth, int decodeHeight, Drawable placeHolder) {
             v.setBackground(placeHolder);
@@ -225,9 +246,11 @@
             ImageColumns.HEIGHT,        // 8, int
         };
 
-        private static final int mSupportedActions =
+        private static final int mSupportedUIActions =
                 FilmStripView.ImageData.ACTION_DEMOTE
                 | FilmStripView.ImageData.ACTION_PROMOTE;
+        private static final int mSupportedDataActions =
+                LocalData.ACTION_DELETE;
 
         // 32K buffer.
         private static final byte[] DECODE_TEMP_STORAGE = new byte[32 * 1024];
@@ -284,8 +307,20 @@
         }
 
         @Override
-        public boolean isActionSupported(int action) {
-            return ((action & mSupportedActions) != 0);
+        public boolean isUIActionSupported(int action) {
+            return ((action & mSupportedUIActions) == action);
+        }
+
+        @Override
+        public boolean isDataActionSupported(int action) {
+            return ((action & mSupportedDataActions) == action);
+        }
+
+        @Override
+        public boolean delete(Context c) {
+            ContentResolver cr = c.getContentResolver();
+            cr.delete(CONTENT_URI, ImageColumns._ID + "=" + id, null);
+            return super.delete(c);
         }
 
         @Override
@@ -355,9 +390,12 @@
 
         static final Uri CONTENT_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
 
-        private static final int mSupportedActions =
+        private static final int mSupportedUIActions =
                 FilmStripView.ImageData.ACTION_DEMOTE
                 | FilmStripView.ImageData.ACTION_PROMOTE;
+        private static final int mSupportedDataActions =
+                LocalData.ACTION_DELETE
+                | LocalData.ACTION_PLAY;
 
         static final String QUERY_ORDER = VideoColumns.DATE_TAKEN + " DESC, "
                 + VideoColumns._ID + " DESC";
@@ -418,8 +456,20 @@
         }
 
         @Override
-        public boolean isActionSupported(int action) {
-            return ((action & mSupportedActions) != 0);
+        public boolean isUIActionSupported(int action) {
+            return ((action & mSupportedUIActions) == action);
+        }
+
+        @Override
+        public boolean isDataActionSupported(int action) {
+            return ((action & mSupportedDataActions) == action);
+        }
+
+        @Override
+        public boolean delete(Context c) {
+            ContentResolver cr = c.getContentResolver();
+            cr.delete(CONTENT_URI, VideoColumns._ID + "=" + id, null);
+            return super.delete(c);
         }
 
         @Override
@@ -531,7 +581,17 @@
         }
 
         @Override
-        public boolean isActionSupported(int action) {
+        public boolean isUIActionSupported(int action) {
+            return false;
+        }
+
+        @Override
+        public boolean isDataActionSupported(int action) {
+            return false;
+        }
+
+        @Override
+        public boolean delete(Context c) {
             return false;
         }
 
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index 8af30db..709d7c6 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -95,7 +95,7 @@
         public int getWidth();
         public int getHeight();
         public int getType();
-        public boolean isActionSupported(int action);
+        public boolean isUIActionSupported(int action);
 
         // prepare() should be called first time before using it.
         public void prepare();
@@ -1151,11 +1151,11 @@
                 int id = mViewInfo[i].getID();
 
                 if (mDataAdapter.getImageData(id)
-                        .isActionSupported(ImageData.ACTION_DEMOTE)
+                        .isUIActionSupported(ImageData.ACTION_DEMOTE)
                         && transY > halfH) {
                     demoteData(i, id);
                 } else if (mDataAdapter.getImageData(id)
-                        .isActionSupported(ImageData.ACTION_PROMOTE)
+                        .isUIActionSupported(ImageData.ACTION_PROMOTE)
                         && transY < -halfH) {
                     promoteData(i, id);
                 } else {
@@ -1192,10 +1192,10 @@
 
                 ImageData data = mDataAdapter.getImageData(mViewInfo[hit].getID());
                 float transY = mViewInfo[hit].getTranslationY(mScale) - dy / mScale;
-                if (!data.isActionSupported(ImageData.ACTION_DEMOTE) && transY > 0f) {
+                if (!data.isUIActionSupported(ImageData.ACTION_DEMOTE) && transY > 0f) {
                     transY = 0f;
                 }
-                if (!data.isActionSupported(ImageData.ACTION_PROMOTE) && transY < 0f) {
+                if (!data.isUIActionSupported(ImageData.ACTION_PROMOTE) && transY < 0f) {
                     transY = 0f;
                 }
                 mViewInfo[hit].setTranslationY(transY, mScale);